網站首頁 編程語言 正文
詳解Spring Bean的生命周期
Spring Bean的生命周期包括以下階段:
1. 實例化Bean
對于BeanFactory容器,當客戶向容器請求一個尚未初始化的bean時,或初始化bean的時候需要注入另一個尚未初始化的依賴時,容器就會調用createBean進行實例化。 對于ApplicationContext容器,當容器啟動結束后,便實例化所有的bean。 容器通過獲取BeanDefinition對象中的信息進行實例化。并且這一步僅僅是簡單的實例化,并未進行依賴注入。 實例化對象被包裝在BeanWrapper對象中,BeanWrapper提供了設置對象屬性的接口,從而避免了使用反射機制設置屬性。
2. 設置對象屬性(依賴注入)
實例化后的對象被封裝在BeanWrapper對象中,并且此時對象仍然是一個原生的狀態,并沒有進行依賴注入。 緊接著,Spring根據BeanDefinition中的信息進行依賴注入。 并且通過BeanWrapper提供的設置屬性的接口完成依賴注入。
3. 注入Aware接口
緊接著,Spring會檢測該對象是否實現了xxxAware接口,并將相關的xxxAware實例注入給bean。
4. BeanPostProcessor
當經過上述幾個步驟后,bean對象已經被正確構造,但如果你想要對象被使用前再進行一些自定義的處理,就可以通過BeanPostProcessor接口實現。 該接口提供了兩個函數:postProcessBeforeInitialzation( Object bean, String beanName ) 當前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數會先于InitialzationBean執行,因此稱為前置處理。 所有Aware接口的注入就是在這一步完成的。postProcessAfterInitialzation( Object bean, String beanName ) 當前正在初始化的bean對象會被傳遞進來,我們就可以對這個bean作任何處理。 這個函數會在InitialzationBean完成后執行,因此稱為后置處理。
5. InitializingBean與init-method
當BeanPostProcessor的前置處理完成后就會進入本階段。 InitializingBean接口只有一個函數:afterPropertiesSet()這一階段也可以在bean正式構造完成前增加我們自定義的邏輯,但它與前置處理不同,由于該函數并不會把當前bean對象傳進來,因此在這一步沒辦法處理對象本身,只能增加一些額外的邏輯。 若要使用它,我們需要讓bean實現該接口,并把要增加的邏輯寫在該函數中。然后Spring會在前置處理完成后檢測當前bean是否實現了該接口,并執行afterPropertiesSet函數。當然,Spring為了降低對客戶代碼的侵入性,給bean的配置提供了init-method屬性,該屬性指定了在這一階段需要執行的函數名。Spring便會在初始化階段執行我們設置的函數。init-method本質上仍然使用了InitializingBean接口。
6. DisposableBean和destroy-method
和init-method一樣,通過給destroy-method指定函數,就可以在bean銷毀前執行指定的邏輯。
詳解Spring Bean生命周期
Spring Bean的完整生命周期從創建Spring容器開始,直到最終Spring容器銷毀Bean,這其中包含了一系列關鍵點。
例子演示
我們用一個簡單的Spring Bean來演示一下Spring Bean的生命周期。
1.首先是一個簡單的Spring Bean,調用Bean自身的方法和Bean級生命周期接口方法,為了方便演示,它實現了BeanNameAware
、BeanFactoryAware
、InitializingBean
和DiposableBean
這4個接口,同時有2個方法,對應配置文件中的init-method和destroy-method。如下:
package springBeanTest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* @author qsk
*/
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean {
private String name;
private String address;
private int phone;
private BeanFactory beanFactory;
private String beanName;
public Person() {
System.out.println("【構造器】調用Person的構造器實例化");
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("【注入屬性】注入屬性name");
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
System.out.println("【注入屬性】注入屬性address");
this.address = address;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
System.out.println("【注入屬性】注入屬性phone");
this.phone = phone;
}
@Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone="
+ phone + "]";
}
// 這是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out
.println("【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
}
// 這是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】調用BeanNameAware.setBeanName()");
this.beanName = arg0;
}
// 這是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out
.println("【InitializingBean接口】調用InitializingBean.afterPropertiesSet()");
}
// 這是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】調用DiposibleBean.destory()");
}
// 通過<bean>的init-method屬性指定的初始化方法
public void myInit() {
System.out.println("【init-method】調用<bean>的init-method屬性指定的初始化方法");
}
// 通過<bean>的destroy-method屬性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法");
}
}
2.接下來是演示BeanPostProcessor接口的方法,如下:
package springBeanTest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("這是BeanPostProcessor實現類構造器!!");
// TODO Auto-generated constructor stub
}
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!");
return arg0;
}
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!");
return arg0;
}
}
如上,BeanPostProcessor接口包括2個方法postProcessAfterInitialization
和postProcessBeforeInitialization
,這兩個方法的第一個參數都是要處理的Bean對象,第二個參數都是Bean的name。返回值也都是要處理的Bean對象。這里要注意。
3、InstantiationAwareBeanPostProcessor 接口本質是BeanPostProcessor的子接口,一般我們繼承Spring為其提供的適配器類InstantiationAwareBeanPostProcessorAdapter來使用它,如下:
package springBeanTest;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out
.println("這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!");
}
// 接口方法、實例化Bean之前調用
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法");
return null;
}
// 接口方法、實例化Bean之后調用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法");
return bean;
}
// 接口方法、設置某個屬性時調用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法");
return pvs;
}
}
這個有3個方法,其中第二個方法postProcessAfterInitialization
就是重寫了BeanPostProcessor的方法。第三個方法postProcessPropertyValues
用來操作屬性,返回值也應該是PropertyValues對象。
4.演示工廠后處理器接口方法,如下:
package springBeanTest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("這是BeanFactoryPostProcessor實現類構造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor調用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
5.配置文件如下beans.xml,很簡單,使用ApplicationContext,處理器不用手動注冊:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="beanPostProcessor" class="springBeanTest.MyBeanPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor" class="springBeanTest.MyInstantiationAwareBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor" class="springBeanTest.MyBeanFactoryPostProcessor">
</bean>
<bean id="person" class="springBeanTest.Person" init-method="myInit"
destroy-method="myDestory" scope="singleton" p:name="張三" p:address="廣州"
p:phone="15900000000" />
</beans>
6.下面測試一下:
package springBeanTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanLifeCycle {
public static void main(String[] args) {
System.out.println("現在開始初始化容器");
ApplicationContext factory = new ClassPathXmlApplicationContext("springBeanTest/beans.xml");
System.out.println("容器初始化成功");
//得到Preson,并使用
Person person = factory.getBean("person",Person.class);
System.out.println(person);
System.out.println("現在開始關閉容器!");
((ClassPathXmlApplicationContext)factory).registerShutdownHook();
}
}
我們來看一下結果:
現在開始初始化容器
2014-5-18 15:46:20 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@19a0c7c: startup date [Sun May 18 15:46:20 CST 2014]; root of context hierarchy
2014-5-18 15:46:20 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [springBeanTest/beans.xml]
這是BeanFactoryPostProcessor實現類構造器!!
BeanFactoryPostProcessor調用postProcessBeanFactory方法
這是BeanPostProcessor實現類構造器!!
這是InstantiationAwareBeanPostProcessorAdapter實現類構造器!!
2014-5-18 15:46:20 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@9934d4: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,person]; root of factory hierarchy
InstantiationAwareBeanPostProcessor調用postProcessBeforeInstantiation方法
【構造器】調用Person的構造器實例化
InstantiationAwareBeanPostProcessor調用postProcessPropertyValues方法
【注入屬性】注入屬性address
【注入屬性】注入屬性name
【注入屬性】注入屬性phone
【BeanNameAware接口】調用BeanNameAware.setBeanName()
【BeanFactoryAware接口】調用BeanFactoryAware.setBeanFactory()
BeanPostProcessor接口方法postProcessBeforeInitialization對屬性進行更改!
【InitializingBean接口】調用InitializingBean.afterPropertiesSet()
【init-method】調用<bean>的init-method屬性指定的初始化方法
BeanPostProcessor接口方法postProcessAfterInitialization對屬性進行更改!
InstantiationAwareBeanPostProcessor調用postProcessAfterInitialization方法
容器初始化成功
Person [address=廣州, name=張三, phone=110]
現在開始關閉容器!
【DiposibleBean接口】調用DiposibleBean.destory()
【destroy-method】調用<bean>的destroy-method屬性指定的初始化方法
Spring Bean生命周期流程圖
原文鏈接:https://blog.csdn.net/Mr_VK/article/details/132090604
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2023-07-14 express+element實現上傳圖片
- 2023-04-09 使用Pytest.main()運行時參數不生效問題解決_python
- 2022-12-05 Python應用開發之實現串口通信_python
- 2022-04-01 Failed to execute goal com.github.eirslettfrontend
- 2022-12-23 Kotlin?try?catch異常處理i詳解_Android
- 2022-12-10 關于torch中tensor數據類型的轉換_python
- 2023-04-13 element UI中flex布局下el-table寬度自適應在IE下出現一直加載寬度的bug解決
- 2023-12-26 layui彈窗傳值
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支