亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring?IOC中的組件掃描

 更新時(shí)間:2024年04月30日 09:55:41   作者:紙杯沒茶  
通過自動(dòng)掃描,Spring?會自動(dòng)從掃描指定的包及其子包下的所有類,并根據(jù)類上的特定注解將該類裝配到容器中,而無需在?XML?配置文件或?Java?配置類中逐一聲明每一個(gè)?Bean,這篇文章主要介紹了Spring?IOC中的組件掃描,需要的朋友可以參考下

版本 Spring Framework 6.0.9?

1. 前言

通過自動(dòng)掃描,Spring 會自動(dòng)從掃描指定的包及其子包下的所有類,并根據(jù)類上的特定注解將該類裝配到容器中,而無需在 XML 配置文件或 Java 配置類中逐一聲明每一個(gè) Bean。

支持的注解
Spring 支持一系列注解,用于標(biāo)記哪些類應(yīng)被自動(dòng)掃描并作為 Bean 管理。這些注解通常包含:

  • @Component:基礎(chǔ)注解,標(biāo)記一個(gè)類作為 Spring 組件。所有其他特殊用途的組件注解都繼承自此注解。
  • @Repository:用于標(biāo)注 DAO(Data Access Object)類,除了具備 @Component 的功能外,還為數(shù)據(jù)訪問異常提供了特殊的翻譯機(jī)制。
  • @Service:用于標(biāo)注業(yè)務(wù)層(Service)類,強(qiáng)調(diào)這是一個(gè)業(yè)務(wù)相關(guān)的組件。
  • @Controller:用于標(biāo)注 MVC 架構(gòu)中的控制器類,通常在 Spring MVC 中使用,與 Spring Web 相關(guān)的請求處理邏輯相關(guān)聯(lián)。
  • @Configuration:用于標(biāo)注配置類,這類類通常包含 @Bean 方法,用于定義其他 Bean。
  • @RestController:結(jié)合了 @Controller 和 @ResponseBody,適用于構(gòu)建 RESTful Web 服務(wù)的控制器。

例子相關(guān)實(shí)體類

控制層(例子中沒引入spring-web包,注解先使用@Component替代)

服務(wù)層

數(shù)據(jù)訪問層

2. 基于xml

2.1 使用

在 Spring 的XML配置文件中,通過 <context:component-scan> 標(biāo)簽開啟自動(dòng)掃描功能。我們可以配置 base-package 指定掃描路徑。

輸出信息說明每個(gè)實(shí)體類都已加載到容器。

