欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

揭秘Spring核心注解@Configuration與@Component的本質(zhì)區(qū)別

 更新時間:2025年07月10日 08:48:08   作者:一勺菠蘿丶  
在Spring框架中,@Configuration和@Component都是常用的注解,但它們有著本質(zhì)的區(qū)別,本文將深入剖析這兩者的核心區(qū)別,并通過代碼示例展示它們的實際行為差異

引言:Spring中的兩個關(guān)鍵角色

在Spring框架中,@Configuration@Component都是常用的注解,但它們有著本質(zhì)的區(qū)別。許多開發(fā)者在使用時容易混淆它們的行為,特別是當(dāng)涉及@Bean方法時。本文將深入剖析這兩者的核心區(qū)別,并通過代碼示例展示它們的實際行為差異。

核心區(qū)別一覽表

場景被標(biāo)記的類本身類內(nèi)部調(diào)用 @Bean 方法
@Component/@Service 類默認(rèn)單例每次調(diào)用都創(chuàng)建新對象
@Configuration 類默認(rèn)單例調(diào)用其他 @Bean 方法返回單例

這個表格揭示了Spring中一個關(guān)鍵但常被誤解的區(qū)別:類本身的單例行為與類內(nèi)部方法調(diào)用的單例行為是不同的概念。

場景一:業(yè)務(wù)組件(@Component/@Service)

類本身的單例行為

@Service // 等同于 @Component
public class UserService {
    // 業(yè)務(wù)邏輯...
}

類本身是單例

Spring容器只會創(chuàng)建一個UserService實例

通過@Autowired注入時

注入的是同一個實例

@Controller
public class UserController {
    @Autowired 
    private UserService service1; // 單例
    
    @Autowired 
    private UserService service2; // 同一個單例
    
    public void checkSingleton() {
        System.out.println(service1 == service2); // 輸出 true
    }
}

關(guān)鍵特性

  • Spring直接管理類的實例化(單例)
  • 不涉及方法調(diào)用攔截
  • 適用于業(yè)務(wù)邏輯組件(Service、Controller等)

場景二:配置類中的@Bean方法調(diào)用

危險示例:在@Component中調(diào)用@Bean方法

@Component // 錯誤用法!
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        System.out.println("創(chuàng)建新的DataSource實例");
        return new HikariDataSource(); // 創(chuàng)建連接池
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate() {
        // 直接調(diào)用 → 每次創(chuàng)建新連接池!
        return new JdbcTemplate(dataSource()); 
    }
}

問題所在

當(dāng)Spring調(diào)用jdbcTemplate()方法時:

直接執(zhí)行dataSource()方法

每次調(diào)用都new HikariDataSource() → 創(chuàng)建多個連接池

輸出結(jié)果:

創(chuàng)建新的DataSource實例
創(chuàng)建新的DataSource實例

根本原因

  • @Component類沒有代理機(jī)制
  • @Bean方法調(diào)用等同于普通Java方法調(diào)用
  • 導(dǎo)致單例被破壞,資源被重復(fù)創(chuàng)建

安全解決方案

方案一:使用@Configuration代理保護(hù)

@Configuration // 關(guān)鍵!
public class CorrectConfig {
    @Bean
    public A a() {
        return new A(b()); // ? 代理確??偡祷赝粚嵗?
    }
    
    @Bean
    public B b() { 
        System.out.println("創(chuàng)建B實例");
        return new B(); 
    }
}

代理機(jī)制

Spring通過CGLIB代理增強(qiáng)@Configuration

單例保護(hù)

多次調(diào)用b()返回同一個實例

輸出結(jié)果:

創(chuàng)建B實例 // 僅打印一次

方案二:使用方法參數(shù)注入(推薦)

@Configuration // 或 @Component
public class BestConfig {
    @Bean
    public A a(B b) { // ? 通過參數(shù)注入單例
        return new A(b);
    }
    
    @Bean
    public B b() { return new B(); }
}
  • 最安全的方式
  • 適用于@Configuration和@Component
  • 明確聲明依賴關(guān)系,代碼更清晰

為什么會有這種差異?

1.@Component/@Service類

  • Spring直接管理類的實例化(單例)
  • 不涉及方法調(diào)用攔截
  • 設(shè)計目標(biāo):業(yè)務(wù)組件實現(xiàn)

2.@Configuration類

  • Spring通過CGLIB代理增強(qiáng)類
  • 攔截@Bean方法調(diào)用,確保單例
  • 設(shè)計目標(biāo):Bean定義和配置中心

實際應(yīng)用場景

正確使用@Configuration

@Configuration
public class AppConfig {
    // 全局單例的基礎(chǔ)設(shè)施
    @Bean
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost/db");
        return ds;
    }
    
    // 安全調(diào)用其他@Bean方法
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

正確使用@Component

@Service
public class OrderService {
    // 業(yè)務(wù)方法
    public void processOrder(Order order) {
        // 業(yè)務(wù)邏輯...
    }
}

常見錯誤及修復(fù)

錯誤示例

@Component // 錯誤!應(yīng)該用@Configuration
public class PaymentConfig {
    @Bean
    public PaymentService paymentService() {
        // 每次創(chuàng)建新驗證器 → 破壞單例
        return new PaymentService(validator()); 
    }
    
