国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

(spring-第1回【IoC基礎篇】)Spring容器中Bean的生命周期

2019-11-14 15:09:31
字體:
來源:轉載
供稿:網友

日出日落,春去秋來,花隨流水,北雁南飛,世間萬物皆有生死輪回。從調用xml中的Bean配置信息,到應用到具體實例中,再到銷毀,Bean也有屬于它的生命周期。

 

人類大腦對圖像的認知能力永遠高于文字,因此,閑言少敘,書歸正傳,上圖先:

 

 

步驟很多,切莫驚慌,我們可以把上面的步驟歸納如下:

1-2:創建實例;

  現在假設sPRing就是個容器,而配置文件中配置的bean屬性才是我們真正需要的東西。創建實例就是說,我把配置文件中的bean信息取出來化作一個真正的bean并放到容器中。

3-4:注入依賴關系;

  第3步是創建實例之后對實例作了一些處理,第4步是把xml中配置的bean屬性值賦予給容器中的實例化之后的bean。

5:bean初始化之前的處理;

  應用開發者需要把容器中實例化的bean拿出來用,這個拿出來的過程就是初始化(注意實例化與初始化的區別,instantiation 和initialization,分得清嗎?英語沒學好怪我咯?),第五步就是在初始化之前,對已經實例化的bean再作一定的處理。

6,7:初始化。

  如果bean實現了InitializingBean,那么將調用InitializingBean的afterPropertiesSet()方法做一些初始化處理。如果沒有實現InitializingBean,而是在配置文件中定義了init-method屬性值,那么系統會找到init-method對應的方法并執行之,程序猿哥哥一般在這個方法里寫一些初始化操作;

8:bean初始化之后的處理。

  初始化之后在這個方法中再對bean進行修飾裝點。

9,10:交給應用開發人員處理;

  如果在<bean>中指定Bean的作用范圍是scopt="prototype",那么系統將bean返回給調用者,spring就不管了(如果兩個實例調用的話,每一次調用都要重新初始化,一個實例的修改不會影響另一個實例的值。如果指定Bean的作用范圍是scope="singleton",則把bean放到緩沖池中,并將bean的引用返回給調用者。這個時候,如果兩個實例調用的話,因為它們用的是同一個引用,任何一方的修改都會影響到另一方。)

11.bean用完之后;

  對于scope="singleton"的bean,使用完之后spring容器會做一些處理,比如編寫釋放資源、記錄日志等操作。

12.銷毀;

  調用配置文件中的銷毀方法銷毀實例。

 

光說不練假把式。來看實例:

 1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4     xsi:schemaLocation="http://www.springframework.org/schema/beans  5        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 6     <bean id="jay" class="com.mesopotamia.bean_life_cycle.JayChou"  7          init-method="myInit" 8          destroy-method="myDestory" 9          p:sex="男"10          p:girlFriend="蔡依林" 11          p:profession="歌手,演員,導演,主持"12          scope="singleton"13          /> 14 </beans>

上面是配置文件,取名為jayConfig.xml,注意bean中定義了init-method、destroy-method屬性,翻閱上文查看這兩個屬性的作用。該bean還定義了scope屬性,對應第9步。

在BeanFactory的bean生命周期中,第1、3、5、8步是由程序員自己擴展的。自己擴展類并在代碼中注冊使用。

下面看一個例子:

 1 package com.mesopotamia.bean_life_cycle; 2  3 import java.beans.PropertyDescriptor; 4  5 import org.springframework.beans.BeansException; 6 import org.springframework.beans.PropertyValues; 7 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; 8  9 public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter{10 11     public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {12         if("jay".equals(beanName)){13             System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");            14         }        15         return null;16     }17     /**實例化Bean后,對Bean進行梳妝打扮*/18     public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {19         if("jay".equals(beanName)){20         System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");21         }22         return true;23     }24 25     //把Bean的配置值賦值給Bean實例的屬性。26     public PropertyValues postProcessPropertyValues(27             PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)28             throws BeansException {29         if("jay".equals(beanName)){30            System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues");31         }32         return pvs;33     }34 35     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {36         return bean;37     }38 39     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {40         return bean;41     }42 }

