【spring源碼分析】IOC容器初始化——查漏補缺(四)

前言:在前幾篇查漏補缺中,其實咱們已經涉及到bean生命週期了,本篇內容進行詳細分析。ide


首先看bean實例化過程:函數

分析:post

bean實例化開始後測試

  • 注入對象屬性後(前面IOC初始化十幾篇文章)。
  • 檢查激活Aware接口。
  • 執行BeanPostProcessor前置處理
  • 實例化bean,這裏會檢查InitializingBean和init-method方法。
  • 執行BeanPostProcessor後置處理
  • 註冊銷燬bean的回調方法(並非必須)。
  • 使用bean。
  • 檢查DisposableBean和destroy-method方法。

注意:Spring是不會主動去調用銷燬方法,必須咱們主動告知Spring容器。this

示例

 1 public class BeanLifeCycle implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
 2 
 3     private String msg;
 4 
 5     public BeanLifeCycle() {
 6         System.out.println("調用構造函數:BeanLifeCycle()");
 7     }
 8 
 9     public String getMsg() {
10         return msg;
11     }
12 
13     public void setMsg(String msg) {
14         System.out.println("屬性注入:setMsg");
15         this.msg = msg;
16     }
17 
18     @Override
19     public void setBeanName(String name) {
20         System.out.println("BeanNameAware#setBeanName 被調用");
21     }
22 
23     @Override
24     public void setBeanClassLoader(ClassLoader classLoader) {
25         System.out.println("BeanClassLoaderAware#setBeanClassLoader 被調用");
26     }
27 
28     @Override
29     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
30         System.out.println("BeanFactoryAware#setBeanFactory 被調用");
31 
32     }
33 
34     @Override
35     public void afterPropertiesSet() throws Exception {
36         System.out.println("InitializingBean#afterPropertiesSet 被調用,並對msg屬性進行修改");
37         this.msg = "InitializingBean#afterPropertiesSet方法對msg屬性進行修改";
38     }
39 
40     @Override
41     public void destroy() throws Exception {
42         System.out.println("DisposableBean#destroy 被調用");
43     }
44 
45     public void initMethod() {
46         System.out.println("init-method 被調用,並對msg屬性進行修改,調用順序在InitializingBean以後");
47         this.msg = "init-method方法對msg屬性進行修改";
48     }
49 
50     public void destroyMethod() {
51         System.out.println("destroy-method 被調用,調用順序在DisposableBean以後");
52     }
53 }

上述爲主測試類,另外爲了測試BeanPostProcessor,咱們還需增長以下測試類:spa

 1 public class BeanLifeCycleBeanPostProcessor implements BeanPostProcessor {
 2 
 3     @Override
 4     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 5         System.out.println("beanName=" + beanName + " 初始化以前調用:BeanPostProcessor#postProcessBeforeInitialization!!!!!");
 6         return bean;
 7     }
 8 
 9     @Override
10     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
11         System.out.println("beanName=" + beanName + " 初始化以後調用:BeanPostProcessor#postProcessAfterInitialization!!!!!");
12         return bean;
13     }
14 }

具體配置以下:code

1 <bean id="beanLifeCycle" class="com.dev.basebean.lifecycle.BeanLifeCycle"
2           init-method="initMethod" destroy-method="destroyMethod" p:msg="屬性注入"/>
3     <bean id="beanLifeCycleBeanPostProcessor" class="com.dev.basebean.lifecycle.BeanLifeCycleBeanPostProcessor"/>

測試代碼:xml

1     @Test
2     public void beanLifeCycleTest() {
3         ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/lifecycle/lifecycle.xml");
4         BeanLifeCycle beanLifeCycle = context.getBean(BeanLifeCycle.class);
5         System.out.println("msg=" + beanLifeCycle.getMsg());
6         ((ClassPathXmlApplicationContext) context).close();
7     }

運行結果以下:對象

經過以上運行結果,咱們可知Bean的生命週期,總結以下:blog

  1. Spring容器根據實例化策略對Bean進行實例化(調用其構造方法)。
  2. 實例化完成後,若是該bean設置了一些屬性,則利用set方法進行屬性設置。
  3. 若是該bean實現了BeanNameAware接口,則調用其setBeanName方法。
  4. 若是該bean實現了BeanClassLoaderAware接口,則調用其setBeanClassLoader方法。
  5. 若是該bean實現了BeanFactoryAware接口,則調用其setBeanFactory方法。
  6. 若是容器中註冊了BeanPostProcessor,則會調用其postProcessBeforeInitialization方法,完成bean前置處理。
  7. 若是該bean實現了InitializingBean接口,則調用其afterPropertiesSet方法。
  8. 若是該bean配置了init-method方法,則調用其指定的方法。
  9. 初始化完成後,若是容器中註冊了BeanPostProcessor,則會調用其postProcessAfterInitialization方法,完成bean後置處理。
  10. 對象初始化完成,就能夠使用bean了(對其進行各類騷操做,上述示例中調用了getMsg方法)。
  11. 在容器關閉以前,若是該bean實現了DisposableBean接口,則調用其destroy方法。
  12. 在容器關閉以前,若是該bean配置了destroy-method方法,則調用其指定方法。

至此bean的生命週期結束,該bean完成了其偉大的一輩子。


by Shawn Chen,2019.05.05,下午。

相關文章
相關標籤/搜索