IoC
当我们的类中依赖其他类或服务的时候,最简单的方式就是在类的构造器中新建其他的依赖类
public Provider() {
Listener listener = new Listener();
}
这样的实质是我们主动去获取想要的对象。而依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。IoC provider统一管理所有的被注入对象和依赖对象。控制从业务逻辑中直接转移到了IoC provider中。
那什么时候会触发依赖注入呢?
- 通过getBean()方法获取Bean对象。
- 给Bean配置了懒加载,ApplicationContext启动完成后调用getBean()来实例化对象。(现在计算机性能已经足够,不是特殊要求下尽量别做懒加载,这样的话可以减少web运行时的调用时间开销。)
依赖注入的方式有三种:构造方法注入,被注入对象在构造方法中声明依赖参数的参数列表,让IoC provider知道它需要哪些依赖。缺点是对象一多,不好维护。
public Provider(Listener listener) {
this.listener = listener;
}
setter方法注入。当前对象为其依赖对象的setter方法,就可以通过setter方法将相应的依赖对象注入到被注入对象中。(缺点是在对象构造之后注入,无法马上就绪)
public Provider() {
private Listener listener;
public setListener(Listener listener) {
this.listener = listener;
}
}
接口方式,声明IoC对应的接口,带有侵入性。
IoC在spring中的实现
IoC provider的职责相对比较简单:业务对象的构建管理和业务对象间的依赖绑定。IoC provider需要记录依赖关系,可以通过以下方式记录:
直接编码方式:
IoCContainer container = "";
container.register(Provider.class, new Listener());
配置文件的方式,可以通过getBean等方法读取xml文件
<bean id = "Provider" class="xx.xx.Provider">
<property name = "Listener">
<ref bean = "xxListener">
</property>
</bean>
spring提供了两种容器类型: BeanFactory和ApplicationContext。
ApplicationContext继承自BeanFactory,拥有更多功能。BeanFactory是生产bean的工厂
public interface BeanFactory {
Object getBean()...
}
BeanFactory主要提供了一些查询bean状态的方法,如getBean。
beans是xml配置中最顶层的元素,它拥有相应的属性来对所辖的bean进行统一的默认行为设置。如果继承的类中也需要注入,可以通过parent属性进行声明。bean的scope用来声明容器中所应处的限定条件和存活时间。
IoC provider在容器启动伊始,会读取xml中的配置,将信息组装成BeanDefinition,注册到相应的BeanDefinitionRegistry。在某个请求需要实例化对象A,这时候如果对象A依赖的对象B还没有实例化,容器会先调用getBean方法实例化B。getBean方法会检查请求的对象是否初始化,如果没有,会根据BeanDefinition所提供的信息实例化对象,并为其注入依赖。
注解方式
如果采用注解方式,<context:component-scan />
会到指定的路径下扫描标有@Component的类,如果找到,则加到IoC provider容器中进行管理。默认情况下,这个方式只会扫描@Component,@Repository,@Service以及@Controller。