@Import原理與實戰

文章目錄

  • 前言
  • 一、導入普通類
  • 二、導入ImportSelector實現類
  • 三、導入ImportBeanDefinitionRegistrar實現類
  • 四、@Import注解的解析
    • 4.1、解析實現ImportSelector的候選bean
    • 4.2、解析實現ImportBeanDefinitionRegistrar的候選bean
    • 4.3、DeferredImportSelector的特殊處理
  • 總結


前言

??@Import是Spring框架提供的一個核心注解,主要用于在配置類中引入其他配置類或組件。通過在類上標注@Import注解,可以將其value屬性中指定的類注冊到Spring容器中,從而實現配置的模塊化和靈活組合。

一、導入普通類

??@Import注解會將其中導入的普通類,注冊成bean放入到Spring容器中。

public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);System.out.println(context.getBean(MyService.class));}
}class MyService {
}@Configuration
@Import(MyService.class) 
class Config {}

??運行結果:

com.itbaima.importdemo.demo1.MyService@55183b20

二、導入ImportSelector實現類

??解析@Import注解時會執行實現了ImportSelector的類的selectImports方法,將返回的數組中的類注冊成bean。

public class Demo2 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config1.class);System.out.println(context.getBean(MyService.class));}
}@Configuration
@Import(MyImport.class)
class Config1{}class MyImport implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.itbaima.importdemo.demo1.MyService"};}
}

??運行結果

com.itbaima.importdemo.demo1.MyService@33d512c1

三、導入ImportBeanDefinitionRegistrar實現類

??實現了ImportBeanDefinitionRegistrar的類,可以自己注冊bean定義,以及從已有的bean定義中獲取指定的bean,進行修改,自由度是最高的。

public class Demo3 {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);System.out.println(context.getBean("orderService"));}
}@Configuration
@Import({MyBeanDefinitionRegistrar.class})
class Config {
}class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {GenericBeanDefinition bd = new GenericBeanDefinition();bd.setBeanClass(MyService.class);registry.registerBeanDefinition("orderService", bd);}
}class MyService {
}

??運行結果:

com.itbaima.importdemo.demo2.MyService@2f9f7dcf

四、@Import注解的解析

??@Import注解的解析,體現在refresh方法中的invokeBeanFactoryPostProcessors(調用所有bean工廠后置處理器)這一步:
在這里插入圖片描述
??ConfigurationClassPostProcessor,用于配置類的解析:
在這里插入圖片描述
??在org.springframework.context.annotation.ConfigurationClassParserprocessImports中完成對于@Import注解的解析:
在這里插入圖片描述

4.1、解析實現ImportSelector的候選bean

??對于候選bean實現了ImportSelector接口的處理:

  1. 利用JVM的類加載機制,對于候選bean進行加載。
  2. 使用Spring提供的工具方法instantiateClass反射創建這個ImportSelector實例,并注入必要的環境參數。
  3. 如果候選bean實現了DeferredImportSelector,則將其加入deferredImportSelectors的集合中,延遲處理
  4. 候選bean實現的是ImportSelector接口,就調用目標類重寫的selectImports方法,決定要導入哪些類名。然后把類名數組轉換成 SourceClass 的集合,并應用排除過濾器。

在這里插入圖片描述
??調用目標類重寫的selectImports方法,傳入的參數就是加入了@Configuration注解的配置類的元信息。最后一步遞歸調用processImports方法很關鍵:假設當前第一次調用processImports方法,解析出的類路徑是com.itbaima.importdemo.demo1.MyService,那么在遞歸調用processImports方法時,再次進入
在這里插入圖片描述
??循環中進行解析時,由于MyService沒有實現ImportSelectorImportBeanDefinitionRegistrar注解,就會進入最后的else分支:(@Import導入的普通bean,進入的也是該分支)
在這里插入圖片描述
??在最后的else分支中,還會去遞歸調用processConfigurationClass,將MyService當做配置類去解析,最終將解析完成的放入到ConfigurationClass的集合中。(注意,通過Import解析出的類路徑下的bean,bean名稱為空,后續需要再次進行處理。)
在這里插入圖片描述
??this.reader.loadBeanDefinitions(configClasses);這一步,會對于@Import導入的普通bean進行處理:
在這里插入圖片描述
??生成一個beanName,并且將bean定義注冊到bean工廠中:
在這里插入圖片描述

4.2、解析實現ImportBeanDefinitionRegistrar的候選bean

