前言
测试下,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; @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; @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; @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
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(); } } }
|