最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot 配置加載全解析從 @ComponentScan 到自動(dòng)配置原理解析

 更新時(shí)間:2026年05月09日 11:08:48   作者:Han.miracle  
本文給大家介紹了Spring Boot 配置加載全解析從@ComponentScan到自動(dòng)配置原理,通過(guò)實(shí)戰(zhàn)案例展示了如何基于@Conditional實(shí)現(xiàn)JDK版本條件裝配,并了詳細(xì)步驟和配置原理,感興趣的朋友一起看看吧

一、三種配置加載方式對(duì)比總覽

我們先通過(guò)一張表,把三種方式的核心區(qū)別講清楚,方便你快速建立整體認(rèn)知:

表格

加載方式觸發(fā)時(shí)機(jī)核心特點(diǎn)適用場(chǎng)景
@ComponentScan項(xiàng)目啟動(dòng)時(shí),隨包掃描一次性加載暴力掃描、全量加載、無(wú)條件生效項(xiàng)目?jī)?nèi)部配置,與啟動(dòng)類在同一包下
@Import配置類解析時(shí)直接導(dǎo)入強(qiáng)制加載、無(wú)條件生效、寫了就生效臨時(shí)導(dǎo)入少量跨包配置、第三方類
AutoConfiguration.imports(自動(dòng)配置)啟動(dòng)時(shí)登記候選,條件判斷后按需加載按需加載、條件判斷、不用不加載通用 Starter、公共模塊、跨項(xiàng)目復(fù)用配置

接下來(lái),我們就對(duì)這三種方式逐一拆解,從使用場(chǎng)景到底層原理,講得明明白白。

二、方式一:@ComponentScan —— 最直接的 “暴力掃描”

1. 什么是 @ComponentScan?

@ComponentScan是 Spring 最基礎(chǔ)的包掃描注解,它會(huì)告訴 Spring:

去指定的包路徑下,掃描所有被@Component、@Service@Repository、@Configuration修飾的類,把它們注冊(cè)到 Spring 容器中。

在 Spring Boot 中,啟動(dòng)類上的@SpringBootApplication注解,本質(zhì)上就包含了@ComponentScan,默認(rèn)掃描啟動(dòng)類所在包及其子包下的所有類。

2. 基本使用示例

@SpringBootApplication
public class BlogApplication {
    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }
}

在這個(gè)示例中,@SpringBootApplication會(huì)自動(dòng)掃描com.bite.blog包下的所有組件類,無(wú)需額外配置。

如果你的配置類不在啟動(dòng)類的同級(jí)或子包下,可以手動(dòng)指定掃描路徑:

@SpringBootApplication(scanBasePackages = "com.bite")
public class BlogApplication {
    // ...
}

3. 核心特點(diǎn)與優(yōu)缺點(diǎn)

? 優(yōu)點(diǎn)

  • 簡(jiǎn)單直接,無(wú)需額外配置,項(xiàng)目?jī)?nèi)的配置類直接生效
  • 無(wú)需手動(dòng)維護(hù)導(dǎo)入列表,新增類自動(dòng)被掃描到

? 缺點(diǎn)

  • 暴力掃描,不管類是否被使用,都會(huì)被加載到容器中,啟動(dòng)時(shí)一次性全量加載
  • 跨包、跨模塊的配置類無(wú)法被掃描到,比如你在common模塊的配置類,在user-service中無(wú)法被自動(dòng)掃描
  • 無(wú)法實(shí)現(xiàn) “按需加載”,不使用的配置類也會(huì)被加載,造成資源浪費(fèi)

4. 適用場(chǎng)景

  • 項(xiàng)目?jī)?nèi)部的業(yè)務(wù)配置類,與啟動(dòng)類在同一包結(jié)構(gòu)下
  • 單體項(xiàng)目中,所有配置類都在項(xiàng)目?jī)?nèi)部的場(chǎng)景

三、方式二:@Import —— 強(qiáng)制導(dǎo)入的 “硬編碼”

1. 什么是 @Import?

@Import是 Spring 提供的顯式導(dǎo)入注解,它的作用是:

直接將指定的類導(dǎo)入到 Spring 容器中,不管這個(gè)類是否被掃描到,也不管它是否被使用。

簡(jiǎn)單說(shuō),就是 “寫了就導(dǎo)入,不寫就不導(dǎo)入”,是一種強(qiáng)制的、無(wú)條件的加載方式。

2. 基本使用示例

場(chǎng)景 1:導(dǎo)入單個(gè)配置類

