IoC 详解 - Bean 的生命周期
- Bean 的实例化过程
1. Bean 的实例化和属性设置
在完成容器的启动阶段后,对于 BeanFactory 来说并不会马上实例化相应的 Bean 定义,此时容器仅仅拥有所有对象的 BeanDefinition 来保存实例化阶段将要用的必要信息。只有当请求方通过 BeanFactory 的 getBean() 方法 请求某个对象实例时,才会触发 Bean 实例化阶段的活动
BeanFactory 的 getBean()方法 可以被客户端对象显式调用,也可以在容器内部隐式的被调用
隐式调用的两种情况:- 对于 BeanFactory: 对象实例化通常采用延迟初始化方式,当
对象A
被请求而需要第一次实例化时,如果它依赖的对象B
没有被实例化过,容器会先对对象A
依赖的对象进行实例化,此时容器内部会首先实例化对象B
以及所有被对象A
依赖而还没有进行实例化的对象。(在容器内部调用 getBean(),对于请求方来说是隐式的) - 对于 ApplicationContext: 启动后会实例化所有的 bean 定义,但在实现的过程中仍然遵循 Spring 容器实现流程的两个阶段,只是会在启动阶段的活动完成之后,紧接着调用注册到该容器的所有 bean 定义的实例化方法。
- 对于 BeanFactory: 对象实例化通常采用延迟初始化方式,当
容器采用“策略模式(Strategy Pattern)”来决定采用什么方式初始化 bean实例,通常可以通过反射或者 CGLIB 动态字节码生成来初始化相应的 bean 实例 或者动态生成其子类
容器总不是直接通过 new 方式添加对象,而是通过 AOP 实现机制,创造了一个目标对象的代理对象(可以简单理解为目标对象的子类,要么具有相同功能,要么更加强大)
2. Aware 接口
- 在经过实例化和属性设置后,容器会检查当前对象实例是否实现了一系列的以 Aware 命名结尾的接口定义,如果是,则将这些 Aware 接口定义中规定的依赖注入给当前的对象实例
- Aware 接口种类:
- 对于 BeanFactory:
- org.springframework.beans.factory.BeanNameAware: 如果 Spring容器 检测到当前对象实例实现了该接口,会将该对象实例的bean定义对应的 beanName 设置到当前实例
- org.springframework.beans.factory.BeanClassLoaderAware: 如果检测到该接口实现,会将对应加载当前 bean 的 ClassLoader 注入当前实例,默认使用加载 org.springframework.util.ClassUtils 类的Classloader
- org.springframework.beans.factory.BeanFactoryAware: 如果检测到该接口实现,BeanFactory容器 会将自身设置到当前对象实例,这样当前对象实例就拥有了一个 BeanFactory容器 的引用,并且可以对这个容器内允许访问的对象进行访问
- 对于 ApplicationContext:
- org.springframework.context.ResourceLoaderAware: ApplicationContext 实现了 Spring 的 ResourceLoader接口。当检测到该接口实现,或将当前 ApplicationContext 自身设置到对象实例,同样使当前对象实例拥有了其所在 ApplicationContext容器 的引用
- org.springframework.context.ApplicationEventPublisherAware: ApplicationContext 作为一个容器,同时还实现了 ApplicationEventPublisher 接口,这样它就可以作为 ApplicationEventPublisher 使用。检测到该接口实现,会将自身注入当前对象实例
- org.springframework.context.MessageSourceAware: ApplicationContext 通过 MessageSource 接口提供国际化的信息支持(I18n,Internationalization)。接测到该接口实现,会将自身注入当前对象实例
- org.springframework.context.ApplicationContextAware: 将自身注入
- 对于 BeanFactory:
3. BeanPostProcessor
- 与 BeanFactoryPostProcessor 会处理容器内所有符合条件的 BeanDefinition 类似,BeanPostProcessor 会处理容器内所有符合条件的实例化后的对象实例
- BeanFactoryPostProcessor 在容器启动阶段,对象未创建之前对创建对象的 BeanDefinition 进行修改,而 BeanPostProcessor 通过 AOP 对一个已经生成的对象进行扩展
- ApplicationContext 对应的 Aware接口 实例上就是通过 BeanPostProcessor 的方式进行处理的,当 ApplicationContext 中每个对象的实例化过程走到 BeanPostProcessor前置处理 这一步时,容器会检测到之前注册到容器的 ApplicationContextAwareProcessor(BeanPostProcessor 的实现类),然后调用其中的 postProcessBeforeInitialization()方法,检查并设置相关依赖
- 将 BeanPostProcessor 注入到容器中:
- BeanFactory: 手动写代码注入
ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(...));
beanFactory.addBeanPostProcessor(new PasswordDecodePostProcessor()); - ApplicationContext: 通过配置文件
<beans>
<bean id="passwordDecodePostProcessor" class="package.name.PasswordDecodePostProcessor">
<!--如果需要,注入必要的依赖-->
</bean>
</beans>
- BeanFactory: 手动写代码注入
4. init-method
- init-method 可以指定我们在容器中获得的对象在执行任何方法前,先执行此方法(比如做任何事情前先洗手)
定义方式:<bean id="tradeDateCalculator" class="FXTradeDateCalculator"
init-method="setupHolidays">
5. destory-method
- 与 init-method 相对应,定义在这个对象被销毁前,需要做的方法