真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringBeanDefinition的加載過(guò)程

本篇內(nèi)容主要講解“Spring BeanDefinition的加載過(guò)程”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Spring BeanDefinition的加載過(guò)程”吧!

專注于為中小企業(yè)提供成都網(wǎng)站建設(shè)、成都網(wǎng)站制作服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)成安免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了近1000家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

一.XML定義

?XML配置的加載由AbstractXmlApplicationContext實(shí)現(xiàn),方法實(shí)現(xiàn)如下:

Spring BeanDefinition的加載過(guò)程

Spring BeanDefinition的加載過(guò)程

?主要是實(shí)例化了一個(gè)XmlBeanDefinitionReader對(duì)象,對(duì)其設(shè)置了Environment對(duì)象(具體過(guò)程可以上一篇)等后,調(diào)用XmlBeanDefinitionReader進(jìn)行解析。直接跟蹤進(jìn)去,得到如下內(nèi)容:

Spring BeanDefinition的加載過(guò)程

?其中參數(shù)inputSource為XML配置文件,Resource則該配置文件的描述,主要描述了該配置文件在classpath中的位置和可用于加載該配置文件的加載器。doLoadDocument方法比較簡(jiǎn)單,主要是加載指定的配置文件,返回一個(gè)JDK內(nèi)置的XML解析Document對(duì)象,以便于解析XML DOM節(jié)點(diǎn)。

?重點(diǎn)看下registerBeanDefinitions方法,如下:

Spring BeanDefinition的加載過(guò)程

?該方法最終委托給了BeanDefinitonDocumentReader來(lái)完成Bean的解析。在這之前,初始化了一系列相關(guān)對(duì)象。包括:

  1. 使用DefaultBeanDefinitionDocumentReader作為BeanDefinitionDocumentReader接口的實(shí)現(xiàn)

  2. 創(chuàng)建了一個(gè)XmlReaderContext用于保存解析過(guò)程中使用到的各個(gè)相關(guān)對(duì)象,如資源描述對(duì)象Resource、ReaderEventListener事件監(jiān)聽(tīng)器、XmlBeanDefinitionReader以及NamespaceHandlerResolver命名空間解析器。其中劃重點(diǎn)的是DefaultNamespaceHandlerResolver,該類完成了自定義XML格式的解析,后面會(huì)有講解。

?初始相關(guān)對(duì)象后便將解析過(guò)程委托給了DefaultBeanDefinitionDocumentReader來(lái)進(jìn)行處理,該類的重點(diǎn)為parseBeanDefinitions方法,在調(diào)用該方法前,先初始化了一個(gè)BeanDefinitionParserDelegate對(duì)象,如下:

Spring BeanDefinition的加載過(guò)程

?并將該delegate對(duì)象傳入了parseBeanDefinitions方法。BeanDefinitionParserDelegate主要提供了命名空間為http://www.springframework.org/schema/beans(下面簡(jiǎn)寫為beans空間)的XML文件解析過(guò)程。該命名空間定義了4個(gè)主要的XML標(biāo)簽,分別為beans、beanimportalias以及這些標(biāo)簽對(duì)應(yīng)的屬性,如下為該命名空間的示例,定義了一個(gè)基礎(chǔ)的Bean。

Spring BeanDefinition的加載過(guò)程

?需要注意的是,上面在初始化BeanDefinitionParserDelegate后會(huì)先解析XML上標(biāo)簽上的默認(rèn)屬性,包括:default-lazy-initdefault-merge、default-autowire、default-dependency-check、default-autowire-candidates、default-init-methoddefault-destroy-method這些全局屬性。

?下面看下parseBeanBefinitoins方法:

Spring BeanDefinition的加載過(guò)程

?該方法會(huì)對(duì)當(dāng)前節(jié)點(diǎn)所屬命名空間進(jìn)行判斷,分為默認(rèn)命名空間和自定義命名空間,其中默認(rèn)命名空間指的是上面提到的beans空間。對(duì)于默認(rèn)命名空間,會(huì)逐一解析每個(gè)DOM子節(jié)點(diǎn),判斷子節(jié)點(diǎn)的命名空間,最終委托給兩個(gè)方法:處理默認(rèn)命名空間的parseDefaultElement方法和處理自定義命名空間的parseClustomElement方法。