比如你的RedisConfigcommon模塊,無(wú)法被業(yè)務(wù)模塊的@ComponentScan掃描到,就可以用@Import手動(dòng)導(dǎo)入:

@SpringBootApplication
@Import(RedisConfig.class) // 強(qiáng)制導(dǎo)入Redis配置類
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

場(chǎng)景 2:導(dǎo)入多個(gè)配置類

@Import({RedisConfig.class, WebConfig.class, SecurityConfig.class})
public class UserServiceApplication {
    // ...
}

場(chǎng)景 3:配合 ImportSelector 動(dòng)態(tài)導(dǎo)入

你還可以通過(guò)實(shí)現(xiàn)ImportSelector接口,動(dòng)態(tài)決定要導(dǎo)入哪些配置類:

public class CustomImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 根據(jù)條件動(dòng)態(tài)返回要導(dǎo)入的類名
        return new String[]{RedisConfig.class.getName()};
    }
}
// 使用
@Import(CustomImportSelector.class)
public class UserServiceApplication {
    // ...
}

3. 核心特點(diǎn)與優(yōu)缺點(diǎn)

? 優(yōu)點(diǎn)

  • 靈活可控,想導(dǎo)入哪個(gè)類就導(dǎo)入哪個(gè)類,不受包掃描路徑限制
  • 可以導(dǎo)入非 Spring 管理的第三方類,無(wú)需修改第三方代碼

? 缺點(diǎn)

  • 無(wú)條件強(qiáng)制加載:不管你項(xiàng)目里有沒有用到這個(gè)類,不管配置是否生效,只要寫了@Import,類就會(huì)被加載到容器中
  • 硬編碼維護(hù),新增配置類需要手動(dòng)修改啟動(dòng)類,不適合多模塊、多項(xiàng)目復(fù)用
  • 無(wú)法實(shí)現(xiàn)按需加載,不使用的配置類也會(huì)被加載,浪費(fèi)容器資源

4. 適用場(chǎng)景

  • 臨時(shí)導(dǎo)入少量跨包、跨模塊的配置類
  • 導(dǎo)入無(wú)法被包掃描到的第三方類
  • 動(dòng)態(tài)導(dǎo)入配置類的場(chǎng)景(配合ImportSelector

四、方式三:AutoConfiguration.imports —— Spring Boot 自動(dòng)配置的核心

1. 什么是 AutoConfiguration.imports?

從 Spring Boot 2.7 開始,spring.factories被廢棄,取而代之的是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,它是 Spring Boot 實(shí)現(xiàn)自動(dòng)配置的核心載體。

簡(jiǎn)單說(shuō),它的作用是:

登記所有自動(dòng)配置類的全限定名,由 Spring Boot 自動(dòng)配置機(jī)制,根據(jù)條件按需加載這些配置類。

你在項(xiàng)目里看到的com.bite.common.config.RedisConfig,就是寫在這個(gè)文件里的自動(dòng)配置類。

2. 完整使用示例

步驟 1:創(chuàng)建自動(dòng)配置類

@Configuration
@ConditionalOnClass(RedisTemplate.class) // 項(xiàng)目中存在RedisTemplate類時(shí)才生效
@ConditionalOnProperty(prefix = "spring.redis", name = "host") // 配置了redis.host才生效
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // RedisTemplate配置邏輯
        return new RedisTemplate<>();
    }
}

驟 2:創(chuàng)建 AutoConfiguration.imports 文件

common模塊的resources目錄下,創(chuàng)建以下路徑的文件:

src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件中寫入自動(dòng)配置類的全限定名:

com.bite.common.config.RedisConfig

步驟 3:業(yè)務(wù)模塊引入 common 依賴

<dependency>
    <groupId>com.bite</groupId>
    <artifactId>common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

此時(shí),業(yè)務(wù)模塊無(wú)需任何額外配置,啟動(dòng)時(shí) Spring Boot 會(huì)自動(dòng)加載RedisConfig,并根據(jù)條件判斷是否生效。

3. 核心原理:自動(dòng)配置的 “三步流程”

很多同學(xué)只知道這個(gè)文件能實(shí)現(xiàn)自動(dòng)配置,但不知道它背后的完整流程,我們拆解成三步講清楚:

第一步:?jiǎn)?dòng)掃描,登記候選

Spring Boot 啟動(dòng)時(shí),會(huì)自動(dòng)掃描項(xiàng)目所有依賴的 jar 包中,META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,把里面所有的配置類全限定名收集起來(lái),放到一個(gè) “自動(dòng)配置候選列表” 中。

?? 注意:此時(shí)配置類還沒有被加載,只是被登記為候選。