上面的類是繼承了InstantiationAwareBeanPostProcessorAdopter的,而InstantiationAwareBeanPostProcessorAdopter這個適配器與是InstantiationAwareBeanPostProcessor的擴展類。

 

 1 package com.mesopotamia.bean_life_cycle; 2  3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.springframework.beans.BeansException; 6 import org.springframework.beans.factory.config.BeanPostProcessor; 7  8  9 public class MyBeanPostProcessor implements BeanPostProcessor{10     11     private Log log=LogFactory.getLog(MyBeanPostProcessor.class);12 13     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        14         if(beanName.equals("jay")){15             JayChou jay = (JayChou)bean;16             log.info("JayChou當前的女朋友是:"+jay.getGirlFriend());17             jay.setGirlFriend("昆凌");18             log.info("調用BeanPostProcessor的postProcessAfterInitialization處理后," +19                     "JayChou的女朋友變成:"+jay.getGirlFriend());20         }21         return bean;22 23     }24 25     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        26         if(beanName.equals("jay")){27             JayChou jay = (JayChou)bean;28             log.info("配置文件中Jay的女朋友是:"+jay.getGirlFriend());29             jay.setGirlFriend("侯佩岑");30             log.info("調用BeanPostProcessor的postProcessBeforeInitialization處理后," +31                     "Jay的女朋友變為:"+jay.getGirlFriend());32             33         }34         return bean;35     }36 }

上面的代碼實現了BeanPostProcessor。InstantiationAwareBeanPostProcessor是實例化前后做的事情,BeanPostProcessor是初始化前后做的事情,它們之間應該存在著父子關系吧?當然是,從名字就能看出來前者是后者的擴展類,讀者可以自己下載spring源碼查看。這兩個類定義好了需要注冊才能使用(把它們注冊到spring容器中使用),稍后再講。這里先講bean類:

 1 package com.mesopotamia.bean_life_cycle; 2  3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.springframework.beans.factory.DisposableBean; 6 import org.springframework.beans.factory.InitializingBean; 7  8 public class JayChou implements InitializingBean,DisposableBean { 9     10     private static Log log=LogFactory.getLog(JayChou.class);11     private String sex;12     private String profession;13     private String girlFriend;14     15     16 17     public JayChou(){18         log.info("調用JayChou的無參構造函數。杰倫出道啦。");19     }20 21     public String getSex() {22         return sex;23     }24 25     public void setSex(String sex) {26         this.sex = sex;27     }28     29 30     public void setGirlFriend(String girlFriend) {31         this.girlFriend = girlFriend;32     }33 34     public String getGirlFriend() {35         return girlFriend;36     }37 38     public String getProfession() {39         return profession;40     }41 42     public void setProfession(String profession) {43         this.profession = profession;44     }45 46 47     public void afterPropertiesSet() throws Exception {48         this.profession="歌手";49         log.info("調用InitializingBean.afterPropertiesSet()," +50                 "屬性配置完畢了再做些善后工作。");51         52     }53 54     public void destroy() throws Exception {55         log.info("調用DisposableBean.destory(),銷毀。。");56         57     }58     59     public void myInit() {        60         this.girlFriend = "徐若瑄";61         log.info("通過調用配置文件初始化女朋友為:"+this.girlFriend);62     }63 64     public void myDestory() {65         System.out.println("調用myDestroy()。");66     }67     68     public String toString(){69         return "JayChou簡介:" +70                 "    性別:"+sex+71                 "    職業:"+profession+72                 "    女朋友:"+girlFriend;73     }74 75 76 }

這個bean實現了InitializingBean,DisposableBean,那么第六步和第11步就可以用得到了。

