- Spring 5企业级开发实战
- 周冠亚 黄文毅
- 1422字
- 2021-04-02 00:56:54
2.4 Spring IoC容器中Bean的生命周期
Spring IoC容器管理的Bean默认都是单利设计模式的(参见本书附录),即每个Bean只有一个实例化的Bean对象存在于Spring IoC容器中,因此Spring IoC容器需要负责管理Bean的产生、使用和销毁等生命周期。
Spring IoC容器中的Bean的生命周期可以分为以下4类:
• Bean自身方法。
• Bean生命周期接口方法。
• 容器级生命周期接口方法。
• 工厂后处理器接口方法。
各个阶段涉及的具体接口和方法如表2-1所示。
表2-1 各阶段具体接口和方法
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-T59_94589.jpg?sign=1739628214-6Hu75W53kzE8Y6xdojz7Nw3A0j3Q7K56-0-9b4050db5e238225819d2db12243942c)
下面先以Bean自身方法和Bean生命周期接口方法为例,演示其各个生命周期的执行时序。
• init-method:指定某个方法在Bean实例化完成,依赖关系设置结束后执行。
• destroy-method:指定某个方法在Bean销毁之前被执行。
• InitializingBean接口:指定在Bean实例化完成,依赖关系设置结束后执行(在init-method之前执行)。
• DiposableBean接口:指定某个方法在Bean销毁之前被执行(在destory-method之前执行)。
• ApplicationContextAware接口:在实例化Bean时,为Bean注入ApplicationContext。
• BeanNameAware接口:在实例化Bean时,为Bean注入beanName。
以下代码BeanLifecycle将实现上述4个接口InitializingBean、DiposableBean、ApplicationContextAware和BeanNameAware,并通过在XML文件中配置该Bean的init-method和destroy-method。通过BeanLifecycle例子将可以更加清晰地阐述Bean自身方法和Bean生命周期接口方法的生命周期。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P60_94593.jpg?sign=1739628214-VVXRbIA5k3n2p1RzuyscecU7knvBtKmj-0-2977728b48bf2456d9a8d3f890329d4a)
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P61_94594.jpg?sign=1739628214-RuG2Zr1IKU9f0ogWRyxjrUcLIjA3QQ2G-0-a2b30dd3439738cf0f6d1bead922316a)
如上述代码中的注释所示,BeanLifecycle这个Bean的生命周期将按照序号1~8顺序执行。下面是对BeanLifecycle准备的测试代码:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P61_94596.jpg?sign=1739628214-7zG6vInHTZ5HAaE2azsPI3SlrGE4BaVx-0-18396ace469baffa71f648feaca0a08d)
这段测试代码很简单,就是通过从Spring IoC容器中注入的BeanLifecycle对象,调用其sayHello()方法。测试代码运行后的结果如图2-11所示。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P62_25369.jpg?sign=1739628214-VPThoAXO1xDcBWzUW3bDDahI7l9R0cjD-0-ee9e4ebadb5d5b3ed4ab217aa40060b5)
图2-11 Bean自身方法和Bean生命周期接口方法生命周期测试图
通过执行结果可以得到Bean自身方法和Bean生命周期接口方法的执行时序:
(1)执行构造器。
(2)执行BeanNameAware接口的setBeanName(String name)方法。
(3)执行ApplicationContextAware接口的setApplicationContext(ApplicationContextapplication Context)方法。
(4)执行InitializingBean接口的afterPropertiesSet()方法。
(5)执行init-method指定的方法。
(6)执行运行时Bean中的业务方法。
(7)执行DisposableBean接口的destroy()方法。
(8)执行destroy-method指定的方法。
Bean自身方法和Bean生命周期接口方法执行的生命周期时序图如图2-12所示。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P62_94601.jpg?sign=1739628214-G9lmh5JBawgfaByToWTGUl2vnaEIvr7N-0-ccf2c3181c25fd013f8b8ed55aac7c26)
图2-12 Bean自身方法和Bean生命周期接口方法生命周期时序图
下面将介绍容器级生命周期接口方法的执行时序。容器级生命周期接口方法有InstantiationAwareBeanPostProcessor和BeanPostProcessor这两个接口,一般也将其实现类称为后处理器。容器级生命周期接口的实现独立于Spring IoC容器中的Bean,其是以容器扩展的形式注册到Spring中的。无论Spring IoC管理任何的Bean,这些后处理器都会发生作用。因此后处理器影响范围是全局的Spring IoC容器中的Bean。用户可以通过编写合理的后处理器来实现感兴趣的Bean加工处理逻辑。
• BeanPostProcessor接口:此接口的方法可以对Bean的属性进行更改。
• InstantiationAwareBeanPostProcessor接口:此接口可以在Bean实例化前、Bean实例化后分别进行操作,也可以对Bean实例化之后进行属性操作(为BeanPostProcessor的子接口)。
• InstantiationAwareBeanPostProcessorAdapter:适配器类。
BeanPostProcessor、InstantiationAwareBeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter三者的关系如图2-13所示。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P63_25387.jpg?sign=1739628214-wEj7Lu7gAgTHrS76pkkzVTW5r13aByGe-0-a15083b6d2e7cdbe3506324d5725b08c)
图2-13 BeanPostProcessor相关类图
如图2-13所示,InstantiationAwareBeanPostProcessorAdapter最终实现了BeanPostProcessor这个顶级接口。下面以InstantiationAwareBeanPostProcessorAdapter为例,讲解容器级生命周期接口方法的执行时序。下面代码将通过ContainerLifecycle类继承InstantiationAwareBean-PostProcessorAdapter来阐述容器级生命周期接口方法的执行时序,具体代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P63_94604.jpg?sign=1739628214-Icx9b9iNakJ59O8d5LNvybTumbfbdp5y-0-a2218831acd66189f763dbe893fa7983)
如上代码段所示,ContainerLifecycle类继承了InstantiationAwareBeanPostProcessorAdapter,重写了其中postProcessBeforeInstantiation、postProcessPropertyValues和postProcessAfterInitialization方法。其执行顺序如下。
• ContainerLifecycle:构造器最先执行。
• postProcessBeforeInstantiation:接口方法和实例化Bean之前调用。
• postProcessPropertyValues:设置某个属性时调用。
• postProcessAfterInitialization:接口方法和实例化Bean之后调用。
测试代码中,还是以上例的BeanLifecycle类为例,调用BeanLifecycle类的sayHello()方法,测试代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P65_94610.jpg?sign=1739628214-N2pf6BZANna7Bvqbzs6xjKgx870QgFPu-0-11ca534318e911ee847ce4d4788a981c)
运行单元测试,测试结果如图2-14所示。
下面将介绍的是工厂级生命周期接口方法,工厂级生命周期接口方法涉及到的有BeanFactoryPostProcessor接口。下面将通过实现BeanFactoryPostProcessor接口来分析。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P66_25840.jpg?sign=1739628214-fHTzE5sDMaPKm5OFqsxQupeSQjyNV8Jg-0-a5539fc5c440f6fded5a48229fd87473)
图2-14 容器级生命周期接口方法结果
工厂级生命周期接口的生命周期,实现代码如下:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P66_94611.jpg?sign=1739628214-aGE6naDPQzwBnnvmXS7U3LErnpurs67d-0-6f786abe6aab32abe55f58fd885ca99d)
测试代码将所有级别生命周期接口进行统一测试,以方便观察完整的Bean生命周期的执行时序:
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P66_94612.jpg?sign=1739628214-CPQR0B8E2UUUFSVpImMgMjN1Fp2nA9zz-0-675c3600232ed06cf1e23b403e96c569)
测试效果图如图2-15所示。
![](https://epubservercos.yuewen.com/45D01C/15056703904176006/epubprivate/OEBPS/Images/Figure-P67_26093.jpg?sign=1739628214-4OZh3BSu25VdSTeV0KmczIufi0LRjvlK-0-f06028f123f2666f108226551c29cc25)
图2-15 完整的生命周期执行顺序