    @Bean
    public Validator validator() { 
        return new PaymentValidator();
    }
}

修復(fù)方案

@Configuration // 修復(fù)方法1:改為@Configuration
public class PaymentConfig {
    @Bean
    public PaymentService paymentService(Validator validator) { // 修復(fù)方法2:參數(shù)注入
        return new PaymentService(validator);
    }
    
    @Bean
    public Validator validator() { 
        return new PaymentValidator();
    }
}

終極總結(jié)

“被@Component或@Service標(biāo)記的類本身默認(rèn)是單例的,@Autowired注入時不會創(chuàng)建新對象。

但在@Component類內(nèi)部調(diào)用@Bean方法時,會像普通Java方法一樣執(zhí)行,每次調(diào)用都創(chuàng)建新實例。

而@Configuration類通過CGLIB代理,確??鏎Bean方法調(diào)用時始終返回單例。”

這個區(qū)別反映了Spring的兩種不同機(jī)制:

  • 組件管理@Component/@Service):處理類實例本身
  • 配置代理@Configuration):處理方法間的調(diào)用關(guān)系

結(jié)語

理解@Configuration@Component的本質(zhì)區(qū)別對于構(gòu)建健壯的Spring應(yīng)用至關(guān)重要。記住以下黃金法則:

  • 配置基礎(chǔ)設(shè)施 → 使用@Configuration
  • 聲明業(yè)務(wù)組件 → 使用@Component/@Service/@Controller
  • 跨Bean依賴 → 總是使用方法參數(shù)注入

面試總結(jié)

"在 @Configuration 類中,所有 @Bean 方法都會CGLIB 代理。當(dāng)在同一個配置類中調(diào)用其他 @Bean 方法時,Spring 會確保始終返回同一個單例實例。而在 @Component 類中,直接調(diào)用 @Bean 方法會像普通 Java 方法一樣執(zhí)行,每次調(diào)用都創(chuàng)建新實例,破壞單例性。

  • @Configuration 用于創(chuàng)建需要全局唯一的基礎(chǔ)設(shè)施(如數(shù)據(jù)庫連接池、線程池)
  • @Component 用于聲明業(yè)務(wù)組件(如Service、Controller), 一般不在@Component中去定義@Bean"

到此這篇關(guān)于揭秘Spring核心注解@Configuration與@Component的本質(zhì)區(qū)別的文章就介紹到這了,更多相關(guān)Spring注解@Configuration與@Component內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解SpringBoot開發(fā)案例之整合Dubbo分布式服務(wù)

    詳解SpringBoot開發(fā)案例之整合Dubbo分布式服務(wù)

    這篇文章主要介紹了詳解SpringBoot開發(fā)案例之整合Dubbo分布式服務(wù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • java實現(xiàn)商品管理系統(tǒng)

    java實現(xiàn)商品管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)商品管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • spring項目中切面及AOP的使用方法

    spring項目中切面及AOP的使用方法

    我們知道,spring兩大核心,IOC(控制反轉(zhuǎn))和AOP(切面),那為什么要使用AOP,AOP是什么呢?帶著這些問題通過本文學(xué)習(xí)下吧
    2021-06-06
  • Java數(shù)據(jù)結(jié)構(gòu)中關(guān)于AVL樹的實現(xiàn)方法詳解

    Java數(shù)據(jù)結(jié)構(gòu)中關(guān)于AVL樹的實現(xiàn)方法詳解

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)中關(guān)于AVL樹的實現(xiàn)方法,AVL樹是高度平衡的二叉樹,它的特點是AVL樹中任何節(jié)點的兩個子樹的高度最大差別為1,本文主要給大家介紹了Java語言如何實現(xiàn)AVL樹,需要的朋友可以參考下
    2024-02-02
  • JDBC SQL語法

    JDBC SQL語法

    結(jié)構(gòu)化查詢語言(SQL)是一種標(biāo)準(zhǔn)化的語言,它允許你在數(shù)據(jù)庫上執(zhí)行操作,如創(chuàng)建項目,讀取內(nèi)容,內(nèi)容更新和刪除條目
    2014-03-03
  • java中關(guān)于移位運算符的demo與總結(jié)(推薦)

    java中關(guān)于移位運算符的demo與總結(jié)(推薦)

    下面小編就為大家?guī)硪黄猨ava中關(guān)于移位運算符的demo與總結(jié)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-05-05
  • mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    這篇文章主要介紹了mybatis實現(xiàn)批量插入并返回主鍵(xml和注解兩種方法),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的問題

    使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的問題

    這篇文章主要介紹了使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2015-11-11
  • Spring Boot與Kotlin定時任務(wù)的示例(Scheduling Tasks)

    Spring Boot與Kotlin定時任務(wù)的示例(Scheduling Tasks)

    這篇文章主要介紹了Spring Boot與Kotlin定時任務(wù)的示例(Scheduling Tasks),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Java浮點類數(shù)字運算方式

    Java浮點類數(shù)字運算方式

    在進(jìn)行浮點數(shù)的加減運算時,直接使用+和-可能會引入精度誤差,為了比較浮點數(shù),可以使用Double的compareTo()方法,或者通過定義一個容差值(Epsilon)來判斷兩個浮點數(shù)是否相等,此外,Double.compare()方法也能比較兩個double值
    2024-10-10

最新評論