第二步:條件判斷,篩選生效

Spring Boot 會(huì)逐個(gè)檢查候選列表中的配置類,根據(jù)類上的@Conditional系列注解(比如@ConditionalOnClass、@ConditionalOnProperty@ConditionalOnMissingBean),判斷這個(gè)配置類是否滿足生效條件:

  • 項(xiàng)目中是否存在指定的類?
  • 配置文件中是否存在對(duì)應(yīng)的配置項(xiàng)?
  • 容器中是否已經(jīng)存在對(duì)應(yīng)的 Bean?

只有滿足所有條件的配置類,才會(huì)被標(biāo)記為 “生效”,進(jìn)入下一步。

第三步:加載生效,注冊(cè) Bean

滿足條件的配置類,會(huì)被 Spring 容器加載,里面的@Bean方法會(huì)被執(zhí)行,生成對(duì)應(yīng)的 Bean 注冊(cè)到容器中;不滿足條件的配置類,會(huì)被直接跳過(guò),不會(huì)被加載。

這就是你說(shuō)的 “只有使用的時(shí)候才加載” 的底層原理!

4. 核心特點(diǎn)與優(yōu)缺點(diǎn)

? 優(yōu)點(diǎn)

  • 真正的按需加載,只有滿足條件時(shí)才會(huì)被加載,不使用則不加載,不浪費(fèi)資源
  • 跨模塊、跨項(xiàng)目復(fù)用,通用配置可以做成 Starter,其他項(xiàng)目引入依賴即可自動(dòng)生效,無(wú)需額外配置
  • 解耦性強(qiáng),配置類可以放在任何包下,不受包掃描路徑限制
  • 支持條件判斷,不同環(huán)境、不同依賴下自動(dòng)適配配置

? 缺點(diǎn)

  • 配置路徑容易寫錯(cuò),文件路徑必須嚴(yán)格按照規(guī)范創(chuàng)建,否則無(wú)法被掃描到
  • 條件注解使用不當(dāng),容易出現(xiàn)配置不生效的問(wèn)題,排查難度比前兩種方式稍高

5. 適用場(chǎng)景

  • 通用 Starter 開發(fā),比如 Redis、MyBatis、Swagger 等公共配置模塊
  • 多模塊項(xiàng)目中的公共配置,多個(gè)業(yè)務(wù)模塊都需要復(fù)用的配置
  • 第三方組件集成,實(shí)現(xiàn) “引入依賴即生效” 的體驗(yàn)

五、三種方式的核心區(qū)別深度對(duì)比

我們?cè)倩氐阶铋_始的問(wèn)題,把三種方式的核心區(qū)別,用最直白的話講透:

1. 加載時(shí)機(jī)與條件

  • @ComponentScan:?jiǎn)?dòng)時(shí)一次性掃描,無(wú)條件全量加載,不管用不用都加載
  • @Import:配置解析時(shí)直接導(dǎo)入,無(wú)條件強(qiáng)制加載,寫了就加載,不管用不用
  • AutoConfiguration.imports:?jiǎn)?dòng)時(shí)登記候選,條件判斷后按需加載,只有滿足條件時(shí)才加載,不用不加載

2. 適用范圍

  • @ComponentScan:僅適用于項(xiàng)目?jī)?nèi)部、與啟動(dòng)類在同一包結(jié)構(gòu)下的配置類
  • @Import:適用于臨時(shí)導(dǎo)入少量跨包、跨模塊的配置類
  • AutoConfiguration.imports:適用于跨模塊、跨項(xiàng)目復(fù)用的通用配置,適合做 Starter

3. 維護(hù)成本

  • @ComponentScan:無(wú)需手動(dòng)維護(hù),新增類自動(dòng)被掃描,維護(hù)成本最低
  • @Import:硬編碼維護(hù),新增配置類需要手動(dòng)修改啟動(dòng)類,維護(hù)成本中等
  • AutoConfiguration.imports:配置文件統(tǒng)一維護(hù),新增配置類只需在文件中添加一行,維護(hù)成本低,且不影響業(yè)務(wù)代碼

六、總結(jié):怎么選?

看到這里,很多同學(xué)可能會(huì)問(wèn):“我在項(xiàng)目里到底該用哪種方式?”

給你一個(gè)直接的選擇建議:

  1. 項(xiàng)目?jī)?nèi)部的業(yè)務(wù)配置:優(yōu)先用@ComponentScan,簡(jiǎn)單直接,無(wú)需額外配置
  2. 臨時(shí)跨包導(dǎo)入少量配置:用@Import,靈活可控,適合臨時(shí)場(chǎng)景
  3. 多模塊復(fù)用的公共配置 / Starter:必須用AutoConfiguration.imports,實(shí)現(xiàn)按需加載、引入即生效