??@Import導入實現ImportBeanDefinitionRegistrar的候選bean的解析邏輯,在else…if的分支中,同樣是通過JVM的類加載機制,加載候選類的class類,然后使用Spring提供的工具方法instantiateClass反射創建這個ImportBeanDefinitionRegistrar實例,并注入必要的環境參數。
在這里插入圖片描述
??最后將其加入到ConfigurationClassimportBeanDefinitionRegistrars屬性中:
在這里插入圖片描述
??它的解析同樣是在processConfigBeanDefinitionsthis.reader.loadBeanDefinitions(configClasses);中:
在這里插入圖片描述
??回調用戶重寫的registerBeanDefinitions的邏輯。
在這里插入圖片描述

4.3、DeferredImportSelector的特殊處理

??用戶實現ImportSelector時,有一種特殊的情況,即用戶實現了DeferredImportSelectorDeferredImportSelectorImportSelector的子類。在該分支中,僅僅是先將其加入DeferredImportSelectorHandlerdeferredImportSelectors屬性中:
在這里插入圖片描述
??DeferredImportSelectorHandlerdeferredImportSelectors屬性是一個集合:
在這里插入圖片描述
??最終會在所有bean解析完成后再去進行解析:
在這里插入圖片描述
??該機制主要應用于Spring Boot的自動配置場景,其核心作用是確保用戶自定義的Bean能夠優先于自動配置的Bean執行。由于spring.factories中定義的自動配置Bean通常采用條件裝配機制,當容器中已存在用戶自定義的同類型Bean時,系統將不再重復裝配。這正是通過@Bean注解添加的Bean能夠覆蓋默認Bean的原因
在這里插入圖片描述
在這里插入圖片描述
??在doProcessConfigurationClass中,默認的@Bean的注解,是后于@Import注解解析的。如果你不顯式允許覆蓋,Spring 在注冊 BeanDefinition 時會拋出異常或者忽略重復的注冊。
在這里插入圖片描述
??但是對于DeferredImportSelector的解析,是在doProcessConfigurationClass的外層parse方法中執行的,后于@Bean注解的解析。

總結

??@Import注解是為了替換掉配置文件中的import標簽,主要是為了導入第三方的配置類,除此之外:

  1. 可以在配置類中指定@Import注解,將其中的類注入到容器中。
  2. 可以在配置類中指定@Import注解,同時其中的類實現了Import Selector接口,會執行重寫的selectImports方法,并且將其中指定的路徑的對象注入到容器中。
  3. 如果導入的類型實現了Import BeanDefinitionRegistrar,則可以自己注冊 BeanDefinition,自由度更高。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86290.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86290.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86290.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

day 18進行聚類,進而推斷出每個簇的實際含義

浙大疏錦行 對聚類的結果根據具體的特征進行解釋,進而推斷出每個簇的實際含義 兩種思路: 你最開始聚類的時候,就選擇了你想最后用來確定簇含義的特征, 最開始用全部特征來聚類,把其余特征作為 x,聚類得到…

Java并發編程實戰 Day 11:并發設計模式

【Java并發編程實戰 Day 11】并發設計模式 開篇 這是"Java并發編程實戰"系列的第11天,今天我們聚焦于并發設計模式。并發設計模式是解決多線程環境下常見問題的經典解決方案,它們不僅提供了優雅的設計思路,還能顯著提升系統的性能…

iview組件庫:當后臺返回到的數據與使用官網組件指定的字段不匹配時,進行修改某個屬性名再將response數據渲染到頁面上的處理

1、需求導入 當存在前端需要的數據的字段渲染到表格或者是一些公共的表格組件展示數據時的某個字段名與后臺返回的字段不一致時,那么需要前端進行稍加處理,而不能直接this.list res.data;這樣數據是渲染不出來的。 2、后臺返回的數據類型 Datalist(pn) …

Ubuntu下有關UDP網絡通信的指令

1、查看防火墻狀態: sudo ufw status # Ubuntu 2、 檢查系統全局廣播設置 # 查看是否忽略廣播包(0表示接收,1表示忽略) sysctl net.ipv4.icmp_echo_ignore_broadcasts# 查看是否允許廣播轉發(1表示允許&#xff09…

vue3:十六、個人中心-修改密碼

一、頁面效果 頁面展示當前用戶名(只讀),展示需要輸入的當前密碼,輸入新的密碼以及確認密碼的提交表單 二、初始建立 1、建立密碼修改頁面 在個人中心文件夾中寫入新頁面UpdatepwdView.vue 2、新建路由 在路由頁面中寫入修改密碼頁面 3、新建菜單 在菜單布局菜單頁面中寫…

GitFlow 工作模式(詳解)

今天再學項目的過程中遇到使用gitflow模式管理代碼,因此進行學習并且發布關于gitflow的一些思考 Git與GitFlow模式 我們在寫代碼的時候通常會進行網上保存,無論是github還是gittee,都是一種基于git去保存代碼的形式,這樣保存代碼…