Spring BeanDefinition的加載過(guò)程

?parseDefautlElement方法如上, 對(duì)beans空間定義的各個(gè)標(biāo)簽分別進(jìn)行了處理:

  1. 解析import標(biāo)簽時(shí),會(huì)讀取resource屬性指定的配置文件,加載后再解析該文件中的bean定義。

  2. 解析alias標(biāo)簽時(shí),讀取標(biāo)簽的name和alias屬性,添加到BeanRegistry緩存中。

  3. 解析bean標(biāo)簽時(shí),直接委托給BeanDefinitionParserDelegate來(lái)處理,過(guò)程為:

    對(duì)于步驟3.d,處理過(guò)程為:

    1. 獲取class屬性值

    2. 獲取parent屬性值

    3. 初始化GenericBeanDefinition實(shí)例

    4. 解析bean節(jié)點(diǎn)的屬性,設(shè)置到BeanDefinition中,包括:scope、abstract、lazy-init、autowired、dependency-checkautowire-candidate、primaryinit-method、destroy-method、factory-method、factory-bean

    5. 解析description子節(jié)點(diǎn),獲取值設(shè)置bean的描述內(nèi)容

    6. 解析meta子節(jié)點(diǎn)列表,獲取key、value值設(shè)置附加元數(shù)據(jù)信息

    7. 解析lookup-method子節(jié)點(diǎn)列表,獲取name、bean值設(shè)置方法注入信息

    8. 解析replaced-method子節(jié)點(diǎn)列表,獲取值設(shè)置需要?jiǎng)討B(tài)代理的方法信息

    9. 解析constructor-arg子節(jié)點(diǎn)列表,獲取值設(shè)置構(gòu)造參數(shù)信息

    10. 解析property子節(jié)點(diǎn)列表,獲取值設(shè)置屬性信息

    11. 解析qualifier子節(jié)點(diǎn)列表,獲取值進(jìn)行設(shè)置

    12. 獲取id屬性值作為beanName

    13. 獲取name屬性值作為aliases,該屬性值可以配置多個(gè),以 , 或者 ; 符進(jìn)行分割,將作為該bean的別名使用;若id值為空,且name不為空,則使用第一個(gè)name值作為id值

    14. 檢查beanName和aliases的唯一性

    15. 解析bean其他配置,生成GenericBeanDefinition對(duì)象

    16. 若beanName為空,則為其分配一個(gè)

?上面解析完bean的配置后,會(huì)再處理子節(jié)點(diǎn)中其他命名空間的配置,使用NamespaceHandler的decorate方法,用以修改Bean定義內(nèi)容,這部分將使用下面的內(nèi)容,放在后面一起講。

  1. 解析beans標(biāo)簽時(shí),會(huì)進(jìn)行遞歸處理

?如上,默認(rèn)命名空間主要用于解析bean的定義,經(jīng)過(guò)上面的處理,bean定義的解析就已經(jīng)完成,會(huì)將實(shí)例對(duì)象注冊(cè)到上下文中進(jìn)行保存

?下面介紹parseClustomElement方法,顧名思義,該方法主要用來(lái)處理自定義命名空間的XML標(biāo)簽的,可以當(dāng)做是spring XML配置處理的一種擴(kuò)展手段,如下,為該方法的內(nèi)容:

Spring BeanDefinition的加載過(guò)程

?主要委托給了NamespaceHandlerResolver,通過(guò)查找到對(duì)應(yīng)節(jié)點(diǎn)對(duì)應(yīng)命名空間的Handler,調(diào)用該Handler的parse方法進(jìn)行處理。

?前面說(shuō)過(guò),NamespaceHandlerResolver使用了DefaultNamespaceHandlerResolver作為實(shí)現(xiàn),跟蹤resolve方法進(jìn)去如下:

Spring BeanDefinition的加載過(guò)程

?過(guò)程為:

  1. 獲取已有的Handler處理列表,返回結(jié)果為一個(gè)Map,Key為XML命名空間,值可能為代表對(duì)應(yīng)Handler類型的Spring對(duì)象或者已經(jīng)實(shí)例化后的Handler對(duì)象,取決于之前是否已經(jīng)調(diào)用過(guò)

  2. 若指為Handler對(duì)象,則直接返回

  3. 若為String對(duì)象,表明未初始化過(guò),則初始化該類,并執(zhí)行init初始化方法,然后將其重新返回Map中

