Spring可以管理singleton作用域的bean生命周期。(无法管理protype类型的)
对于singleton的bean,管理bean的生命周期有以下两个时机:
(1)注入依赖关系后
(2)即将销毁bean之前
一、依赖关系注入之后的行为
有两种方式:
(1)使用init-method属性
(2)实现initializingBean接口
说明:方式(1)写普通方法init() (方法名任意),在xml中配置。代码污染小。
方式(2)实现initializingBean接口,并实现方法 void afterPropertiesSet() throws Exception。
实验1:init-method属性
public class SteelAxe implements Axe
{
public SteelAxe()
{
System.out.println("Spring实例化依赖bean:SteelAxe实例...");
}
public String chop()
{
return "钢斧砍柴真快";
}
}
public class Chinese implements Person , BeanNameAware, ApplicationContextAware
{
private Axe axe;
public void setBeanName(String beanName)
{
System.out.println("===setBeanName===");
}
public void setApplicationContext(ApplicationContext ctx)
{
System.out.println("===setApplicationContext===");
}
public Chinese()
{
System.out.println("Spring实例化主调bean:Chinese实例...");
}
// axe的setter方法
public void setAxe(Axe axe)
{
System.out.println("Spring调用setAxe()执行依赖注入...");
this.axe = axe;
}
public void useAxe()
{
System.out.println(axe.chop());
}
// 测试用的初始化方法
public void init()
{
System.out.println("正在执行初始化方法 init...");
}
}
xml:
<bean id="steelAxe" class="codeEETest.org.crazyit.app.service.impl.SteelAxe"/>
<!-- 配置chinese Bean,使用init-method="init"指定该Bean所有属性设置完成后,自动执行init方法 -->
<bean id="chinese" class="codeEETest.org.crazyit.app.service.impl.Chinese"
init-method="init">
<property name="axe" ref="steelAxe"/>
</bean>
Spring实例化依赖bean:SteelAxe实例... //xml中从上到下的bean,调用对应的构造方法
Spring实例化主调bean:Chinese实例... //同上
Spring调用setAxe()执行依赖注入... //setter方法
===setBeanName===
===setApplicationContext=== //这是两个通知
正在执行初始化方法 init... //这里才开始执行xml中配置的初始化
钢斧砍柴真快 //测试类中执行了p.useAxe();
实验2:initializingBean接口
public class Chinese implements Person,InitializingBean, BeanNameAware, ApplicationContextAware
{
private Axe axe;
public void setBeanName(String beanName)
{
System.out.println("===setBeanName===");
}
public void setApplicationContext(ApplicationContext ctx)
{
System.out.println("===setApplicationContext===");
}
public Chinese()
{
System.out.println("Spring实例化主调bean:Chinese实例...");
}
// axe的setter方法
public void setAxe(Axe axe)
{
System.out.println("Spring调用setAxe()执行依赖注入...");
this.axe = axe;
}
public void useAxe()
{
System.out.println(axe.chop());
}
// 测试用的初始化方法
public void init()
{
System.out.println("正在执行初始化方法 init...");
}
// 实现InitializingBean接口必须实现的方法
@Override
public void afterPropertiesSet() throws Exception
{
System.out.println("正在执行初始化方法 afterPropertiesSet...");
}
}
Spring实例化依赖bean:SteelAxe实例...
Spring实例化主调bean:Chinese实例...
Spring调用setAxe()执行依赖注入...
===setBeanName===
===setApplicationContext===
正在执行初始化方法 afterPropertiesSet... //在init-method属性前执行
正在执行初始化方法 init...
钢斧砍柴真快
不推荐使用initializingBean接口的方式,污染代码。如果二者同时出现,先执行initializingBena接口。
二、Bean销毁之前
两种方式:
(1)destroy-method属性
(2)DisposableBean接口
说明:方式(1):代码污染小
方式(2):实现destroy()方法
package org.crazyit.app.service;
public interface Person
{
public void useAxe();
}
package org.crazyit.app.service;
public interface Axe
{
public String chop();
}
package org.crazyit.app.service.impl;
import org.springframework.beans.factory.DisposableBean;
import org.crazyit.app.service.*;
public class Chinese implements Person,DisposableBean
{
private Axe axe;
public Chinese()
{
System.out.println("Spring实例化主调bean:Chinese实例...");
}
public void setAxe(Axe axe)
{
System.out.println("Spring执行依赖关系注入...");
this.axe = axe;
}
public void useAxe()
{
System.out.println(axe.chop());
}
//方式1:普通的close()方法,方法名是任意的
public void close()
{
System.out.println("正在执行销毁之前的方法 close...");
}
//方式2:接口
public void destroy() throws Exception
{
System.out.println("正在执行销毁之前的方法 destroy...");
}
}
package org.crazyit.app.service.impl;
import org.crazyit.app.service.*;
public class SteelAxe implements Axe
{
public SteelAxe()
{
System.out.println("Spring实例化依赖bean:SteelAxe实例...");
}
public String chop()
{
return "钢斧砍柴真快";
}
}
public class BeanTest
{
public static void main(String[] args)
{
// 以CLASSPATH路径下的配置文件创建ApplicationContext
AbstractApplicationContext ctx = new
ClassPathXmlApplicationContext("beans.xml");
// 获取容器中的Bean实例
Person p = ctx.getBean("chinese" , Person.class);
p.useAxe();
// 为Spring容器注册关闭钩子
ctx.registerShutdownHook();
}
}
<bean id="steelAxe" class="org.crazyit.app.service.impl.SteelAxe"/>
<!-- 配置chinese Bean,使用destroy-method="close"
指定该Bean实例被销毁之前,Spring会自动执行指定该Bean的close方法 -->
<bean id="chinese" class="org.crazyit.app.service.impl.Chinese"
destroy-method="close">
<property name="axe" ref="steelAxe"/>
</bean>
说明:ctx.registerShutdownHook()是为了在JVM里注册关闭钩子(shutdown hook),保证spring容器恰当关闭,执行singleton的析构方法。没有这个将无法看到销毁的执行。
Spring实例化依赖bean:SteelAxe实例...
Spring实例化主调bean:Chinese实例...
Spring执行依赖关系注入...
钢斧砍柴真快
正在执行销毁之前的方法 destroy...
正在执行销毁之前的方法 close...