spring 中使用@Configuration注解修飾的類為什么必須被代理
一、問題描述和場景
先來一段代碼:如下,內容很簡單,AopTest被configuration修飾,里面有兩個方法,p()實例返回對象person,a()方法引用p(),同時返回對象A。並且都被@bean注解修飾。

用這個場景來驗證spring加@configuration注解的類都必須被代理:
首先有一個問題;如果方法P在調用方法A,在不生成代理對象的時候,此時會創建兩次Person對象?那么創建兩次對象,即在spring里非單例對象,這樣的話無法保證spring中配置類的屬性單例原則。
那么有沒有一種可能,通過代理方法來管理person對象的創建,如果調用方法p()會交由代理去判斷person對象是否已經被創建成功,如果是那么則交由代理對象的proxy.invokeSuper的方法調用父類
去創建;如果沒有則通過代理類$$BeanFactory.getBean的方法創建對象person,從而保證對象只被創建一次,即為單例。
二、源碼分析
1、主函數,register上面的AopTest

2、到refresh()方法,當執行到invokeBeanDefinitionRegistryPostProcessors 方法解析此類,則從map里面遍歷 BeanDefinition ,判斷當前BeanDefinition 的map里面的屬性key -configurationClass 值是full還是lite,剛開始掃描時候為null,則繼續解析,判斷若果加了@Configuration configurationClass 的值設置為full。如下圖所示:

3、調用 invokeBeanFactoryPostPorcessors ,此方法遍歷所有的BeanFactoryPostPorcessors,如下圖,此時的對象還是普通對象,並非生成的代理對象。

4、 在遍歷中會調用到enhanceConfigurationClass ,此方法中獲取regist里面的所有類,遍歷判斷 isfullConfigurationClass 是否為full,若為full,存到一個LinkedHashMap 中,為lite則不存,若map為null ,則返回之后直接new 對象。調用enhanceConfigurationClasses() ,判斷該類是否實現EnhancedConfiguration接口spring完成代理則會讓該類去實現此接口;若沒有被代理則去實現代理 enhancer.create()創建代碼對象,可以看出該對象已經是"aopTest" -> "Generic bean: class [com.mashibing.AopTest$$EnhancerBySpringCGLIB$$fa629855]代理對象

結論: 凡是加了@Configuration注解修飾的類都會被spring代理,目的是為了解決@Bean單例問題
