日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Boot - 自动装配中的不可忽视的@Import

發布時間:2025/3/21 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Boot - 自动装配中的不可忽视的@Import 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • Pre
  • 四種處理方式
  • 從@SpringBootApplication注解說起
    • @SpringBootApplication組合注解說明
      • @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited
      • @SpringBootCon?guration
      • @EnableAutoConfiguration
      • @ComponentScan
    • @EnableAutoConfiguration
      • @AutoConfigurationPackage
      • @Import(AutoConfigurationImportSelector.class)
  • @Import源碼
    • @Import 普通組件
    • @Import 實現了ImportSelector接口的組件 (類的全限定類名)
    • @Import 實現了ImportBeanDefinitionRegistrar接口的組件
  • 最佳實踐 @EnableXXX
    • 【自定義注解 @EnableArtisan】
    • 將AppConfig.java添加@EnableArtisan
  • 源碼

Pre

Spring Boot - 自動配置實現原理


四種處理方式

在使用 Spring Boot 時,@Import 也是一個非常常見的注解,可以用來動態創建 Bean。

在 @Import 注解的屬性中可以設置需要引入的類名,例如 @AutoConfigurationPackage 注解上的 @Import(AutoConfigurationPackages.Registrar.class)。根據該類的不同類型,Spring 容器針對 @Import 注解有以下四種處理方式:

  • 如果該類實現了 ImportSelector 接口,Spring 容器就會實例化該類,并且調用其 selectImports 方法;
  • 如果該類實現了 DeferredImportSelector 接口,則 Spring 容器也會實例化該類并調用其 selectImports方法。DeferredImportSelector 繼承了 ImportSelector,區別在于 DeferredImportSelector 實例的 selectImports 方法調用時機晚于 ImportSelector 的實例,要等到 @Configuration 注解中相關的業務全部都處理完了才會調用;
  • 如果該類實現了 ImportBeanDefinitionRegistrar 接口,Spring 容器就會實例化該類,并且調用其 registerBeanDefinitions 方法;
  • 如果該類沒有實現上述三種接口中的任何一個,Spring 容器就會直接實例化該類。

我們來搞一搞@Import吧


從@SpringBootApplication注解說起

我們都知道 啟動一個SpringBoot應用 無須各種的配置文件,無須各種繁雜的pom依賴,一個main方法,就能run起來了。

與其他框架整合也相當方便,使用EnableXXXXX注解就可以完成整合

那SpringBoot是如何實現自動配置的????


@SpringBootApplication組合注解說明

@SpringBootApplication: Spring Boot應用標注在某個類上說明這個類是SpringBoot的主配置類,SpringBoot需要運行這個類的main方法來啟動SpringBoot應用

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited

注解說明:

  • @Target(ElementType.TYPE) 設置當前注解可以標記在哪
  • @Retention(RetentionPolicy.RUNTIME) 當注解標注的類編譯以什么方式保留。 RetentionPolicy.RUNTIME 會被jvm加載
  • @Documented java doc 會生成注解信息
  • @Inherited 是否會被繼承

更詳細的請參考我以前寫的一篇博文: Java-Java5.0注解解讀


@SpringBootCon?guration

Spring Boot的配置類 , 標注在某個類上,表示這是一個Spring Boot的配置類


@EnableAutoConfiguration

開啟自動配置功能 , @EnableAutoCon?guration告訴SpringBoot開啟自動配置,會自動去加載自動配置類


@ComponentScan

相當于在spring.xml 配置中<context:comonent-scan> 但是并沒有指定basepackage,如果沒有指定spring底層會自動掃描當前配置類所有在的包


@EnableAutoConfiguration

SpringBootApplication注解中最重要的一個注解就是 @EnableAutoConfiguration.

@AutoConfigurationPackage

將當前配置類所在包保存在BasePackages的Bean中。供Spring內部使用

使用了@Import注解 保存掃描路徑, 注冊

那看下 org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar


@Import(AutoConfigurationImportSelector.class)

關鍵點!

可以看到,在@EnableAutoConfiguration注解內也使用到了@Import注解來完成導入配置的功能


