Spring 依賴注入原理二

上篇 Spring 依賴注入原理

接著上篇的文章未完待續部分,開始分享Spring註解依賴注入也稱為自動裝配。實際專案中常碰到如下場景跨業務服務之間呼叫如下圖所示。在工作多年後,翻閱原始碼才知道其原理。

package test;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。beans。factory。annotation。Value;import org。springframework。stereotype。Service;@Servicepublic class UserService { @Autowired private OrderService orderService;}

一 註解依賴注入原理

啟動以下面這種為例載入配置類Cfg。java,分享原理

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Cfg。class);

1 在AnnotationConfigApplicationContext建構函式內部執行doRegisterBean函式,傳入引數beanClass建立AnnotatedGenericBeanDefinition例項,賦值給abd變數,透過abd呼叫函式為屬性賦值,最後BeanDefinition例項註冊到集合中。

Spring 依賴注入原理二

建立AnnotatedGenericBeanDefinition例項

Spring 依賴注入原理二

註冊到集合中

2 執行函式invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)內部執行函式invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory。getApplicationStartup());取出加了@ComponentScan註解屬性值於集合中。

Spring 依賴注入原理二

呼叫函式invokeBeanFactoryPostProcessors

Spring 依賴注入原理二

Spring 依賴注入原理二

取出加了@ComponentScan註解屬性值於集合中

執行this。componentScanParser。parse(componentScan, sourceClass。getMetadata()。getClassName());迴圈取出解析ComponentScan註解的basePackages屬性值,接著解析出路徑下的class檔案並對應建立Resource例項存於陣列中賦值給變數resources,迴圈遍歷resources取出加了註解@Component並建立BeanDefinition例項存於set集合中再迴圈存於registerBeanDefinition,最後返回值賦值給變數scannedBeanDefinitions。

Spring 依賴注入原理二

解析配置類

Spring 依賴注入原理二

呼叫parse函式,解析轉換配置類

Spring 依賴注入原理二

載入註解@ComponentScan下的basePackage屬性值並建立對應Resource例項

Spring 依賴注入原理二

返回Set例項

3 迴圈遍歷儲存beanname的List集合,取出beanname作為鍵到快取查詢,當獲取不到,執行singleFactory。getObject(),使用建構函式反射建立例項。

Spring 依賴注入原理二

迴圈例項化每個bean

Spring 依賴注入原理二

例項化bean

4 執行populateBean函式,對已建立的例項的屬性賦值。迴圈遍歷List 例項,當取出AutowiredAnnotationBeanPostProcessor例項時,開始對待注入的屬性賦值,過程是執行函式findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)找出類中待注入的屬性,封裝到InjectionMetadata中,然後返回,再執行InjectionMetadata例項的函式inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs),迴圈遍歷待注入的屬性傳入引數執行inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs),解析待注入的值(非原生的呼叫getBean()生成相應型別例項),最後執行Filed例項的set(Object obj, Object value),反射為bean例項的屬性附上值。

Spring 依賴注入原理二

bean例項屬性填充,呼叫初始化函式