【Vue3】(三)vue3中的pinia狀態管理、組件通信

目錄 一、vue3的pinia 二、【props】傳參 三、【自定義事件】傳參 四、【mitt】傳參 五、【v-model】傳參(平常基本不寫) 六、【$attrs】傳參 七、【$refs和$parent】傳參 八、provide和inject 一、vue3的pinia 1、什么是pinia? pinia …

【DAY43】復習日

內容來自浙大疏錦行python打卡訓練營 浙大疏錦行 作業: kaggle找到一個圖像數據集,用cnn網絡進行訓練并且用grad-cam做可視化 進階:并拆分成多個文件

xtp+ctp 交易系統接口簡介

CTP(上海期貨交易所綜合交易平臺)和 XTP(中泰證券極速交易平臺)是中國金融市場中兩個重要的證券期貨交易系統,它們在定位、架構和應用場景上有顯著區別: 1. 開發主體與服務領域 維度CTPXTP開發公司上海期貨…

阿里云Alibaba Cloud安裝Docker與Docker compose【圖文教程】

個人記錄 進入控制臺,找到定時與自動化任務 進入‘安裝/卸載擴展程序’ 點擊‘安裝擴展程序’ 選擇docker社區版,點擊下一步與確定,等待一會 安裝成功 查詢版本 查詢docker sudo docker version查詢docker compose sudo docker compo…

非Root用戶啟動SSH服務經驗小結

各位看官,小子我先問個問題:是不是經常在容器里想開個SSH,卻發現自己不是root,處處碰壁?這是常態。多數容器鏡像精簡到連SSH服務都沒有,就算有,咱們普通用戶也沒權限啟動它。 今天小子就介紹一…

Windows開機自動啟動中間件

WinSW(Windows Service Wrapper 是一個開源的 Windows 服務包裝器,它可以幫助你將應用程序打包成系統服務,并實現開機自啟動的功能。 一、下載 WinSW 下載 WinSW-x64.exe v2.12.0 (?? 更多版本下載) 和 sample-minimal.xml 二、配置 WinS…

【CATIA的二次開發23】抽象對象Document涉及文檔激活控制的方法

在CATIA VBA開發中,Document對象是最核心、最基礎的對象之一。它代表了當前在CATIA會話中打開的一個文檔(文件)。 幾乎所有與文件操作、模型訪問相關的操作都始于獲取一個Document對象。Document對象包含多種方法和屬性,以下介紹Document對象方法和屬性 一、Document對象方…

基于多維視角的大模型提升認知醫療過程層次激勵編程分析

系統架構設計 #mermaid-svg-k3W5lvie1sP3T956 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-k3W5lvie1sP3T956 .error-icon{fill:#552222;}#mermaid-svg-k3W5lvie1sP3T956 .error-text{fill:#552222;stroke:#55222…

【評測】Qwen3-Embedding模型初體驗

回到目錄 【評測】Qwen3-Embedding模型初體驗 模型的介紹頁面 0.6B運行配置:筆記本i5-8265U,16G內存,無GPU核顯運行,win10操作系統 8B運行配置:AMD8700G,64G內存,4090D 24G顯存,ub…

MPLAB X IDE ?軟件安裝與卸載

1、下載MPLAB X IDE V6.25 MPLAB X IDE | Microchip Technology 正常選Windows,點擊Download,等待自動下載完成; MPLAB X IDE 一臺電腦上可以安裝多個版本; 2、安裝MPLAB X IDE V6.25 右鍵以管理員運行;next; 勾選 I a…

PLC入門【2】PLC的接線

02 PLC的接線 PLC 的品牌介紹,PLC的接線 1、PLC 大體分為歐式和日式 2、只要學會三菱的,整個日式的也差不多會了。 3、PLC 分為晶體管輸出和繼電器輸出。 4、PLC 接線都差不多的 我們主要是講這個三菱的 PLC, 三菱和臺達的 PLC,…

Hibernate Validator 數據驗證

Hibernate Validator不僅可以用于Controller層的參數驗證,還可以在Service層、Repository層或任何其他層中使用。 手動驗證 在任何地方都可以通過Validator接口手動觸發驗證: public class ManualValidationExample {public void validateObject(Obje…

【深度學習】表示學習:深度學習的數據解構與重構藝術

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程,深度學習領域研究生必讀教材),開始深度學習領域學習,深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

如何在PowerBI中使用Analyze in Excel

如何在PowerBI中使用Analyze in Excel 之前分享過如何使用DAXStudio將PowerBI與Excel連接 ,今天介紹另外一個工具,也可以實現同樣的功能,Analyze in Excel。 使用Analyze in Excel 第一步: 首先準備好一個PBIX文件&#xff0c…