Spring之bean的生命周期
Spring之bean的生命周期
在傳統的Java應用中,bean的生命周期很簡單,使用Java關鍵字 new 進行Bean 的實例化,然後該Bean 就能夠使用了。一旦bean不再被使用,則由Java自動進行垃圾回收。
相比之下,Spring管理Bean的生命周期就複雜多了,正確理解Bean 的生命周期非常重要,因為Spring對Bean的管理可擴展性非常強,下面展示了一個Bean的構造過程
- Bean 容器找到配置文件中 Spring Bean 的定義。
- Bean 容器利用 Java Reflection API 創建一個 Bean 的實例。
- 如果涉及到一些屬性值 利用 set()方法設置一些屬性值。
- 如果實現了其他 *.Aware介面,就調用相應的方法。
- 如果有和載入這個 Bean 的 Spring 容器相關的 BeanPostProcessor 對象,執行postProcessBeforeInitialization() 方法
- 如果 Bean 實現了InitializingBean介面,執行afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定義包含 init-method 屬性,執行指定的方法。
- 如果有和載入這個 Bean 的 Spring 容器相關的 BeanPostProcessor 對象,執行postProcessAfterInitialization() 方法
- 當要銷毀 Bean 的時候,如果 Bean 實現了 DisposableBean 介面,執行 destroy() 方法。
- 當要銷毀 Bean 的時候,如果 Bean 在配置文件中的定義包含 destroy-method 屬性,執行指定的方法。
在 BeanFactory
的注釋里,有這麼一段話,如下圖所示:
程式碼演示
- 新建一個
User
類,讓其實現介面BeanNameAware
、BeanFactoryAware
、InitializingBean
和DiposableBean
這4個介面,以及編寫userInit()
和userDestroy()
兩個方法,對應配置文件中<bean>
的init-method
和destroy-method
。
package com.wqing.domain;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
/**
* @Description 用於演示 Bean 的生命周期
* @Author wqing
* @Date 2022/8/11 15:37
*/
public class User implements BeanNameAware, BeanFactoryAware,
InitializingBean, DisposableBean {
private String name;
private Integer age;
private BeanFactory beanFactory;
private String beanName;
public User() {
System.out.println("[構造器]--調用Person的構造函數進行實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("[屬性填充]--注入屬性name");
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("[屬性填充]--注入屬性age");
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//這是 BeanFactoryAware 介面的方法
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[BeanFactoryAware]--執行BeanFactoryAware.setBeanFactory(),beanFactory為:" + beanFactory);
this.beanFactory = beanFactory;
}
//這是 BeanNameAware 介面的方法
@Override
public void setBeanName(String name) {
System.out.println("[BeanNameAware]--執行BeanNameAware.setBeanName(),beanName為: " + name);
this.beanName = name;
}
//這是 DisposableBean 介面的方法
@Override
public void destroy() throws Exception {
System.out.println("[DisposableBean]--執行DisposableBean.destroy()");
}
//這是 InitializingBean 介面的方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[InitializingBean]--執行InitializingBean.afterPropertiesSet()");
}
// 通過<bean>的init-method屬性指定的初始化方法
public void userInit() {
System.out.println("[init-method]--執行<bean>的init-method屬性指定的初始化方法");
}
// 通過<bean>的destroy-method屬性指定的初始化方法
public void userDestroy() {
System.out.println("[destroy-method]--執行<bean>的destroy-method屬性指定的銷毀方法");
}
}
- 自定義
MyBeanPostProcessor
實現BeanPostProcessor
package com.wqing.domain;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @Description
* @Author 王清
* @Date 2022/8/11 16:06
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 實例化、依賴注入完畢,在調用顯示的初始化之前完成一些訂製的初始化任務
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[BeanPostProcessor]--執行BeanPostProcessor.postProcessBeforeInitialization()");
return bean;
}
/**
* 實例化、依賴注入、初始化完畢時執行
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[BeanPostProcessor]--執行BeanPostProcessor.postProcessAfterInitialization()");
return bean;
}
}
BeanPostProcessor
介面包括2個方法postProcessAfterInitialization
和postProcessBeforeInitialization
,這兩個方法的第一個參數都是要處理的Bean對象,第二個參數都是Bean的name。返回值也都是要處理的Bean對象。
- 編寫
application.xml
,將User
和MyBeanPostProcessor
註冊進容器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="//www.springframework.org/schema/beans"
xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//www.springframework.org/schema/beans //www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.wqing.domain.User" init-method="userInit"
destroy-method="userDestroy">
<property name="name" value="張三"/>
<property name="age" value="20"/>
</bean>
<bean id="myBeanPostProcessor" class="com.wqing.domain.MyBeanPostProcessor"/>
</beans>
- 編寫測試類
package com.wqing;
import com.wqing.domain.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Description
* @Author wqing
* @Date 2022/8/5 14:38
*/
public class Test {
public static void main(String[] args) {
System.out.println("容器開始創建");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User bean = context.getBean(User.class);
System.out.println("使用 bean");
System.out.println(bean);
System.out.println("容器開始銷毀");
context.close();
}
}
執行結果
容器開始創建
[構造器]--調用Person的構造函數進行實例化
[屬性填充]--注入屬性name
[屬性填充]--注入屬性age
[BeanNameAware]--執行BeanNameAware.setBeanName(),beanName為: user
[BeanFactoryAware]--執行BeanFactoryAware.setBeanFactory(),beanFactory為:org.springframework.beans.factory.support.DefaultListableBeanFactory@38082d64: defining beans [user,myBeanPostProcessor]; root of factory hierarchy
[BeanPostProcessor]--執行BeanPostProcessor.postProcessBeforeInitialization()
[InitializingBean]--執行InitializingBean.afterPropertiesSet()
[init-method]--執行<bean>的init-method屬性指定的初始化方法
[BeanPostProcessor]--執行BeanPostProcessor.postProcessAfterInitialization()
使用 bean
User{name='張三', age=20}
容器開始銷毀
[DisposableBean]--執行DisposableBean.destroy()
[destroy-method]--執行<bean>的destroy-method屬性指定的銷毀方法