文章目录
1、总结
其中,@PostConstruct
的调用与 BeanPostProcessor
相关。
强调:
需要根据应用的需求做出合适的决定:
- 当需要考虑可移植性问题时,使用方法回调
- 需要减少配置量时,可以使用DisposableBean接口
- (书上没写注解的应用场景,注解似乎适合以上两种需求)
2、测试
测试类:A
package book.chapter4;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class A implements InitializingBean , DisposableBean {
public A() {
System.out.println("1. construct ... ");
}
private String a ;
public String getA() {
return a;
}
public void setA(String a) {
System.out.println("2. setting ... ");
this.a = a;
}
@PostConstruct
public void postConstruct() {
System.out.println("3. postConstruct ... ");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4. afterPropertiesSet.afterPropertiesSet() ... ");
}
public void init() {
System.out.println("5. init-method ... ");
}
public void doSomething() {
System.out.println("-------------- do something ... ");
}
@PreDestroy
public void PreDestroy() {
System.out.println("1. PreDestroy ... ");
}
@Override
public void destroy() throws Exception {
System.out.println("2. DisposableBean.destroy() ... ");
}
public void destroyMethod() {
System.out.println("3. destroy-method ... ");
}
}
测试类:Demo
package book.chapter4;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDemo {
@Test
public void testXml() {
System.out.println("###### load ##############");
GenericXmlApplicationContext gtx = new GenericXmlApplicationContext();
gtx.load("classpath:book/chapter4/app-context-a.xml") ;
gtx.refresh();
System.out.println("###### getBean ############");
A bean = gtx.getBean("a" , A.class);
bean.doSomething();
System.out.println("###### close #############");
gtx.close();
}
}
测试结果
3、扩展
在 Spring 中销毁回调函数的唯一缺点是他们不会自动触发;
如果 applicationContext 的实现 是 GenericXmlApplicationContext 时候 很好解决
registerShutdownHook()
只需要 进行 销毁注册方法 registerShutdownHook()
package book.chapter4;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDemo {
@Test
public void testLoad$Close() {
System.out.println("###### load ##############");
GenericXmlApplicationContext gtx = new GenericXmlApplicationContext();
gtx.load("classpath:book/chapter4/app-context-a.xml") ;
gtx.refresh();
System.out.println("###### getBean ############");
A bean = gtx.getBean("a" , A.class);
bean.doSomething();
System.out.println("###### close #############");
gtx.close();
}
@Test
public void testRegisterShutdownHook() {
System.out.println("###### load ##############");
GenericXmlApplicationContext gtx = new GenericXmlApplicationContext();
gtx.registerShutdownHook();
gtx.load("classpath:book/chapter4/app-context-a.xml") ;
gtx.refresh();
System.out.println("###### getBean ############");
A bean = gtx.getBean("a" , A.class);
bean.doSomething();
System.out.println("###### close #############");
}
}
运行 测试 testRegisterShutdownHook 。发现在没有 调用 close 时候也能进行资源释放。
ApplicationContextAware 接口
最后,可以 添加一个 实现了 ApplicationContextAware 接口 的bean
会自动扫描 是否存在 GenericXmlApplicationContext ,
存在 ,就自动 执行 注册方法 registerShutdownHook()
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="init"
default-destroy-method="destroyMethod"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<context:annotation-config />
<bean id="a" class="book.chapter4.A" p:a="propA"/>
<bean class="book.chapter4.ShutdownHookBean" />
</beans>
实现了 ApplicationContextAware 接口 的bean
package book.chapter4;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.GenericXmlApplicationContext;
public class ShutdownHookBean implements ApplicationContextAware {
public ShutdownHookBean() {
System.out.println("### ShutdownHookBean constructor ... ");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(applicationContext instanceof GenericXmlApplicationContext) {
GenericXmlApplicationContext gtx = (GenericXmlApplicationContext)applicationContext ;
gtx.registerShutdownHook();
System.out.println("#### registerShutdownHook() ... ");
}
}
}
Test 类
package book.chapter4;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDemoHook {
@Test
public void testHookBean() {
System.out.println("###### load ##############");
GenericXmlApplicationContext gtx = new GenericXmlApplicationContext();
gtx.load("classpath:book/chapter4/app-context-xml-hook.xml") ;
gtx.refresh();
System.out.println("###### getBean ############");
A bean = gtx.getBean("a" , A.class);
bean.doSomething();
System.out.println("###### close #############");
}
}