考慮到其他項(xiàng)目也可能會(huì)操作 Redis,我們可以把 RedisConfig 放置在 bite-common 包下。

思考與問(wèn)題

  1. 問(wèn)題一:放在 bite-common 包下的配置類,不在業(yè)務(wù)項(xiàng)目的 @ComponentScan 掃描路徑下,@Configuration 注解無(wú)法生效。解決辦法:借助 Spring Boot 的自動(dòng)配置機(jī)制,讓 RedisConfig 被 Spring 管理。
  2. 問(wèn)題二:如果直接用自動(dòng)配置管理 RedisConfig,所有引用 bite-common 的工程,都會(huì)強(qiáng)制加載這個(gè) Bean,不符合 “按需加載” 的需求。解決辦法:借助 @Conditional 系列注解,實(shí)現(xiàn)根據(jù)條件動(dòng)態(tài)裝配 Bean。

七、核心基礎(chǔ):@Conditional注解原理

@Conditional 是 Spring 4.0 引入的注解,允許開發(fā)者根據(jù)特定條件,控制 Bean 的注冊(cè)與裝配,通常與 @Configuration、@Bean 配合使用。

Spring 在解析配置類時(shí),會(huì)根據(jù) @Conditional 配置的條件,決定是否要裝配對(duì)應(yīng)的 Bean:

  • 條件滿足:Bean 會(huì)被注冊(cè)到容器中
  • 條件不滿足:Bean 會(huì)被跳過(guò),不會(huì)被加載

1.@Conditional注解定義

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}
  • value:接收一個(gè) Condition 接口實(shí)現(xiàn)類數(shù)組,Spring 會(huì)根據(jù)這些類的判斷結(jié)果,決定是否裝配 Bean。
  • 可標(biāo)注在類上(控制整個(gè)配置類),也可標(biāo)注在 @Bean 方法上(控制單個(gè) Bean)。

2.Condition接口:條件匹配規(guī)則

Condition 是一個(gè)函數(shù)式接口,matches 方法就是自定義條件邏輯的入口:

@FunctionalInterface
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
  • matches 返回 true:條件滿足,Bean 會(huì)被裝配
  • matches 返回 false:條件不滿足,Bean 不會(huì)被裝配

八、實(shí)戰(zhàn)案例:基于@Conditional實(shí)現(xiàn) JDK 版本條件裝配

自定義條件類,實(shí)現(xiàn):當(dāng)前 JDK 版本為 21 時(shí),注冊(cè) JDK21 Bean;版本為 17 時(shí),注冊(cè) JDK17 Bean。

1. 步驟 1:定義 JDK 版本條件類

// JDK21 生效條件
public class Java21Condition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return JavaVersion.getJavaVersion().equals(JavaVersion.TWENTY_ONE);
    }
}
// JDK17 生效條件
public class Java17Condition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return JavaVersion.getJavaVersion().equals(JavaVersion.SEVENTEEN);
    }
}

2. 步驟 2:定義配置類與 Bean

@Configuration
public class AppConfig {
    @Bean
    @Conditional(Java21Condition.class)
    public JDK21 jdk21() {
        System.out.println("JDK21 初始化完成");
        return new JDK21();
    }
    @Bean
    @Conditional(Java17Condition.class)
    public JDK17 jdk17() {
        System.out.println("JDK17 初始化完成");
        return new JDK17();
    }
}
// 模擬JDK類
class JDK21 {}
class JDK17 {}

3. 步驟 3:測(cè)試效果

@SpringBootTest
class ConditionalTest {
    @Test
    void test() {
        // JDK17環(huán)境:只會(huì)打印"JDK17 初始化完成"
        // JDK21環(huán)境:只會(huì)打印"JDK21 初始化完成"
    }
}

九、Spring Boot 常用@Conditional擴(kuò)展注解

Spring Boot 封裝了一套常用的條件注解,覆蓋了絕大多數(shù)開發(fā)場(chǎng)景,無(wú)需手動(dòng)實(shí)現(xiàn) Condition 接口:

