關(guān)于@Configuration的作用說明
一、問題描述
在項(xiàng)目中,通常都會(huì)配置一個(gè)或者多個(gè)加了@Configuration注解的配置類,那么@Configuration這個(gè)注解到底有神馬作用勒?
@ComponentScan("com") public class AppConfig { ?? ?@Bean ?? ?public TestDao testDao() { ?? ??? ?return new TestDao(); ?? ?} }
public class Test { ?? ?public static void main(String[] args) { ?? ??? ?AnnotationConfigApplicationContext acc = new AnnotationConfigApplicationContext(AppConfig.class); ?? ?} }
public class TestDao { ?? ?public TestDao(){ ?? ??? ?System.out.println("testDao"); ?? ?} }
執(zhí)行上面的代碼,我們會(huì)發(fā)現(xiàn)當(dāng)我們不加@Configuration這個(gè)注解的時(shí)候我們的TestDao 這個(gè)類還是還是會(huì)被實(shí)例化,也會(huì)打印testDao。我們的spring環(huán)境也可以正常運(yùn)行。
那么我們的@Configuration注解是來解決什么問題的勒?
我們來看一下下面這段代碼。當(dāng)我們?cè)贏ppConfig中有2個(gè)方法,而且第二個(gè)方法調(diào)用了第一個(gè)方法。
@ComponentScan("com") public class AppConfig { @Bean public TestDao testDao() { return new TestDao(); } @Bean public TestDao1 testDao1() { testDao(); return new TestDao1(); } }
public class TestDao1 { public TestDao1(){ System.out.println("testDao1"); } }
不加@Configuration的打印結(jié)果:
加上@Configuration的打印結(jié)果:
二、分析
從表面來看,當(dāng)我們不加@Configuration注解的時(shí)候,我們的TestDao會(huì)被實(shí)例化兩次,這違背了我們spring默認(rèn)單例的設(shè)計(jì)原則,當(dāng)加上我們的@Configuration注解的時(shí)候,TestDao只被實(shí)例化了一次。
那么其底層到底做了什么,讓我們來深追一下spring源碼吧。
當(dāng)我們解析beanAppcofig的時(shí)候,會(huì)給它的一個(gè)屬性標(biāo)識(shí)為Full,表明它是一個(gè)全注解類。
然后在我們調(diào)用ConfigurationClassPostProcessor.postProcessBeanFactory()方法的時(shí)候會(huì)去判斷我們的bean工廠當(dāng)中是否有bean需要進(jìn)行cglib代理。
然后遍歷configBeanDefs這個(gè)map
cglib代理主要是對(duì)我們的方法進(jìn)行攔截增強(qiáng);當(dāng)我們執(zhí)行AppConfig中的方法的時(shí)候會(huì)去執(zhí)行cglib代理類中的代理方法,主要就是callBacks中的方法。
isCurrentlyInvokedFactoryMethod(beanMethod))
會(huì)判斷我們的執(zhí)行方法和我們的調(diào)用方法是否是同一個(gè);如果是同一個(gè)就調(diào)用父類的方法進(jìn)行new;如果不是就調(diào)用$$beanFactory.getBean()獲取。
三、總結(jié)
加上@Configuration注解主要是給我們的類加上了cglib代理。
在執(zhí)行我們的配置類的方法時(shí),會(huì)執(zhí)行cglib代理類中的方法,其中有一個(gè)非常重要的判斷,當(dāng)我們的執(zhí)行方法和我們的調(diào)用方法是同一個(gè)方法時(shí),會(huì)執(zhí)行父類的方法new(cglib代理基于繼承);當(dāng)執(zhí)行方法和調(diào)用方法不是同一個(gè)方法時(shí)會(huì)調(diào)用beanFactory.getBean獲取。
相關(guān)文章
JavaWeb Session失效時(shí)間設(shè)置方法
這篇文章主要介紹了JavaWeb Session失效時(shí)間設(shè)置方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12功能強(qiáng)大的TraceId?搭配?ELK使用詳解
這篇文章主要為大家介紹了功能強(qiáng)大的TraceId?搭配?ELK使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09java 獲取request中的請(qǐng)求參數(shù)代碼詳解
這篇文章主要介紹了java 獲取request中的請(qǐng)求參數(shù)的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-05-05Java源碼解析HashMap的tableSizeFor函數(shù)
今天小編就為大家分享一篇關(guān)于Java源碼解析HashMap的tableSizeFor函數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01WebSocket實(shí)現(xiàn)數(shù)據(jù)庫更新時(shí)前端頁面刷新
這篇文章主要為大家詳細(xì)介紹了WebSocket實(shí)現(xiàn)數(shù)據(jù)庫更新時(shí)前端頁面刷新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法
這篇文章主要介紹了SpringCloud服務(wù)實(shí)現(xiàn)同時(shí)使用eureka和nacos方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01