Spring IOC容器
1.IOC及Bean容器
(1)接口及面向接口编程
1)接口
- 用于沟通的中介物的抽象化
- 实体把自己提供给外界的一种抽象化说明,用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式
- 对应Java接口即声明,声明了哪些方法是对外公开提供的
- 在Java8中,接口可以拥有方法体
2)面向接口编程
- 结构设计中,分清层次及调用关系,每层只向外(上层)提供一组功能接口,各层间仅依赖接口而非实现类
- 接口实现的变动不影响各层间的调用,这一点在公共服务中尤为重要
- “面向接口编程”中“接口”是用于隐藏具体实现和实现多态性的组件
(2)IOC概念
- IOC:控制反转。控制权的转移,应用程序本身不负责依赖对象的创建和维护,而是由外部容器负责创建和维护
- 控制反转是“获得依赖对象的过程被反转了”,获得依赖对象的过程由自身管理变为了由IOC容器主动注入
- DI(依赖注入Dependency Injection)是控制反转的一种实现方式
- 目的:创建对象并且组装对象之间的关系
- IOC类比于房屋中介
- 找中介 找IOC容器
- 中介介绍房子 容器创建返回对象
- 租房、入住 使用对象
- IOC容器中将所有的对象称为Bean
(3)Spring的Bean配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-init-method="init" default-destroy-method="destroy"> <bean id="接口名" class="接口实现类的全路径"></bean> </beans>
扩展:单元测试
- 下载junit-*.jar并引入工程
- 创建UnitTestBase类,完成对Spring配置文件的加载、销毁
- 所有的单元测试类都继承自UnitTestBase,通过它的getBean方法获取想要得到的对象
- 子类(具体执行单元测试的类)加注解:@RunWith(BlockJUnit4ClassRunner.class)
- 单元测试方法加注解:@Test
- 右键选择要执行的单元测试方法执行或者执行一个类的全部单元测试方法
(4)Bean的初始化
1)基础:两个包
- org.springframework.beans
- org.springframework.context
- BeanFactory提供配置结构和基本功能,加载并初始化Bean
- ApplicationContext保存了Bean对象并在Spring中被广泛使用
2)方式,ApplicationContext
- 本地文件
FileSystemXmlApplicationContext context=new FileSystemXmlApplicationContext("F:/workspace/appcontext.xml");
- ClassPath:相对工程路径
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring-context.xml");
- Web应用中依赖servlet或Listener
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>
2.Spring注入方式
(1)Spring注入的概念
- Spring注入是指在启动Spring容器加载bean配置的时候,完成对变量的赋值行为
(2)两种注入方式
- 设值注入
1)在InjectionServiceImpl类中生成setInjectionDAO方法
private InjectionDAO injectionDAO; public void setInjectionDAO(InjectionDAO injectionDAO){ this.injectionDAO=injectionDAO; }
2)spring-injection.xml文件
<beans ...> <!--声明两个bean,在IOC中初始化加载当前xml文件的时候创建这两个对象--> <bean id="injectionService" class="com.gc.ioc.injection.service.InjectionServiceImpl"> <!--在InjecionServiceImpl这个类中有名称为injectionDAO成员变量, 该成员变量的类型是InjectionDAOImpl(下面那个bean的class) ref 表示引用,该成员变量有个引用,它的id是injectionDAO(下面那个bean的id)--> <property name="injectionDAO" ref="injectionDAO"/> </bean> <!--injectionDAO代表InjectionDAOImpl这个类的一个实例,将这个实例赋值给property中的成员变量injectionDAO--> <bean id="injectionDAO" class="com.gc.injection.dao.InjectionDAOImpl"></bean> </beans>
3)测试类TestInjection.java
@RunWith(BlockJUnit4ClassRunner.class) public class TestInjection extends UnitTestBase { public TestInjection(){ super("classpath:spring-injection.xml"); } @Test public void testSetter(){ InjectionServer service=super.getBean(injectionService); service.save("数据"); } }
- 构造注入
1)在InjectionServiceImpl类中生成构造方法
private InjectionDAO injectionDAO; public InjectionServiceImpl(InjectionDAO injectionDAO){ this.injectionDAO=injectionDAO; }
2)spring-injection.xml文件
<beans ...> <bean id="injectionService" class="com.gc.ioc.injection.service.InjectionServiceImpl"> <!--constructor-arg 构造器的参数--> <constructor-arg name="injectionDAO" ref="injectionDAO"/> </bean> <bean id="injectionDAO" class="com.gc.injection.dao.InjectionDAOImpl"></bean> </beans>
3)测试类TestInjection.java
@RunWith(BlockJUnit4ClassRunner.class) public class TestInjection extends UnitTestBase { public TestInjection(){ super("classpath:spring-injection.xml"); } @Test public void testConstructor(){ InjectionServer service=super.getBean(injectionService); service.save("数据"); } }