那都用它,我們來搞搞@Import吧


@Import源碼


@Import表示要導入的一個或多個@Configuration類

我們來看下value方法源碼中的注釋: Configuration,ImportSelector,ImportBeanDefinitionRegistrar 或者是一個普通的組件

那分別來看下如何使用吧

POM 核心 有個context就夠了

<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.18</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.6.RELEASE</version></dependency></dependencies>

@Import 普通組件

@Import({ 要導入的組件 } )

【模擬第三方框架提供的】

package com.artisan.configuration;import com.artisan.beans.Artisan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;/*** @author 小工匠* @version 1.0* @description: 自定義的配置類 類比第三方的配置類* @date 2021/5/22 8:50* @mark: show me the code , change the world*/@Configuration public class ArtisanConfig {@Beanpublic Artisan artisan() {Artisan artisan = new Artisan();artisan.setName("小工匠");artisan.setAge(18);return artisan;} }

【模擬Spring自己的】

/*** 系統當前加載的配置類*/@Configuration @Import({ArtisanConfig.class}) // @Import(ArtisanImportSelector.class) //@Import(ArtisanRegistrar.class) //@EnableArtisan public class AppConfig { }

將AppConfig.java添加注解 @Import({ArtisanConfig.class}) , 將第三方的配置類導入到Bean容器中 , 本質上就是導入 一個Configuration配置類組件

【測試類】

public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);Artisan artisan = ctx.getBean(Artisan.class);System.out.println(artisan);} }

【測試結果】


@Import 實現了ImportSelector接口的組件 (類的全限定類名)

【ImportSelector接口 返回全限定名】

package com.artisan.impt;import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/5/22 9:25* @mark: show me the code , change the world*/ public class ArtisanImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{"com.artisan.beans.Artisan"};} }

【AppConfig - @Import(ArtisanImportSelector.class)】

/*** 系統當前加載的配置類*/@Configuration //@Import({ArtisanConfig.class})@Import(ArtisanImportSelector.class) //@Import(ArtisanRegistrar.class) //@EnableArtisan public class AppConfig { }

測試

ArtisanSelector返回的類的全限定類名,即為導入到容器中的組件全類名


@Import 實現了ImportBeanDefinitionRegistrar接口的組件

【ImportBeanDefinitionRegistrar 接口】

package com.artisan.impt;import com.artisan.beans.Artisan; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata;/*** @author 小工匠* @version 1.0* @description: TODO* @date 2021/5/22 9:28* @mark: show me the code , change the world*/ public class ArtisanRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Artisan.class);builder.setScope(BeanDefinition.SCOPE_SINGLETON);builder.addPropertyValue("name", "小工匠Registrar");builder.addPropertyValue("age", "18");registry.registerBeanDefinition("artisan", builder.getBeanDefinition());} }

【AppConfig - @Import(ArtisanRegistrar.class) 】

/*** 系統當前加載的配置類*/@Configuration //@Import({ArtisanConfig.class}) // @Import(ArtisanImportSelector.class) @Import(ArtisanRegistrar.class) //@EnableArtisan public class AppConfig { }

【測試】

ImportBeanDefinitionRegistrar類似于ImportSelector用法,只不過這種用法能自定義化注冊,往容器內注入一個BeanDefinition,然后BeanDeiniton在容器內轉為一個實例bean。


最佳實踐 @EnableXXX

【自定義注解 @EnableArtisan】

package com.artisan.annotation;import com.artisan.configuration.ArtisanConfig; import com.artisan.impt.ArtisanImportSelector; import com.artisan.impt.ArtisanRegistrar; import org.springframework.context.annotation.Import;import java.lang.annotation.*;@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented// @Import({ArtisanConfig.class}) @Import({ArtisanImportSelector.class}) 都可以 @Import({ArtisanRegistrar.class}) public @interface EnableArtisan {}

將AppConfig.java添加@EnableArtisan

【測試結果】


源碼

https://github.com/yangshangwei/boot2/tree/master/spring_maven

總結

以上是生活随笔為你收集整理的Spring Boot - 自动装配中的不可忽视的@Import的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。