注解作用使用場(chǎng)景
@ConditionalOnClass類路徑中存在指定類時(shí)生效判斷項(xiàng)目是否引入了 Redis、MyBatis 等依賴
@ConditionalOnMissingClass類路徑中不存在指定類時(shí)生效實(shí)現(xiàn) “無(wú)依賴時(shí)才加載” 的配置
@ConditionalOnBean容器中存在指定 Bean 時(shí)生效依賴其他 Bean 才能加載的配置
@ConditionalOnMissingBean容器中不存在指定 Bean 時(shí)生效實(shí)現(xiàn)默認(rèn)配置,允許用戶自定義 Bean 覆蓋
@ConditionalOnProperty配置文件中存在指定屬性且值匹配時(shí)生效根據(jù)配置開關(guān)控制配置是否啟用
@ConditionalOnSingleCandidate容器中存在唯一指定類型的 Bean 時(shí)生效Spring Boot 自動(dòng)配置中常用(如 RedisConnectionFactory

十、實(shí)戰(zhàn)落地:Redis 自動(dòng)配置完整實(shí)現(xiàn)(結(jié)合AutoConfiguration.imports+@Conditional)

回到 bite-common 模塊的 RedisConfig,實(shí)現(xiàn)跨模塊復(fù)用 + 按需加載。

1. 步驟 1:創(chuàng)建 Redis 自動(dòng)配置類

@Configuration
// 條件1:類路徑中存在 RedisTemplate(說(shuō)明項(xiàng)目引入了Redis依賴)
@ConditionalOnClass(RedisTemplate.class)
// 條件2:配置文件中存在 spring.redis.host(說(shuō)明項(xiàng)目配置了Redis連接)
@ConditionalOnProperty(prefix = "spring.redis", name = "host")
public class RedisConfig {
    @Bean
    // 條件3:容器中不存在名為 redisTemplate 的Bean(用戶未自定義時(shí)才生效)
    @ConditionalOnMissingBean(name = "redisTemplate")
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 序列化器配置...
        return template;
    }
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }
}

2. 步驟 2:配置AutoConfiguration.imports文件

bite-common 模塊的 resources 目錄下,創(chuàng)建以下文件:src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中寫入配置類的全限定名:

com.bite.common.config.RedisConfig

3. 步驟 3:業(yè)務(wù)模塊引入依賴并配置

在需要使用 Redis 的業(yè)務(wù)模塊中,引入 bite-common 依賴:

<dependency>
    <groupId>com.bite</groupId>
    <artifactId>bite-common</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

并在 application.yml 中配置 Redis 連接信息:

spring:
  redis:
    host: 127.0.0.1
    port: 6379

4. 效果驗(yàn)證

  • 引入 Redis 依賴、配置連接信息、未自定義 RedisTemplateRedisConfig 自動(dòng)生效,注入默認(rèn)的 RedisTemplateStringRedisTemplate
  • 未引入 Redis 依賴:@ConditionalOnClass 條件不滿足,RedisConfig 不加載,不影響項(xiàng)目啟動(dòng)
  • 自定義了 RedisTemplate@ConditionalOnMissingBean 條件不滿足,默認(rèn)配置不生效,用戶的自定義 Bean 會(huì)覆蓋默認(rèn)配置

十一、底層原理:自動(dòng)配置 +@Conditional的完整執(zhí)行流程

Spring Boot 啟動(dòng)時(shí),這套機(jī)制分為三步執(zhí)行:

  1. 掃描收集自動(dòng)配置類:?jiǎn)?dòng)時(shí)掃描所有依賴 jar 包中的 AutoConfiguration.imports 文件,收集所有配置類,放入「候選列表」(此時(shí)未加載,僅登記)。
  2. 逐個(gè)條件判斷:遍歷候選列表,根據(jù)配置類 / 方法上的 @Conditional 系列注解,執(zhí)行條件匹配,篩選出滿足條件的配置類。
  3. 加載并注冊(cè) Bean:滿足條件的配置類會(huì)被加載,@Bean 方法執(zhí)行并注冊(cè) Bean;不滿足條件的配置類直接跳過(guò),不占用資源。

到此這篇關(guān)于Spring Boot 配置加載全解析:從 @ComponentScan 到自動(dòng)配置原理的文章就介紹到這了,更多相關(guān)SpringBoot自動(dòng)配置原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

鄂托克旗| 武邑县| 池州市| 永州市| 巴彦县| 广州市| 丹寨县| 祁连县| 卢湾区| 焦作市| 沈丘县| 临沂市| 色达县| 南澳县| 济宁市| 拉孜县| 六枝特区| 边坝县| 海原县| 镇宁| 香港 | 铜鼓县| 读书| 兴隆县| 临漳县| 普兰县| 彭山县| 古丈县| 靖江市| 中超| 金阳县| 洪洞县| 建水县| 驻马店市| 嘉荫县| 清新县| 宜兰市| 遂平县| 安顺市| 历史| 大宁县|