前言

测试下,spring bean 生命周期的几种回调函数,初始化方法,销毁方法

一、环境

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.26.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.26.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.26.RELEASE</version>
</dependency>
</dependencies>

二、代码测试

1、xml 配置 init destory

通过在xml配置bean的 init-method、destroy-method

public class Person {
private String name;
private String age;
// getter setter
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}

public void init() {
System.out.println("person init ~");
}

public void destroy() {
System.out.println("person destory ~");
}

}
<bean class="com.juststand.bean.model.Person" id="person" init-method="init" destroy-method="destroy">
<property name="age" value="10" ></property>
<property name="name" value="test" ></property>
</bean>
public class Test {

public static void main(String[] args) throws InterruptedException {

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("model.xml");
Person person = applicationContext.getBean("person", Person.class);
System.out.println(person);
Thread.sleep(2000);
applicationContext.destroy();
System.out.println("context destory");
}
}

结果

person init ~
Person{name=’test’, age=’10’}
person destory ~
context destory

2、注解

通过@PostConstruct、@PreDestroy

public class Student {
private String name;
private int level;
// getter setter
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", level=" + level +
'}';
}

@PostConstruct
public void init() {
System.out.println("student iniit");
}

@PreDestroy
public void destory() {
System.out.println("student destory");
}
}
// 注解配置需要开启才行
<context:annotation-config></context:annotation-config>
<bean class="com.juststand.bean.model.Student" id="student">
<property name="level" value="1" ></property>
<property name="name" value="test" ></property>
</bean>
public static void main(String[] args) throws InterruptedException {

ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("model.xml");
Student student = applicationContext.getBean("student", Student.class);
System.out.println(student.toString());
Thread.sleep(2000);
applicationContext.destroy();
System.out.println("context destory");
}

结果

student init
Student{name=’test’, level=1}
student destory
context destory

3、实现接口

bean 实行 InitializingBean 、DisposableBean 这两个接口

public class Zoo implements InitializingBean, DisposableBean {
private String name;
// getter setter
@Override
public String toString() {
return "Zoo{" +
"name='" + name + '\'' +
'}';
}

public void destroy() throws Exception {
System.out.println("zoo destory");
}

public void afterPropertiesSet() throws Exception {
System.out.println("zoo initing");
}
}
<bean class="com.juststand.bean.model.Zoo" id="zoo">
<property name="name" value="zoo"></property>
</bean>
public class Test {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("model.xml");
Zoo zoo = applicationContext.getBean("zoo", Zoo.class);
System.out.println(zoo.toString());
Thread.sleep(2000);
applicationContext.destroy();
System.out.println("context destory");
}
}

结果

zoo initing
Zoo{name=’zoo’}
zoo destory
context destory

三、注意事项

  • 初始化回调方法是在 属性赋值 set 方法之后调用
  • 如果三种都使用了且方法不同,执行顺序如下
    • @PostConstruct > InitializingBean.afterPropertiesSet() > init-method
    • @PreDestroy > DisposableBean.destroy() > destroy-init
// zoo初始化为例
// DefaultSingletonBeanRegistry.getSingleton() -> AbstractAutowireCapableBeanFactory.doCreateBean()进行实例化
try {
// 实例化完成
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 初始化 回调方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {

boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 具体初始化方法
((InitializingBean) bean).afterPropertiesSet();
}
}
}