共计 2824 个字符,预计需要花费 8 分钟才能阅读完成。
1 IoC
与DI
IoC
是 Inversion of Control
的简称,也就是管制反转。通常来说,创建对象须要调用者手动创立,也就是 new XXX()
的形式。当 Spring
框架呈现后,对象的实例不再由调用者创立,而是由 Spring
容器创立,这样控制权就由调用者转移到 Spring
容器,控制权产生了反转,这就是 Spring
的管制反转。从 Spring
容器来看,Spring
容器负责将被依赖对象赋值给调用者的成员变量,相当于为调用者注入它所依赖的实例,这就是 Spring
的依赖注入(Dependency Injection
,DI
)。
一句话总结:
IoC
:控制权由调用者交由Spring
容器,管制产生了反转DI
:由Spring
容器注入须要的值到对象中
2 Spring IoC
容器
Spring
中实现 IoC
的是 Spring IoC
容器,次要基于以下两个接口:
BeanFactory
ApplicationContext
2.1 BeanFactory
位于 org.springframework.beans.factory
下,提供了残缺的 IoC
服务反对,是一个治理 Bean
工厂,次要负责初始化各种 Bean
。能够通过XmlBeanFactory
来获取 XML
文件中的 Bean
并进行拆卸,例子如下:
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("/xxx/xxx/xxx/xxx/applicationContext.xml"));
TestInterface test = (TestInterface)factory.getBean("test");
test.hello();
须要应用绝对路径,而且,该办法曾经过期了:
因而不举荐应用。
2.2 ApplicationContext
ApplicationContext
是 BeanFactory
的子接口,也称为利用上下文,除了蕴含 BeanFactory
的性能外还增加了国际化、资源拜访、事件流传等的反对,创立 ApplicationContext
的实例有以下三种办法:
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
Web
服务器实例化
2.2.1 ClassPathXmlApplicationContext
该类从 resources
下寻找指定的 XML
文件:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
TestInterface test = (TestInterface)context.getBean("test");
test.hello();
2.2.2 FileSystemXmlApplicationContext
该类读取配置文件须要加上前缀:
classpath:
:该前缀示意从类门路读取,对于Maven
我的项目来说就是resources
file:
:该前缀示意从绝对路径获取
例子:
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
//ApplicationContext context = new FileSystemXmlApplicationContext("file:/xxx/xxx/xxx/xxxx/xxx/applicationContext.xml");
2.2.3 Web
服务器实例化
个别应用基于 ContextLoaderListener
的实现形式,批改web.xml
,增加如下代码:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</context-param>
3 DI
的两种办法
DI
通常有两种实现形式:
- 构造方法注入
setter
注入
上面别离来看一下。
3.1 构造方法注入
Spring
能够利用反射机制通过构造方法实现注入,比方有以下三个类:
public interface TestInterface {void hello();
}
public class TestA implements TestInterface {
@Override
public void hello() {System.out.println("Test A");
}
}
public class TestB {
private TestInterface test;
public TestB(TestInterface test)
{this.test = test;}
public void method()
{test.hello();
}
}
TestInterface
是一个简略的接口,而 TestA
实现了该接口,TestB
须要一个 TestInterface
类型的对象,因而能够先注入一个 TestA
,再将该TestA
注入到 TestB
的构造方法中:
<bean id="testA" class="TestA"/> <!-- 注入一个 TestA 对象 -->
<bean id="testB" class="TestB">
<constructor-arg index="0" ref="testA" /> <!-- 将下面注入的 TestA 作为参数传入构造方法中,在传给 TestB 的公有成员 -->
</bean>
constructor-arg
是用于定义通过构造方法的形式进行注入的标签,index
定义地位,从 0
开始,ref
是某个 Bean
的援用,值为该 Bean
的id
。
3.2 通过 setter
注入
在下面的例子中,批改 TestB
如下:
public class TestB {
private TestInterface test;
public void setTest(TestInterface test) {this.test = test;}
public void method()
{test.hello();
}
}
其实就是增加了一个setter
,接着批改配置文件:
<bean id="testA" class="TestA"/>
<bean id="testB" class="TestB">
<property name="test" ref="testA" />
</bean>
<property>
示意通过 setter
注入,name
是公有成员的名字,ref
是被传入 setter
的Bean
的 id
值。