<context:component-scan> 其他配置元素:

  • resource-pattern:可選屬性,用于指定在掃描包路徑下應(yīng)匹配的資源模式。默認(rèn)值為 “**/*.class”,即掃描所有 .class 文件。可以根據(jù)需要修改此模式,例如,僅掃描特定目錄下的類。
  • use-default-filters:布爾屬性,默認(rèn)值為 true。決定是否啟用默認(rèn)的過濾規(guī)則,即查找?guī)в?@Component、@Repository、@Service、@Controller、@Configuration 等注解的類。如果設(shè)置為 false,則需要手動(dòng)配置 和 來指定掃描規(guī)則。
  • scope-resolver:指定一個(gè)自定義的 ScopeMetadataResolver 實(shí)現(xiàn)類,用于確定掃描到的 Bean 的作用域。默認(rèn)情況下,Spring 使用 AnnotationScopeMetadataResolver,根據(jù)類上的 @Scope 注解來確定作用域。
  • scoped-proxy:指定是否為掃描到的帶有作用域注解的 Bean 創(chuàng)建代理。可能的值包括:
    • no(默認(rèn)):不創(chuàng)建代理。
    • interfaces:為實(shí)現(xiàn)了接口的 Bean 創(chuàng)建 JDK 動(dòng)態(tài)代理。
    • targetClass:為未實(shí)現(xiàn)接口或需要保留原始類類型的 Bean 創(chuàng)建 CGLIB 代理。
  • name-generator:指定一個(gè)自定義的 BeanNameGenerator 實(shí)現(xiàn)類,用于生成掃描到的 Bean 的名稱。默認(rèn)使用 AnnotationBeanNameGenerator,根據(jù)類上的 @Component 等注解的 value 屬性或類名生成 Bean 名稱。
  • include-filter 和 exclude-filter:這兩個(gè)元素屬于子標(biāo)簽,用于指定更細(xì)粒度的掃描規(guī)則??梢园醋⒔忸愋汀⒆⒔鈱傩?、全類名模式等進(jìn)行包含或排除。

2.2 掃描原理

  • 當(dāng)我們使用ClassPathXmlApplicationContext作為IOC容器,在refresh方法的obtainFreshBeanFactory階段會創(chuàng)建一個(gè)bean工廠DefaultListableBeanFactory。
  • 當(dāng)前上下文調(diào)用loadBeanDefinitions方法,根據(jù)容器的配置文件加載bean定義。
  • 配置文件中通過 <context:component-scan> 標(biāo)簽開啟自動(dòng)掃描功能,屬于其他命名空間,托管給 ComponentScanBeanDefinitionParser處理。
  • ComponentScanBeanDefinitionParser#parse方法中創(chuàng)建一個(gè)ClassPathBeanDefinitionScanner對象,調(diào)用其scan方法掃描組件并加載到bean工廠中。

其他命名空間

Spring框架除了核心的XML命名空間外,還提供了多個(gè)擴(kuò)展命名空間(除beans以外的命名空間),以支持特定的功能模塊和簡化配置。

  • http://www.springframework.org/schema/beans:核心命名空間,這是最基礎(chǔ)且最常用的命名空間,用于定義bean、設(shè)置屬性、注入依賴、配置構(gòu)造函數(shù)參數(shù)、初始化方法、銷毀方法、自動(dòng)裝配等基本IoC容器功能。http://www.springframework.org/schema/context:
  • context命名空間,提供了對Java配置類、自動(dòng)掃描、注解驅(qū)動(dòng)的bean定義、屬性占位符替換、資源加載等上下文相關(guān)的高級功能的支持。通過此命名空間,可以簡化基于注解的配置,如@Component、@Autowired等。

在實(shí)例化XmlReaderContext時(shí),DefaultBeanDefinitionDocumentReader會創(chuàng)建一個(gè)命名空間解析器DefaultNamespaceHandlerResolver,緩存到XmlReaderContext,當(dāng)Reader解析配置文件時(shí)發(fā)現(xiàn)存在其他命名空間時(shí),通過DefaultNamespaceHandlerResolver加載 META-INF/spring.handlers 路徑下的其他命名空間處理器,獲取對應(yīng)的處理器處理。

XmlReaderContext 是Spring框架中用于處理XML配置文件解析過程中的上下文對象,為DefaultBeanDefinitionDocumentReader在解析和處理XML配置文件時(shí)提供了必要的環(huán)境支持。

context命名空間處理器(ComponentScanBeanDefinitionParser)

  • 獲取基礎(chǔ)包名basePackages。
  • 創(chuàng)建類路徑 Bean 定義掃描程序ClassPathBeanDefinitionScanner。
  • 遍歷掃描包名,查找被@Component及其派生注解修飾的類。將它們封裝為BeanDefinitionHolder對象。
  • 往bean工廠加載特定注解后置處理器的bean定義(internalConfigurationAnnotationProcessor、internalAutowiredAnnotationProcess、internalCommonAnnotationProcessor、internalEventListenerProcessor、internalEventListenerFactory),觸發(fā)組件注冊事件.

獲取基礎(chǔ)包名basePackages

  • element.getAttribute(BASE_PACKAGE_ATTRIBUTE)方法從對象中獲取base-package的屬性值。
  • parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage)方法解析占位符,獲取解析值。
  • StringUtils.tokenizeToStringArray(basePackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)方法將基礎(chǔ)包名按逗號、分號或空格等常見分隔符拆分為一個(gè)字符串?dāng)?shù)組basePackages。

創(chuàng)建組件掃描器

ComponentScanBeanDefinitionParser#configureScanner方法通過對XML元素element的各項(xiàng)屬性(use-default-filters、resource-pattern、name-generator、scope-resolver、scoped-proxy)和子元素(include-filter、exclude-filter)進(jìn)行解析,創(chuàng)建一個(gè)定制化的掃描器ClassPathBeanDefinitionScanner。

另外通過ClassPathBeanDefinitionScanner構(gòu)造函數(shù)實(shí)例化時(shí),會創(chuàng)建一個(gè)Component類型的注解類型過濾器AnnotationTypeFilter添加到includeFilters屬性中,用于將類與@Component進(jìn)行匹配。

掃描組件

ClassPathBeanDefinitionScanner#doScan掃描指定的basePackages包及其子包,查找并處理符合要求的bean定義,最終將它們封裝為BeanDefinitionHolder對象并返回,bean定義類型是ScannedGenericBeanDefinition。

掃描核心方法ClassPathScanningCandidateComponentProvider#findCandidateComponents用于在指定的basePackage包及其子包下查找符合要求的候選bean組件(BeanDefinition),支持索引查找(效率更高)或按傳統(tǒng)方式查找(獲取指定包下所有class對象篩選)。

我們只看傳統(tǒng)方式查找方式,ClassPathScanningCandidateComponentProvider#scanCandidateComponents方法用于在給定的basePackage及其子包下通過類路徑掃描機(jī)制查找候選bean組件(BeanDefinition).

ClassPathScanningCandidateComponentProvider#isCandidateComponent方法用于判斷給定的MetadataReader所代表的類是否滿足候選bean組件的條件,在不添加其他排除過濾器、包含過濾器或配置,上面創(chuàng)建組件掃描器過程中,已知添加了一個(gè)AnnotationTypeFilter包含過濾器,在此處使用,匹配被@Component注解的類。

觸發(fā)組件注冊事件

ComponentScanBeanDefinitionParser#registerComponents負(fù)責(zé)將一組BeanDefinition注冊到Spring IoC容器中,并處理與之相關(guān)的XML元素及注解配置處理器。實(shí)際上做了兩件事

往bean工廠加載特定注解后置處理器的bean定義觸發(fā)組件注冊事件,一般情況下是EmptyReaderEventListener,空方法。

3. 全注解開發(fā)

AnnotationConfigApplicationContext 是 Spring Framework 中的一個(gè)核心類,用于創(chuàng)建和管理基于 Java 注解的 Spring 應(yīng)用程序上下文。AnnotationConfigApplicationContext 有兩種開啟組件掃描的方式

  • 直接指定包路徑
  • 通過@ComponentScan注解

3.1 通過指定包路徑開啟掃描

使用

掃描原理

接受一個(gè)字符串?dāng)?shù)組參數(shù) basePackages的有參構(gòu)造邏輯分成三部分:

  • this(); 調(diào)用無參構(gòu)造函數(shù)
  • scan(basePackages); 執(zhí)行類路徑掃描
  • refresh(); 啟動(dòng)應(yīng)用上下文

無參構(gòu)造函數(shù)實(shí)例化組件掃描器 ClassPathBeanDefinitionScanner,用于在類路徑中掃描并注冊基于注解的 Bean 定義(如 @Component、@Service、@Repository、@Controller 等)。

調(diào)用ClassPathBeanDefinitionScanner#scan方法掃描組件,與基于xml掃描邏輯一樣,調(diào)用的是ClassPathBeanDefinitionScanner#scan方法,所以bean定義創(chuàng)建的類型也是ScannedGenericBeanDefinition類。

3.2 通過Java配置類開啟掃描

使用

c

掃描原理

接受一個(gè)類型為 Class<?> 的可變參數(shù)數(shù)組 componentClasses的有參構(gòu)造邏輯分成三部分:

  • this(); 調(diào)用無參構(gòu)造函數(shù)
  • register(componentClasses); 注冊指定的組件
  • refresh(); 啟動(dòng)應(yīng)用上下文

第一部分雖然與接受字符串的有參構(gòu)造(指定掃描路徑)一樣調(diào)用了無參構(gòu)造,但我們這里只關(guān)注 帶注釋的 Bean 定義讀取器AnnotatedBeanDefinitionReader,而不是類路徑 Bean 定義掃描程器ClassPathBeanDefinitionScanner。

實(shí)例化AnnotatedBeanDefinitionReader過程中,會調(diào)用AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)方法,往bean工廠注冊一個(gè)bean定義后置處理器ConfigurationClassPostProcessor。

第二部分注冊Java配置類ScanConfig,實(shí)例化并初始化bean定義類AnnotatedGenericBeanDefinition,并加載到bean工廠中。

第三部分在refresh方法invokeBeanFactoryPostProcessors階段,會調(diào)用在第一部分注冊的ConfigurationClassPostProcessor(在當(dāng)前階段會調(diào)用getBean方法實(shí)例化)后置處理。

ConfigurationClassPostProcessor 是 Spring 框架中一個(gè)重要的 BeanDefinitionRegistryPostProcessor 實(shí)現(xiàn),主要負(fù)責(zé)處理帶有 @Configuration 注解的類以及它們內(nèi)部定義的 @Bean 方法和其他相關(guān)注解。postProcessBeanDefinitionRegistry方法會篩選出有效的@configuration類,調(diào)用配置類解析器ConfigurationClassParser的parse方法解析。

從第二部分知道,ScanConfig生成的bean定義類是AnnotatedGenericBeanDefinition,是AnnotatedBeanDefinition的子類。debug源碼到處理@ComponentScan注解(this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());),說明ConfigurationClassParser處理邏輯委托給componentScanParser,調(diào)用其parse方法處理。

這里的this.componentScanParser是ComponentScanAnnotationParser類,在調(diào)用ConfigurationClassParser構(gòu)造函數(shù)實(shí)例化時(shí)創(chuàng)建。

ComponentScanAnnotationParser#parse方法中的邏輯就很熟悉了,可以對標(biāo)context命名空間處理各個(gè)屬性。在方法中是新建了一個(gè)ClassPathBeanDefinitionScanner類,而不是使用AnnotationConfigApplicationContext無參構(gòu)造中實(shí)例化的ClassPathBeanDefinitionScanner,最后執(zhí)行doscan方法掃描組件。

總結(jié)

總結(jié)一下通過@ComponentScan開啟掃描流程.

  • this();
    • 在實(shí)例化AnnotatedBeanDefinitionReader過程中,往bean工廠加載了ConfigurationClassPostProcessor的bean定義
  • register(componentClasses);
    • 往bean工廠加載了包含@Configuration、@ComponentScan注解的ScanConfig配置類 的bean定義。
  • refresh();
    • 在invokeBeanFactoryPostProcessors階段實(shí)例化了ConfigurationClassPostProcessor,并調(diào)用其postProcessBeanDefinitionRegistry方法處理@Configuration配置類。
    • ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法中,獲取并篩選有效的 @Configuration類,實(shí)例化了配置類解析器ConfigurationClassParser,調(diào)用其parse方法,解析配置類(ScanConfig.class)。
    • ConfigurationClassParser#parse包含處理配置類中各種注解,其中就包含@ComponentScan。但解析@ComponentScan,委托給了ComponentScanAnnotationParser類,調(diào)用其parse方法.
    • ComponentScanAnnotationParser#parse實(shí)例化了類路徑 Bean 定義掃描器ClassPathBeanDefinitionScanner,ClassPathBeanDefinitionScanner加載掃描配置后調(diào)用doScan掃描組件。

相關(guān)文章

  • Spring中屬性文件properties的讀取與使用詳解

    Spring中屬性文件properties的讀取與使用詳解

    這篇文章主要介紹了Spring中屬性文件properties的讀取與使用詳解的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • ElasticSearch的安裝與基本概念

    ElasticSearch的安裝與基本概念

    這篇文章主要介紹了ElasticSearch的安裝與基本概念,提供了一個(gè)分布式多用戶能力的全文搜索引擎,Elasticsearch是用Java開發(fā)的,需要的朋友可以參考下
    2023-04-04
  • 一文讀懂Spring中@Bean注解的核心作用

    一文讀懂Spring中@Bean注解的核心作用

    快速了解Spring框架中的@Bean注解?本文將帶你一鍵掌握其核心作用!只需一篇短文,揭示@Bean注解如何在Spring中定義bean實(shí)例,以及管理和裝配Bean的奧秘,閱讀指南,讓Spring開發(fā)更加得心應(yīng)手!
    2024-01-01
  • JavaSwing后臺播放音樂mp3

    JavaSwing后臺播放音樂mp3

    這篇文章主要為大家詳細(xì)介紹了JavaSwing后臺播放音樂mp3,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Spring Cloud Zuul路由網(wǎng)關(guān)服務(wù)過濾實(shí)現(xiàn)代碼

    Spring Cloud Zuul路由網(wǎng)關(guān)服務(wù)過濾實(shí)現(xiàn)代碼

    這篇文章主要介紹了Spring Cloud Zuul路由網(wǎng)關(guān)服務(wù)過濾實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • jtds1.1連接sqlserver2000測試示例

    jtds1.1連接sqlserver2000測試示例

    這篇文章主要介紹了jtds1.1連接sqlserver2000測試示例,需要的朋友可以參考下
    2014-02-02
  • Java Code Cache滿導(dǎo)致應(yīng)用性能降低問題解決

    Java Code Cache滿導(dǎo)致應(yīng)用性能降低問題解決

    這篇文章主要介紹了Java Code Cache滿導(dǎo)致應(yīng)用性能降低問題解決,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java的validation參數(shù)校驗(yàn)代碼實(shí)例

    Java的validation參數(shù)校驗(yàn)代碼實(shí)例

    這篇文章主要介紹了Java的validation參數(shù)校驗(yàn)代碼實(shí)例,Validation參數(shù)校驗(yàn)是指在程序運(yùn)行中對傳進(jìn)來的參數(shù)進(jìn)行合法性檢查,以保證程序的正確性和安全性,需要的朋友可以參考下
    2023-10-10
  • 詳解Spring-boot中讀取config配置文件的兩種方式

    詳解Spring-boot中讀取config配置文件的兩種方式

    這篇文章主要介紹了詳解Spring-boot中讀取config配置文件的兩種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • springboot國際化多語言配置方式

    springboot國際化多語言配置方式

    這篇文章主要介紹了springboot國際化多語言配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04

最新評論