荐 Spring 系列——Bean生命周期
上篇文章《Spring 系列——IOC容器初始化》中我们介绍了Spring IOC容器初始化的过程,主要过程分为三个步骤:
- 解析配置文件,组装成
BeanDefinition
对象 - 将
BeanDefinition
注册到容器中 - 对单例非懒加载Bean进行实例化
容器初始化完毕后,我们就能通过getBean()
方法从容器中获取Bean实例。
对于单例非懒加载的Bean,容器在第三步中已经进行了实例化,getBean
直接能取到实例对象
对于其他Bean,容器还未进行实例化,getBean()
方法会先实例化Bean,然后再返回实例对象。本篇文章就对Bean在容器中的生命周期进行介绍。
注意:Spring容器只负责管理单例Bean(scope=singleton)的生命周期;对于多例Bean(scope=prototype),只负责创建,交给使用者之后就不会管理其生命周期
如果文章中有描述错误或者不合理的地方,欢迎指正!
开门见山
废话不多说,直接上图,让我们从宏观的视角去感受一下Bean
在容器里发生了什么
从上图中,我们看到Spring 容器中 Bean从创建到销毁,有5个主干流程:
- 构造 Bean 对象
- 设置 Bean 属性
- 初始化回调
- Bean 调用
- 销毁 Bean
左侧图例标识了关键源码的位置,方便大家自己去看源码,下面是对源码关键代码的说明
-
createBeanInstance
:通过反射API创建Bean对象 -
populateBean
:如果Bean有依赖属性,则会设置属性;如果是依赖对象,则会先实例化依赖的对象 -
initializeBean
:Bean初始化回调-
invokeAwareMethods
:调用实现了*Aware
接口中的方法- 如果Bean实现了
BeanNameAware
接口,调用setBeanName
设置Bean的名称 - 如果Bean实现了
BeanClassLoaderAware
,调用setBeanClassLoader
设置Bean的类加载器 - 如果Bean实现了
BeanFactoryAware
,调用setBeanFactory
设置Bean的容器
- 如果Bean实现了
-
applyBeanPostProcessorsBeforeInitialization
:初始化前置增强,如果注册了BeanPostProcessor
,调用postProcessBeforeInitialization
,在Bean初始化前执行 -
invokeInitMethods
:调用初始化方法- 如果Bean实现了
InitializingBean
接口,调用afterPropertiesSet
,执行初始化 - 如果配置文件中Bean定义包含了
init-method
属性,则调用相应的方法
- 如果Bean实现了
-
applyBeanPostProcessorsAfterInitialization
:初始化后置增强,如果注册了BeanPostProcessor
,调用postProcessAfterInitialization
,在Bean初始化后执行
-
- Bean初始化完成,可以被调用
- 销毁Bean
- 如果Bean实现了
DisposableBean
接口,当容器不再需要Bean引用时,执行destory
销毁Bean - 如果配置文件中Bean定义包含了
destory-method
属性,则调用相应的方法
- 如果Bean实现了
小试牛刀
下面我们通过一个Demo来演示一下Bean完整的生命周期,加深大家的印象
- 我们定义一个
LifeService
类,实现下面6个接口:BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
、InitializingBean
、DisposableBean
、ApplicationContextAware
接口;同时自定义init-method
和destory-method
方法。如果不了解这几个接口,大家可以去阅读源码了解一下,这里就不展开了
public class LifeService implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware,
InitializingBean, DisposableBean, ApplicationContextAware {
private String name;
public void setName(String name) {
System.out.println("设置属性");
this.name = name;
}
public LifeService() {
System.out.println("构造方法");
}
public void myInit(){
System.out.println("init-method自定义初始化方法");
}
public void myDestory(){
System.out.println("destroy-method自定义销毁方法");
}
public void printMessage(){
System.out.println("======执行业务逻辑 printMessage=====");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory");
}
@Override
public void setBeanName(String name) {
System.out.println("setBeanName");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化init afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext");
}
}
- 定义一个
MyBeanPostProcessor
实现BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Before postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("After postProcessAfterInitialization");
return bean;
}
}
- 配置xml配置文件,指定init-method和destroy-method属性
<bean id="lifeService" class="com.dev.domain.LifeService" init-method="myInit" destroy-method="myDestory">
<property name="name" value="muskmelon"/>
</bean>
<!--自定义后置处理器-->
<bean id="postProcessor" class="com.dev.domain.MyBeanPostProcessor"/>
- 启动容器,执行业务逻辑,销毁容器
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
LifeService lifeService = (LifeService) context.getBean("lifeService");
lifeService.printMessage();
((ClassPathXmlApplicationContext) context).close();
}
=======执行结果=======
构造方法
设置属性,name=muskmelon
setBeanName
setBeanClassLoader
setBeanFactory
setApplicationContext
Before postProcessBeforeInitialization
初始化init afterPropertiesSet
init-method自定义初始化方法
After postProcessAfterInitialization
======执行业务逻辑 printMessage=====
destroy
destroy-method自定义销毁方法
可以看到执行结果和我们描述的基本一致,我们前面说了BeanPostProcessor
是在Bean生命周期中的调用执行,但是它是什么时候注册到容器中的呢?我们就得翻出讲IOC容器初始化的这篇文章了,详细请看《Spring 系列——IOC容器初始化》
庖丁解牛
我们直接看refresh
方法的源码吧
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
// 【看这里】注册BeanPostProcessor的实现类
// 接口提供两个方法:postProcessBeforeInitialization 和 postProcessAfterInitialization
// 这两个方法分别在初始化前后执行
registerBeanPostProcessors(beanFactory);
//下面的省略
......
}
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 1.获取容器中继承了BeanPostProcessor接口的子类的beanName集合
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 注册BeanPostProcessorChecker,用于校验一个Bean在实例化的过程中,能成功的执行所有的BeanPostProcessor后置处理,如果有一个失败,则会打印相关日志
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 2.将BeanPostProcessor根据实现的排序接口分类,分为3类:PriorityOrdered,Ordered,nonOrdered
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 3. 注册 priorityOrderedPostProcessors
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 4.注册 orderedPostProcessors
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
// 5.注册 nonOrderedPostProcessors
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 6.注册 internalPostProcessors
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 7.注册ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
我们看到registerBeanPostProcessors
方法的作用就是将BeanPostProcessor
注册到容器。细心的读者可能看到我们的示例代码中还实现了一个ApplicationContextAware
接口,其实这是在ApplicationContextAwareProcessor
处理器中执行的,这也是BeanPostProcessor
的子类,但是上面源码中注册了众多的BeanPostProcessor
,并没有对ApplicationContextAwareProcessor
进行注册,那它是在哪里注册的呢?
其实也是在容器初始化的过程中进行注册的,我们看refresh
方法的prepareBeanFactory
方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// ...省略
// 【看这里】
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// ....省略
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// ...省略
}
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))
注册了容器上下文的增强处理器,除了对实现ApplicationContextAware
接口的Bean进行处理,如果Bean还实现了以下接口也会进行调用:EnvironmentAware
、EmbeddedValueResolverAware
、ResourceLoaderAware
、ApplicationEventPublisherAware
、MessageSourceAware
,具体的用途就不展开了,有兴趣的读者可以自行查阅资料。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
抛砖引玉
上面我们讲述的都是ApplicationContext中Bean的生命周期,那么BeanFactory中Bean的生命周期是否有什么不同呢?
示例代码仍然使用上面的,贴一下使用BeanFactory来注册Bean的代码
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("spring.xml"));
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
LifeService lifeService2 = (LifeService)beanFactory.getBean("lifeService");
lifeService2.printMessage();
beanFactory.destroySingletons();
}
=======执行结果=======
构造方法
设置属性
setBeanName
setBeanClassLoader
setBeanFactory
Before postProcessBeforeInitialization
初始化init afterPropertiesSet
init-method自定义初始化方法
After postProcessAfterInitialization
======执行业务逻辑 printMessage=====
destroy
destroy-method自定义销毁方法
对比上面的结果,我们看到执行代码中BeanPostProcessor
是通过手动注册,执行结果中没有输出setApplicationContext
,这是为什么呢?
在了解Spring IOC容器初始化的流程后,我们知道ApplicationContext
是BeanFactory的子类,它在初始化的过程中(refresh
方法),除了读取配置文件,解析成BeanDefinition
,并注册到容器中之外,还做了诸多用于扩展Bean的功能,比如:注册BeanPostProcessor
,实例化单例非懒加载Bean,注册BeanFactoryPostProcessor
等等,不清楚的可以再回过头去看看容器初始化的流程,温故而知新。
BeanFactory
是Spring容器最顶端的接口类,提供了配置框架和基础功能,ApplicationContext
添加了更多企业级功能。所以像BeanPostProcessor
诸如此类的功能就需要我们自己手动配置,没有注册过ApplicationContextAwareProcessor
,就自然不会打印setApplicationContext
。
综上所述
至此,Spring Bean生命周期的流程我们讲完了,我们来一起总结以下:
- Spring 容器只管理单例Bean的生命周期,prototype类型的Bean创建完成后,其生命周期就丢给使用者自己处理(一般就是通过GC进行回收了)
- Bean生命周期关键步骤:创建Bean对象,设置Bean属性,初始化回调,调用Bean,销毁Bean
- Spring 容器中通过注册
BeanPostProcessor
,在Bean初始化前后,对Bean实例进行特殊处理;我们也可以通过自定义BeanPostProcessor
来实现Bean的扩展功能 -
ApplicationContext
中Bean的生命周期和BeanFactory
中Bean的生命周期区别
(1)BeanFactory
容器中不会调用setApplicationContext
方法
(2)BeanFactory
容器中BeanPostProcessor
需要手动注册
(3)BeanFactory
容器启动时不会去实例化所有Bean,包括单例非懒加载的bean,而是在调用的时候去实例化。
本文地址:https://blog.csdn.net/czxlylc/article/details/107104197
上一篇: 网上书城(权限管理)
下一篇: 荐 我的 java 入门进阶之路 (七)