下面看Main方法類:

 1 package com.mesopotamia.bean_life_cycle; 2  3 import org.apache.commons.logging.Log; 4 import org.apache.commons.logging.LogFactory; 5 import org.springframework.beans.factory.BeanFactory; 6 import org.springframework.beans.factory.config.ConfigurableBeanFactory; 7 import org.springframework.beans.factory.xml.XmlBeanFactory; 8 import org.springframework.core.io.ClassPathResource; 9 import org.springframework.core.io.Resource;10 11 12 public class BeanLifeCycleMain {13     14     private static Log log=LogFactory.getLog(BeanLifeCycleMain.class);15     16     private static void LifeCycleInBeanFactory(){17         Resource res = new ClassPathResource("com/mesopotamia/bean_life_cycle/jayConfig.xml");    18        BeanFactory bf = new XmlBeanFactory(res);19      20        /**BeanFactory是ConfigurableBeanFactory的父類,且該父類沒有這個添加方法,所以要轉換。*/21        ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); 22        //BeanPostProcessor23        ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());             24        25        JayChou jay = (JayChou)bf.getBean("jay");26        log.info("jay:"+jay.toString());27       28       // jay.setGirlFriend("溫嵐");29        JayChou jay2 = bf.getBean("jay",JayChou.class);30        jay2.setGirlFriend("溫嵐");31        log.info("jay2:"+jay2.toString());32        log.info("jay:"+jay.toString());33        34        log.info(jay == jay2);35        ((XmlBeanFactory)bf).destroySingletons();36     }37     public static void main(String[] args) {38         LifeCycleInBeanFactory();39     }40 }

第17、18行是裝載配置文件并啟動容器(相關知識請自己腦補)。第21行和23行是注冊事件,注冊后才能正常使用。先看一下執行結果:

1  2015-11-07 22:01:26,907  INFO [main] (XmlBeanDefinitionReader.java:315) - Loading XML bean definitions from class path resource [com/mesopotamia/bean_life_cycle/jayConfig.xml]2  MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation3  2015-11-07 22:01:27,068  INFO [main] (JayChou.java:18) - 調用JayChou的無參構造函數。杰倫出道啦。4  InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation5  InstantiationAwareBeanPostProcessor.postProcessPropertyValues6  2015-11-07 22:01:27,106  INFO [main] (MyBeanPostProcessor.java:28) - 配置文件中Jay的女朋友是:蔡依林7  2015-11-07 22:01:27,106  INFO [main] (MyBeanPostProcessor.java:30) - 調用BeanPostProcessor的postProcessBeforeInitialization處理后,Jay的女朋友變為:侯佩岑8  2015-11-07 22:01:27,106  INFO [main] (JayChou.java:49) - 調用InitializingBean.afterPropertiesSet(),屬性配置完畢了再做些善后工作。9  2015-11-07 22:01:27,106  INFO [main] (JayChou.java:61) - 通過調用配置文件初始化女朋友為:徐若瑄10  2015-11-07 22:01:27,106  INFO [main] (MyBeanPostProcessor.java:16) - JayChou當前的女朋友是:徐若瑄11  2015-11-07 22:01:27,107  INFO [main] (MyBeanPostProcessor.java:18) - 調用BeanPostProcessor的postProcessAfterInitialization處理后,JayChou的女朋友變成:昆凌12  2015-11-07 22:01:27,110  INFO [main] (BeanLifeCycleMain.java:26) - jay:JayChou簡介:	性別:男	職業:歌手	女朋友:昆凌13  2015-11-07 22:01:27,110  INFO [main] (BeanLifeCycleMain.java:31) - jay2:JayChou簡介:	性別:男	職業:歌手	女朋友:溫嵐14  2015-11-07 22:01:27,110  INFO [main] (BeanLifeCycleMain.java:32) - jay:JayChou簡介:	性別:男	職業:歌手	女朋友:溫嵐15  2015-11-07 22:01:27,110  INFO [main] (BeanLifeCycleMain.java:34) - true16  2015-11-07 22:01:27,110  INFO [main] (DefaultSingletonBeanRegistry.java:422) - Destroying singletons in org.springframework.beans.factory.xml.XmlBeanFactory@6e293a: defining beans [jay]; root of factory hierarchy17  2015-11-07 22:01:27,111  INFO [main] (JayChou.java:55) - 調用DisposableBean.destory(),銷毀。。18  調用myDestroy()。

  行1:加載xml。

  行2:實例化之前處理了一些事情。

  行3:duang!開始實例化,實例化當然首先要執行構造函數(這是美好世界的窗口)。

  行4:實例化之后處理了一些事情。

  行5:實例化之后注入屬性值之前要調用這個函數。

  行6:注入xml的屬性值,可以看到是配置中的"蔡依林"。

  行7:注入屬性值后,隨即又把女朋友這個屬性的值改為了"侯佩岑"。

  行8:屬性配置完畢了做一些善后工作。在JayChou類的第48行可以看到,我把職業改為了"歌手",所以后面顯示的職業都是"歌手",而不是配置文件中的"歌手,演員,導演,主持"。

  行9:調用了配置文件中的init-method。通過<bean>的class屬性找到這個類,再找到屬性值對應的這個方法執行。行8和行9對應流程圖表中的第六步和第七步,在此可以看到先執行第6步,后執行第七步。然而,行9是在配置文件中實現的,這正符合spring容器的宗旨,而行8的實現必須implements InitializingBean,給代碼帶來復雜度和污染,因此行8(也就是圖表第六步)一般是不提倡的。

  行10和行11是初始化之后做的事情,首先顯示當前女朋友,在行9中已經改為徐若瑄。緊接著行11又把女朋友改為了昆凌。

  行12-行15:看對應的代碼就會發現,兩個對象其實引用的是同一個地址,jay2修改了屬性之后jay1也會跟著作改變,這就是singleton配置方式的作用。

  行16是關閉容器。

  行17和行18,一個是調用DisposableBean的銷毀,一個是調用配置文件的銷毀,利弊取舍與上文行9的敘述相同。

 

  哥哥們姐姐們,那么如果把配置文件的scope屬性改為"prototype"會發生什么呢?讓我們看一下打印的日志:

1  2015-11-07 22:37:29,280  INFO [main] (XmlBeanDefinitionReader.java:315) - Loading XML bean definitions from class path resource [com/mesopotamia/bean_life_cycle/jayConfig.xml]2  MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation3  2015-11-07 22:37:29,407  INFO [main] (JayChou.java:18) - 調用JayChou的無參構造函數。杰倫出道啦。4  InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation5  InstantiationAwareBeanPostProcessor.postProcessPropertyValues6  2015-11-07 22:37:29,444  INFO [main] (MyBeanPostProcessor.java:28) - 配置文件中Jay的女朋友是:蔡依林7  2015-11-07 22:37:29,444  INFO [main] (MyBeanPostProcessor.java:30) - 調用BeanPostProcessor的postProcessBeforeInitialization處理后,Jay的女朋友變為:侯佩岑8  2015-11-07 22:37:29,444  INFO [main] (JayChou.java:49) - 調用InitializingBean.afterPropertiesSet(),屬性配置完畢了再做些善后工作。9  2015-11-07 22:37:29,445  INFO [main] (JayChou.java:61) - 通過調用配置文件初始化女朋友為:徐若瑄10  2015-11-07 22:37:29,445  INFO [main] (MyBeanPostProcessor.java:16) - JayChou當前的女朋友是:徐若瑄11  2015-11-07 22:37:29,445  INFO [main] (MyBeanPostProcessor.java:18) - 調用BeanPostProcessor的postProcessAfterInitialization處理后,JayChou的女朋友變成:昆凌12  2015-11-07 22:37:29,446  INFO [main] (BeanLifeCycleMain.java:26) - jay:JayChou簡介:	性別:男	職業:歌手	女朋友:昆凌13  2015-11-07 22:37:29,446  INFO [main] (JayChou.java:18) - 調用JayChou的無參構造函數。杰倫出道啦。14  InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation15  InstantiationAwareBeanPostProcessor.postProcessPropertyValues16  2015-11-07 22:37:29,447  INFO [main] (MyBeanPostProcessor.java:28) - 配置文件中Jay的女朋友是:蔡依林17  2015-11-07 22:37:29,447  INFO [main] (MyBeanPostProcessor.java:30) - 調用BeanPostProcessor的postProcessBeforeInitialization處理后,Jay的女朋友變為:侯佩岑18  2015-11-07 22:37:29,447  INFO [main] (JayChou.java:49) - 調用InitializingBean.afterPropertiesSet(),屬性配置完畢了再做些善后工作。19  2015-11-07 22:37:29,447  INFO [main] (JayChou.java:61) - 通過調用配置文件初始化女朋友為:徐若瑄20  2015-11-07 22:37:29,448  INFO [main] (MyBeanPostProcessor.java:16) - JayChou當前的女朋友是:徐若瑄21  2015-11-07 22:37:29,448  INFO [main] (MyBeanPostProcessor.java:18) - 調用BeanPostProcessor的postProcessAfterInitialization處理后,JayChou的女朋友變成:昆凌22  2015-11-07 22:37:29,448  INFO [main] (BeanLifeCycleMain.java:31) - jay2:JayChou簡介:	性別:男	職業:歌手	女朋友:溫嵐23  2015-11-07 22:37:29,448  INFO [main] (BeanLifeCycleMain.java:32) - jay:JayChou簡介:	性別:男	職業:歌手	女朋友:昆凌24  2015-11-07 22:37:29,449  INFO [main] (BeanLifeCycleMain.java:34) - false25  2015-11-07 22:37:29,449  INFO [main] (DefaultSingletonBeanRegistry.java:422) - Destroying singletons in org.springframework.beans.factory.xml.XmlBeanFactory@ce5b1c: defining beans [jay]; root of factory hierarchy

  上面的日志是見證奇跡的時刻,當創建jay2對象時,從13行到21行,又進行了一次初始化的過程,而22行到24行發現,兩個對象不相同了,這就是prototype的作用。

 

 applicationContext中Bean的生命周期與BeanFactory類似,但是又有不同。對于InstantiationAwareBeanPostProcessor和MyBeanPostProcessor,BeanFactory需要在代碼中注冊方才能使用,而ApplicationContext只需要在xml中配置,spring會自動將它們注冊到應用上下文中,這是二者最大的區別,也是為什么普遍使用ApplicationContext而非BeanFactory的原因。ApplicationContext是BeanFactory的擴展類。

 

  spring當前在各大企業應用中廣受青睞,spring融匯的java思想也堪稱經典,因此筆者后面將繼續跟廣大猿猿一塊學習探討spring的精髓,對于文中的錯誤與不足,抑或是讀者有一般人不告訴他的精辟見解,還望在評論中留言,一起學習。共勉。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 关岭| 沙河市| 永仁县| 宁阳县| 泾川县| 苏尼特右旗| 金沙县| 绿春县| 墨玉县| 东宁县| 宜君县| 锦屏县| 青海省| 家居| 嘉善县| 兖州市| 大关县| 屯昌县| 河南省| 岢岚县| 库尔勒市| 彝良县| 广平县| 奉新县| 宝鸡市| 唐海县| 莱芜市| 连城县| 苗栗市| 平和县| 丰台区| 隆尧县| 金塔县| 措美县| 景谷| 彰化市| 牡丹江市| 泸西县| 法库县| 大关县| 达尔|