Spring可以管理 singleton作用域 Bean的生命周期,Spring可以精确地知道该Bean何时被创建、何时被初始化完成、容器何时准备销毁该Bean实例。
对于 prototype作用域 的Bean,Spring容器仅仅负责创建,当容器创建了Bean实例之后,Bean实例完全交给客户端代码管理,容器不再跟踪其生命周期。
每次客户端请求prototype作用域的Bean时,Spring都会产生一个新的实例,Spring容器无从知道它曾经创建了多少个prototype作用域Bean,也无从知道这些prototype作用域Bean什么时候会被销毁。
对于singleton作用域的Bean,每次客户端代码请求时都返回同一个共享实例,客户端代码不能控制Bean的销毁,Spring容器可以跟踪Bean实例的产生、销毁。容器可以在创建Bean之后,进行某些通用资源的申请;还可以在销毁Bean实例之前,先回收某些资源,比如数据库连接。
对于singleton作用域的Bean,Spring容器知道Bean何时实例化结束、何时销毁,Spring可以管理实例化结束之后和销毁之前的行为。管理Bean的生命周期行为主要有如下两个时机:
① 注入依赖关系之后。
② 即将销毁Bean之前。
依赖关系注入之后的行为:
Spring提供两种方式在Bean全部属性设置成功后执行特定行为:
⑴ 使用 init-method 属性
使用init-method属性指定某个方法应在Bean全部依赖关系设置结束后自动执行,使用这种方法不需将代码与Spring的接口耦合在一起,代码污染小。
⑵ 实现 InitializingBean 接口
该接口提供一个方法,void afterPropertiesSet( )throws Exception。Spring容器会在为该Bean注入依赖关系之后,接下来会调用该Bean所实现的afetrPropertiesSet( )方法。
Axe.java :
Person.java :
- public interface Axe {
- public String chop();
- }
SteelAxe.java :
- public interface Person {
- public void useAxe();
- }
Chinese.java :
- public class SteelAxe implements Axe {
- @Override
- public String chop() {
- return "钢斧砍柴真快";
- }
- public SteelAxe() {
- System.out.println("Spring实例化依赖bean:SteelAxe实例...");
- }
- }
bean.xml 核心配置:
- public class Chinese implements Person,InitializingBean {
- private Axe axe;
- public Chinese() {
- System.out.println("Spring实例化主调Bean:Chinese实例...");
- }
- public void setAxe(Axe axe) {
- System.out.println("Spring执行依赖关系注入...");
- this.axe = axe;
- }
- @Override
- public void useAxe() {
- System.out.println(axe.chop());
- }
- public void init(){
- System.out.println("正在执行初始化方法init...");
- }
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("正在执行初始化方法afterPropertiesSet...");
- }
- }
Test.java :
- <bean id="chinese" class="com.bean.Chinese" init-method="init">
- <property name="axe" ref="steelAxe"></property>
- </bean>
- <bean id="steelAxe" class="com.bean.SteelAxe"/>
运行Test.java,控制台输出:
- public class Test {
- public static void main(String[] args) {
- ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
- Person p=(Person) ctx.getBean("chinese");
- p.useAxe();
- }
- }
从运行结果可以看出:依赖注入完成之后,程序先调用afterPropertiesSet方法,在调用init-method属性所指定的方法进行初始化。
如果某个Bean类实现了InitializingBean接口,当该Bean的所有依赖关系被设置完成后,Spring容器自动调用该Bean实例的afterPropertiesSet方法。其结果与采用init-method属性指定生命周期方法几乎一样。但是实现接口污染了代码,是侵入式设计,因此不推荐使用。