本文主要介紹spring創(chuàng)建bean的過程概述(spring創(chuàng)建bean的三種),下面一起看看spring創(chuàng)建bean的過程概述(spring創(chuàng)建bean的三種)相關(guān)資訊。
創(chuàng)建spring bean的過程介紹了創(chuàng)建factorybean的方法,然后介紹了創(chuàng)建factorybean的方法。在創(chuàng)建spring bean的過程中,會(huì)分為創(chuàng)建單例bean和創(chuàng)建原型bean。一般來說,在spring中,幾乎所有的對(duì)象都是由singleton創(chuàng)建的,除非有其他業(yè)務(wù)需要設(shè)置為其他作用域的bean,所以我們重點(diǎn)以創(chuàng)建singleton beans為例。
singleton bean的創(chuàng)建在創(chuàng)建時(shí)會(huì)調(diào)用getbean,然后是dogetbean。一般來說,在spring中,只要是以do開頭的方法,基本上都是真正的工作方法,所以let 讓我們看看dogetbean方法的源代碼:
protected t t dogetbean(string name,@nullable classt requiredtype,@nullable object[] args,僅布爾類型檢查)拋出bean異常{//解析為規(guī)范的bean名稱,因?yàn)樗赡苁莊actorybean前綴bean或別名bean string bean name = transformed bean name(name);對(duì)象bean//eagle檢查手動(dòng)注冊(cè)的單體的單體緩存。//獲取bean對(duì)象共享實(shí)例=獲取緩存中的singleton(bean name);if (sharedinstance!= null args = = null){ bean = getobjectforbean instance(shared instance,name,beanname,null);}//如果不在緩存中,否則{//省略代碼...//檢查此工廠中是否存在bean定義。//檢查父類容器//省略代碼...如果(!typecheckonly) {//標(biāo)記已創(chuàng)建markbeanascreated(bean name);}試試{//合并bean定義rootbean定義mbd = getmergedlocalbeandefinition(bean name);checkm: dependenson){ if(is dependent(bean name,dep)){//省略代碼...}//注冊(cè)依賴bean,放入集合registerdependent bean (dep,bean name);try {//create bean get bean(dep);} catch(nosuchbeandifinitenexception ex){//省略代碼...} } }/createbean instance . if(mbd . issing leton){//如果是singleton,就創(chuàng)建bean共享實(shí)例= get singleton (beanname,-{ try {//create bean return create bean(bean name,mbd,args);} catch (beansexception ex) {//省略代碼...}});//在獲取bean對(duì)象時(shí),會(huì)檢查獲取的對(duì)象是否為factor bean = getobjectforbean instance(shared instance,name,beanname,mbd);}//如何創(chuàng)建原型函數(shù)else if (mbd.isprototype) {//省略代碼...} else {//省略代碼...}} catch (beansexception ex) {//省略代碼...} }//省略代碼...返回(t)bean;}去掉不重要的代碼,可以看到是先從緩存中獲取的。如果沒有獲得,就會(huì)進(jìn)行一些列檢查,最后檢查是否是singleton bean。如果是,將調(diào)用getsingleton方法,還有一個(gè)beanname,objectfactory的lambda表達(dá)式,表達(dá)式中有一個(gè)createbean方法,就是創(chuàng)建的bean方法。
那么什么時(shí)候調(diào)用cratebean方法呢?
答案是執(zhí)行l(wèi)ambda表達(dá)式的具體方法。讓 讓我們看看這個(gè)objectfactory接口是什么。
objectfactory對(duì)象工廠直接查看源代碼:
@ functional interface public interface objectfactory t {/* * *返回此工廠管理的對(duì)象的實(shí)例(可能是共享的或獨(dú)立的)*。* @返回結(jié)果實(shí)例* @創(chuàng)建錯(cuò)誤時(shí)拋出beans exception */t getobject拋出beans exception;}這個(gè)接口是一個(gè)函數(shù)接口,可以直接用于lambda表達(dá)式。當(dāng)調(diào)用getobject方法時(shí),實(shí)際執(zhí)行的是lambda表達(dá)式中的方法。
看看getsingleton方法的源代碼:
公共對(duì)象getsingleton(string beanname,objectfactory?singleton factory){ assert . not null(bean name, bean名稱不能為空);synchronized(this . singleton objects){ object singleton object = this . singleton objects . get(bean name);if(singleton object = = null){ if(this。singleton currently industration){//省略代碼...}//省略。密碼...//在創(chuàng)建singleton(bean name)之前,檢查正在創(chuàng)建的singleton對(duì)象并將其添加到集合中;//設(shè)置為新的singleton對(duì)象標(biāo)識(shí)符boolean newsingleton = false//設(shè)置異常集合,發(fā)生異常時(shí)將異常添加到集合中。布爾recordsupressedexceptions =(this。隱藏的異常= = null);if(recordsuppressedexceptions){ this . suppressedexceptions = new linked hashset;} try {//執(zhí)行特定方法并調(diào)用cratebean方法singleton object = singleton factory。getobject;//singleton = true作為新的singleton對(duì)象;} catch(illegalstateexception ex){//省略代碼...} catch(beancreateexception ex){/省略代碼...} finally { if(recordsupressedexceptions){ this . suppressed exceptions = null;}//在創(chuàng)建singleton creation (beanname)后檢查并移除singleton對(duì)象;} if (newsingleton) {//將singleton (beanname,singleton object)添加到緩存中;} }返回singletonobject}此處執(zhí)行后,將執(zhí)行l(wèi)ambda表達(dá)式中的createbean方法:
受保護(hù)對(duì)象創(chuàng)建bean (string beanname,rootbean definition mbd,@ nullableobject [] args)拋出beancreation異常{//省略代碼...rootbean definition mbd toose = mbd;//確保bean類實(shí)際上在t處被解析他的觀點(diǎn),并且//在動(dòng)態(tài)解析的類//不能存儲(chǔ)在共享的合并bean定義中的情況下,克隆bean定義。//解析bean的類用來反映和創(chuàng)建對(duì)象類?resolved class = resolvebean class(mbd,bean name);if (resolvedclass!= null!mbd . hasbean classmbd . getbean class name!= null){ mbd toose = new root bean definition(mbd);mbd tuse . setbean class(resolved class);}//preparemethodoverrides。try {//方法重寫準(zhǔn)備要使用的lookup-methodreplace-methodmbd。preparethodoverrides;} catch(beadefinitionvalidationexception ex){//省略代碼...} try {//給beanpostprocessors一個(gè)返回代理而不是目標(biāo)bean實(shí)例的機(jī)會(huì)。//提前解析實(shí)例化,用instantiationawarebeanpostprocessor實(shí)現(xiàn)object bean = resolvebeforeinstantiation(bean name,mbd to use);如果(豆!= null) {返回bean}} catch (throwable ex) {//省略代碼...} try {//實(shí)例化初始化bean //真正創(chuàng)建bean對(duì)象bean instance = docreatebean (bean,mbd要用,args);//省略代碼...返回beaninstance} catch (beancreationexception | implicitlyappearedsingletonexception ex){//省略代碼...} catch (throwable ex) {//省略代碼...}}首先解析bean的類型,主要用于后期反射創(chuàng)建對(duì)象,在rootbeandefinition中設(shè)置,然后覆蓋方法。
spring方法覆蓋實(shí)際方法覆蓋意味著當(dāng)使用lookup-method和replacred winter/a * @自1.0 * */公共抽象類myhouse {公共抽象my car park;}定義我的車
/* * * * @作者a redwinter/a * @自1.0 * */公共接口mycar {/* *買車* @還車*/mycar buy;}定義實(shí)現(xiàn)類:
寶馬:
/* * * * @作者a red winter/a * @自1.0 **/public class寶馬實(shí)現(xiàn)mycar { @ override public mycar buy{ rred winter/a * @自1.0 **/public類ben實(shí)現(xiàn)mycar { @ override public mycar buy{ return this;}}xml配置:
?xml版本= 1.0 encoding = utf-8 ?bxmlns : xsi = http://www.w3.org/2001/ xml schema-實(shí)例和xmlns : cont cho 13-@ . com schema location = http://www.springframework.org/sc://www.springframework.org/schema/cont id = 我的房子 class = com . red winter . test . method override . lookup method . my house 查找方法名稱= 公園 bean = 寶馬汽車公司//bean bean id = 我的房子 class = com . red winter . test . method override . lookup method . my house 查找方法名稱= 公園 bean = 本 //bean!設(shè)置為原型bean id = 寶馬汽車公司class = com . red winter . test . method override . lookup method . bmw scope = 原型和/bean id = 本 class = com . r * @自1.0 * */public class lookup test {/* * lookup-method用于求解單實(shí)例對(duì)象和多實(shí)例對(duì)象的*/@testpublic void lookuptest。{ classpathmlaplicationcontext = new classpathmlaplicationcontext( class path : method-override . xml );my house my house =(my house)context . get bean( 我的房子 );my house my house 1 =(my house)context . get bean( 我的房子 );system . out . println(my house . park);system . out . println(my house 1 . park);}}輸出:
com . red winter . test . method override . lookup method . bmw @ 4a 765 com . red winter . test . method override . lookup method . bmw @ 3e 6358這里myhouse是singleton對(duì)象,myhouse1調(diào)用的方法每次都是不同的對(duì)象。
spring是如何實(shí)現(xiàn)方法覆蓋的?源代碼太復(fù)雜,太復(fù)雜。這里,直接看執(zhí)行過程:
只要設(shè)置了lookup-method標(biāo)記,spring將創(chuàng)建一個(gè)lookupoverride類,并在加載beandefinition和執(zhí)行方法parselookupoverridesubelements時(shí)將其放入beandefinition的methodoverrides屬性中。在創(chuàng)建bean時(shí),我們會(huì)判斷這個(gè)屬性值是否有值。如果是,我們?cè)趯?shí)例化對(duì)象時(shí)會(huì)得到一個(gè)實(shí)例化策略,然后調(diào)用simpleinstationstrategy # instantiate方法,然后用cglib實(shí)例化,創(chuàng)建一個(gè)enhancer增強(qiáng)類,設(shè)置回調(diào)類型如下:
私有靜態(tài)最終類。[] callback_types =新類?[]{noop.class,lookupoverridemethodinterceptor . class,replaceoverridemethodinterceptor . class };最后,當(dāng)方法被執(zhí)行時(shí),它將被調(diào)用到回調(diào)類lookupoverridemethodinterceptor,然后bean將被創(chuàng)建:
@ override public object intercept(object obj,method method,object[] args,method proxy mp)throwable {//cast是安全的,因?yàn)閏allbackfilter篩選器是有選擇地使用的。lookup override lo =(lookup override)getbean definition。getmethodoverrides。getoverride(方法);assert.state(lo!= null, 找不到lookup override );object[]args tous: null);//如果沒有-arg,則不要 t in siston args at all if(string utils。hast: this . own:豆);} : this . owner . get bean(method . get returntype);}}那個(gè) 本文就到這里,下一篇繼續(xù)。
標(biāo)簽:
方法代碼
了解更多spring創(chuàng)建bean的過程概述(spring創(chuàng)建bean的三種)相關(guān)內(nèi)容請(qǐng)關(guān)注本站點(diǎn)。