一、Bean生命周期大致流程
- Bean的实例化
- Bean的属性赋值
- Bean的初始化
- Bean的使用
- Bean的销毁
二、Bean生命周期详细执行流程
1. 实例化bean
- 根据配置情况调用构造方法或工厂方法实例化Bean。
- 如xml、properties、yaml、注解等配置方式
2. 设置Bean属性值
- 根据set方法、构造器或注解等对Bean设置属性值。
3. * 调用BeanNameAware的setBeanName()方法
- 如果Bean实现了
BeanNameAware接口,则Spring将调用Bean的setBeanName()方法传入当前Bean的 id值。 - BeanNameAware接口
public interface BeanNameAware extends Aware { void setBeanName(String name); } - 传入,not设值,aware意为
意识到,感知到,即实现该接口的Bean可以让Bean感知到/获取到其在Spring容器中的id属性值。
4. * 调用BeanFactoryAware的setBeanFactory()方法
- 如果Bean实现了
BeanFactoryAware接口的setBeanFactory()方法,则Spring将调用Bean的setBeanFactory()方法,传入当前 工厂实例的引用。 - BeanFactoryAware接口
public interface BeanFactoryAware extends Aware { void setBeanFactory(BeanFactory beanFactory) throws BeansException; } - 实现该接口的 Bean 可以在 Bean 加载的过程中获取到加载该 Bean 的 BeanFactory。
5. * 调用ApplicationContextAware的setApplicationContext()方法
- 如果Bean实现了
ApplicationContextAware接口的setApplicationContext()方法,则Spring传入当前 ApplicationContext实例的引用。 -
public interface ApplicationContextAware extends Aware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; } - 实现该接口的Bean可以获取到 Spring 的 ApplicationContext,从而能够获取任意 Bean 及大量 IOC 容器信息。
6. * 调用BeanPostProcessor的预初始化方法
- 如果
Bean和BeanPostProcessor相关联,则Spring将调用该接口的预初始化方法postProcessBeforeInitialization()对bean进行加工操作。这个非常重要,AOP就是用它实现的。 - BeanPostProcessor接口
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
7. * 调用InitializingBean接口的afterPropertiesSet()方法
- 如果Bean实现了
InitializingBean接口,则Spring将调用该接口的afterPropertiesSet()方法。 - InitializingBean接口
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
8. 调用自定义的初始化方法
- 如果在配置文件中通过
init-method属性指定了初始化方法,则调用该初始化方法。
9. * 调用BeanPostProcessor的后初始化方法
- 如果有
BeanPostProcessor和Bean相关联,则Spring将调用该接口的后初始化方法postProcessorAfterInitialization()方法。
10. Bean的使用
- 此时,就可以使用Bean了。
- 如果未指定/指定了Bean的生命周期为
singleton,则将该Bean放入Spring IOC的缓冲池中,交由Spring管理该Bean的生命周期。 - 如果指定了Bean的生命周期为
prototype,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11. Bean的销毁
(1)如果Bean实现了DisposableBean接口,则Spring将调用该接口的destory()方法将Spring中的Bean销毁。
- DisposableBean接口
public interface DisposableBean { void destroy() throws Exception; }
(2)如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法销毁Bean。
(3)如果同时存在(1)(2),则先调用(1)再调用(2)。
三、其他
1. 为什么要实现各种aware接口?
- Spring依赖注入的特点是
无感知的。也就是说所有的Bean对Spring容器的存在是无感知的,并不清楚容器的存在。我们如果需要使用到Spring容器中的一些资源,就要让Bean主动意识到容器的存在,才能获取到容器中的一些资源。 - BeanNameAware:获取容器中 Bean 的名称。
- BeanFactoryAware:获取当前 BeanFactory,以便调用容器的服务/资源。
- ApplicationContextAware:获取当前 ApplicationContext,以便调用容器的服务/资源。
2. 如果Bean实现了DisposableBean接口,也自定义了destory-method,那会执行两次desotry,销毁一次不就OK,两次销毁的意义?
- I don't know.
参考:
- JavaEE企业级应用开发教程:Spring+SpringMVC+MyBatis / 黑马程序员编著
- c.biancheng.net/spring/life…
- www.zhihu.com/zvideo/1435…