?對(duì)于第(1)步中Handler處理列表的獲取,Spring會(huì)掃描classpath中所有位于META-INF中的spring.handlers配置文件,將所有內(nèi)容讀取到一個(gè)Map中并返回。

Spring BeanDefinition的加載過(guò)程

?如上,為spring-context模塊提供的spring.handlers文件,提供了該模塊自定義命名空間標(biāo)簽的支持。如下為自定義命名空間的例子:

Spring BeanDefinition的加載過(guò)程

?主要引入了context空間的spring-configured標(biāo)簽和annotation-config標(biāo)簽。

?至此,介紹了XML配置下的bean解析。

二、注解配置

?下面介紹Spring以注解的方式進(jìn)行bean加載的過(guò)程,如下,為開(kāi)啟注解加載所需要的配置:

Spring BeanDefinition的加載過(guò)程

?根據(jù)前面的內(nèi)容,component-scanhttp://www.springframework.org/schema/context命名空間中的標(biāo)簽,處理對(duì)象在spring-context模塊的spring.handlers文件中定義,對(duì)應(yīng)的是類org.springframework.context.config.ContextNamespaceHandler,如下:

Spring BeanDefinition的加載過(guò)程

?查看該類,可以知道,component-scan由ComponentScanBeanDefinitionParser處理,如下:

Spring BeanDefinition的加載過(guò)程

?主要過(guò)程為:

  1. 獲取base-package屬性內(nèi)容賦值給basePackage

  2. 替換basePackage中的占位符內(nèi)容

  3. 根據(jù) , ; \t \n 分割符分割basePackage,得到多個(gè)包路徑

  4. 解析component-scan配置內(nèi)容,返回ClassPathBeanDefinitionScanner對(duì)象

    1. 解析設(shè)置use-default-filters參數(shù)

    2. 解析設(shè)置resource-pattern參數(shù)

    3. 解析設(shè)置name-generator參數(shù)

    4. 解析設(shè)置scope-resolver、scoped-proxy等參數(shù)

    5. 解析設(shè)置include-filterexclude-filter等參數(shù), ClassPathBeanDefinitionScanner對(duì)象再初始化時(shí)默認(rèn)增加了org.springframework.stereotype. Component、javax.annotation.ManagedBean和javax.inject.Named幾種注解

  5. 調(diào)用ClassPathBeanDefinitionScanner的doScan方法執(zhí)行掃描,將符合的類并注冊(cè)到上下文中然后返回

  6. 解析annotation-config參數(shù),如果為true(默認(rèn)為true)則自動(dòng)注冊(cè)一系列用于后置解析的注解處理類定義到上下文中 這里重點(diǎn)看下第(5)步和第(6)步

?第(5)執(zhí)行掃描時(shí),會(huì)遍歷第(3)步返回的所有路徑,對(duì)于每個(gè)路徑,會(huì)調(diào)用父類ClassPathScanningCandidateComponentProvider的findCandidateComponents方法,返回該路徑下所有符合要求的Bean,如下:

Spring BeanDefinition的加載過(guò)程

?ClassPathScanningCandidateComponentProvider會(huì)找到指定路徑所有的類,包裝為Resource[]對(duì)象,對(duì)于每個(gè)Resource,會(huì)使用SimpleMetadataReaderFactory工廠類為每個(gè)Resouce對(duì)象新建一個(gè)SimpleMetadataReader對(duì)象,該對(duì)象用于解析類的信息,需要注意的是,在初始化SimpleMetadataReader對(duì)象的時(shí)候就會(huì)執(zhí)行解析動(dòng)作,將結(jié)果存為ClassMetadata數(shù)據(jù)和AnnotationMetadata數(shù)據(jù),前者用于存儲(chǔ)類的定義信息,包括類名,是否接口,包含的屬性等信息,后者則包含所有的注解信息。獲取SimpleMetadataReader對(duì)象后,會(huì)判斷該類是否符合component-scanner定義的include-filterexclude-filter中定義的內(nèi)容,注意,默認(rèn)包含了@Component等對(duì)象,所以默認(rèn)會(huì)加載所有有@Component注解且所有有@Component元注解注解(如@Service、@Repository)的類。若符合要求,則將該類包裝為ScannedGenericBeanDefinition對(duì)象,同時(shí)會(huì)檢查該類不能為一個(gè)接口且不能依賴一個(gè)內(nèi)部非靜態(tài)類,若符合,則添加到待返回列表中。

