学习Spring(六) -- Spring中Bean的作用域以及生命周期
2019獨角獸企業重金招聘Python工程師標準>>>
Bean的作用域
????默認情況下,bean的作用域為單例模式(singleton):
在applicationContext創建時,就將配置文件中的bean加載完畢;
在調用getBean時,從applicationContext中獲取;
????也就是說,在整個應用程序中,bean只存在一個實例,下面寫一段代碼測試一下,寫一個Car類,有一個Name字段:
package?cn.net.bysoft.lesson4;public?class?Car?{public?Car()?{}@Overridepublic?String?toString()?{return?"Car?[name="?+?name?+?"]";}public?String?getName()?{return?name;}public?void?setName(String?name)?{this.name?=?name;}private?String?name;}????在配置文件中,配置這個Car的bean元素:
<bean?id="car"?class="cn.net.bysoft.lesson4.Car"> </bean> @Testpublic?void?testScopeIsDefault()?{//?在Spring容器初始化時就生成了bean對應的對象。//?在調用時,從Spring容器中get一個對象,這個對象是單例的。Car?car?=?(Car)?ctx.getBean("car");car.setName("Audi");Car?car1?=?(Car)?ctx.getBean("car");car1.setName("BMW");//?get到的對象都會修改這個單例的bean。System.out.println(car);System.out.println(car1);/***?output:?*?Car?[name=BMW]?*?Car?[name=BMW]*?*/}????測試發現,對car設置的name值被car1覆蓋了,也就是說,car與car1實際是使用的同一個car實例,car==car1。
????可以改變bean的作用域來解決此問題,將scope=prototype:
<bean?id="car2"?class="cn.net.bysoft.lesson4.Car"?scope="prototype"> </bean> @Testpublic?void?testScopeIsPrototype()?{//?設置了bean的scope=prototype后//?在Spring容器初始化時不會自動生成bean對應的對象//?而是在get時生成對象,對象不是單例的。Car?car?=?(Car)?ctx.getBean("car2");car.setName("Audi");Car?car1?=?(Car)?ctx.getBean("car2");car1.setName("BMW");System.out.println(car);System.out.println(car1);/***?output:?*?Car?[name=Audi]?*?Car?[name=BMW]*?*/}Bean的生命周期
????正常情況下,spring加載bean時,首先會調用構造函數,接著對property賦值時調用setter方法。
????如果需要對bean有更多的控制,可以設置init-method與destroy-method屬性,修改一下car對象,加入init與destory方法:
package?cn.net.bysoft.lesson4;public?class?Car?{public?Car()?{System.out.println("1.執行了構造函數。");}public?void?init()?{System.out.println("3.執行初始化。");}public?void?destory()?{System.out.println("5.執行銷毀。");}@Overridepublic?String?toString()?{System.out.println("4.使用bean方法。");return?"Car?[name="?+?name?+?"]";}public?String?getName()?{return?name;}public?void?setName(String?name)?{System.out.println("2.調用setter方法。");this.name?=?name;}private?String?name;}????在配置文件中為bean配置init-method與destory-method:
<bean?id="car3"?class="cn.net.bysoft.lesson4.Car"?init-method="init"destroy-method="destory"?scope="singleton"><property?name="name"?value="Audi"></property> </bean>????在進行測試,看看各個方法的執行順序:
@Testpublic?void?testCycle()?{Car?car?=?(Car)?ctx.getBean("car3");System.out.println(car);ctx.close();}執行了構造函數
執行了setter()方法
執行了init()方法
執行了destory()方法
使用bean的后置處理器
????上面的做法是為單個類進行更多的初始化控制,還可以配置全局的初始化控制,做法為,創建一個類使用實現BeanPostProcessor接口,將該類配置到spring配置文件中即可:
package?cn.net.bysoft.lesson4;import?org.springframework.beans.BeansException; import?org.springframework.beans.factory.config.BeanPostProcessor;public?class?MyBeanPostProcessor?implements?BeanPostProcessor?{@Override//?后置初始化處理public?Object?postProcessAfterInitialization(Object?bean,?String?beanName)throws?BeansException?{System.out.println("after..."?+?bean.getClass()?+?",?"?+?beanName);return?bean;}@Override//?前置初始化處理public?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)throws?BeansException?{System.out.println("before..."?+?bean.getClass()?+?",?"?+?beanName);return?bean;}} <bean?id="car4"?class="cn.net.bysoft.lesson4.Car"?init-method="init"destroy-method="destory"?scope="singleton"><property?name="name"?value="BMW"></property></bean><bean?class="cn.net.bysoft.lesson4.MyBeanPostProcessor"></bean> @Testpublic?void?testBeanPostProcessor()?{Car?car?=?(Car)?ctx.getBean("car4");System.out.println(car);ctx.close();}????通過結果可以看到,配置的處理器before在init方法前被調用,after在init方法后調用。
轉載于:https://my.oschina.net/u/2450666/blog/663154
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的学习Spring(六) -- Spring中Bean的作用域以及生命周期的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java数据结构与排序算法——堆和堆排序
- 下一篇: javascript 函数 add(1)