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 各阶段具体接口和方法
下面先以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生命周期接口方法的生命周期。
如上述代码中的注释所示,BeanLifecycle这个Bean的生命周期将按照序号1~8顺序执行。下面是对BeanLifecycle准备的测试代码:
这段测试代码很简单,就是通过从Spring IoC容器中注入的BeanLifecycle对象,调用其sayHello()方法。测试代码运行后的结果如图2-11所示。
图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所示。
图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所示。
图2-13 BeanPostProcessor相关类图
如图2-13所示,InstantiationAwareBeanPostProcessorAdapter最终实现了BeanPostProcessor这个顶级接口。下面以InstantiationAwareBeanPostProcessorAdapter为例,讲解容器级生命周期接口方法的执行时序。下面代码将通过ContainerLifecycle类继承InstantiationAwareBean-PostProcessorAdapter来阐述容器级生命周期接口方法的执行时序,具体代码如下:
如上代码段所示,ContainerLifecycle类继承了InstantiationAwareBeanPostProcessorAdapter,重写了其中postProcessBeforeInstantiation、postProcessPropertyValues和postProcessAfterInitialization方法。其执行顺序如下。
• ContainerLifecycle:构造器最先执行。
• postProcessBeforeInstantiation:接口方法和实例化Bean之前调用。
• postProcessPropertyValues:设置某个属性时调用。
• postProcessAfterInitialization:接口方法和实例化Bean之后调用。
测试代码中,还是以上例的BeanLifecycle类为例,调用BeanLifecycle类的sayHello()方法,测试代码如下:
运行单元测试,测试结果如图2-14所示。
下面将介绍的是工厂级生命周期接口方法,工厂级生命周期接口方法涉及到的有BeanFactoryPostProcessor接口。下面将通过实现BeanFactoryPostProcessor接口来分析。
图2-14 容器级生命周期接口方法结果
工厂级生命周期接口的生命周期,实现代码如下:
测试代码将所有级别生命周期接口进行统一测试,以方便观察完整的Bean生命周期的执行时序:
测试效果图如图2-15所示。
图2-15 完整的生命周期执行顺序