?執(zhí)行完上面的findCandidateComponents方法后,會(huì)為其分配一個(gè)beanName,用于內(nèi)部使用,之后會(huì)調(diào)用AnnotationConfigUtils的processCommonDefinitionAnnotations方法,該方法會(huì)對(duì)上面返回的BeanDefinition解析一些基本的注解屬性并進(jìn)行設(shè)置,包括@Lazy、@Primary、@DependsOn@Role@Description。完成該步后會(huì)判斷該bean是否已經(jīng)存在,若不存在,則添加到上下文中。

?第(6)步的代碼如下:

Spring BeanDefinition的加載過(guò)程

?重點(diǎn)在后半部分,會(huì)調(diào)用AnnotationConfigUtils的registerAnnotationConfigProcessors方法,該方法添加了一系列用于后置解析的注解處理類定義到上下文中,包括:

  1. 添加ConfigurationClassPostProcessor處理器(BeanDefinitionRegistryPostProcessor),添加@Configuration功能,對(duì)應(yīng)bean為org.springframework.context.annotation.internalConfigurationAnnotationProcessor

  2. 添加AutowiredAnnotationBeanPostProcessor處理器(SmartInstantiationAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor),添加@Autowired@Value功能,對(duì)應(yīng)bean為org.springframework.context.annotation.internalAutowiredAnnotationProcessor

  3. 添加RequiredAnnotationBeanPostProcessor處理器(SmartInstantiationAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor),添加@Required功能,對(duì)應(yīng)bean為org.springframework.context.annotation.internalRequiredAnnotationProcessor

  4. 添加CommonAnnotationBeanPostProcessor處理器(InstantiationAwareBeanPostProcessor 、DestructionAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor、BeanPostProcessor),添加@PostConstruct、@PreDestroy功能,對(duì)應(yīng)bean為org.springframework.context.annotation.internalCommonAnnotationProcessor

  5. 添加PersistenceAnnotationBeanPostProcessor處理器(InstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor),添加@PersistenceUnit、@PersistenceContext功能,對(duì)應(yīng)bean為org.springframework.context.annotation.internalPersistenceAnnotationProcessor

  6. 添加EventListenerMethodProcessor,添加@EventListener功能,對(duì)應(yīng)bean為org.springframework.context.event.internalEventListenerProcessor

  7. 添加DefaultEventListenerFactory,對(duì)應(yīng)bean為org.springframework.context.event.internalEventListenerFactory

?以上各個(gè)bean在添加前都會(huì)先判斷是否已經(jīng)存在改定義,若不存在才增加,因而可以通過(guò)在添加相應(yīng)bean的方式,修改對(duì)應(yīng)的處理功能。

?PS:第(6)步添加注解后置處理的方法其實(shí)也是annotation-config這個(gè)標(biāo)簽功能的主要處理方法。由上可知annotation-config的處理類為AnnotationConfigBeanDefinitionParser,該類內(nèi)部其實(shí)也是調(diào)用了AnnotationConfigUtils的registerAnnotationConfigProcessors方法來(lái)完成注解的功能,具體代碼如下:

Spring BeanDefinition的加載過(guò)程

三、接口回調(diào)

?結(jié)合之前Spring啟動(dòng)的內(nèi)容,接上上面的內(nèi)容,可以得到如下的接口回調(diào)順序

Spring BeanDefinition的加載過(guò)程

?因?yàn)镮nstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor等接口繼承自MergedBeanDefinitionPostProcessor接口,MergedBeanDefinitionPostProcessor接口繼承自BeanPostrProcessor,實(shí)現(xiàn)類上存在重疊,這里先根據(jù)講解順序排序。

到此,相信大家對(duì)“Spring BeanDefinition的加載過(guò)程”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


名稱欄目:SpringBeanDefinition的加載過(guò)程
當(dāng)前路徑:http://weahome.cn/article/ghjipi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部