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 :
public interface Axe { public String chop(); }Person.java :
public interface Person { public void useAxe(); }SteelAxe.java :
public class SteelAxe implements Axe { @Override public String chop() { return "钢斧砍柴真快"; } public SteelAxe() { System.out.println("Spring实例化依赖bean:SteelAxe实例..."); } }Chinese.java :
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..."); } }bean.xml 核心配置:
<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(); } }运行Test.java,控制台输出:
从运行结果可以看出:依赖注入完成之后,程序先调用afterPropertiesSet方法,在调用init-method属性所指定的方法进行初始化。
如果某个Bean类实现了InitializingBean接口,当该Bean的所有依赖关系被设置完成后,Spring容器自动调用该Bean实例的afterPropertiesSet方法。其结果与采用init-method属性指定生命周期方法几乎一样。但是实现接口污染了代码,是侵入式设计,因此不推荐使用。