Spring @Bean 與 @ComponentScan 的差異
有時候在寫 Spring config 時,新手都會搞不清楚 @Bean 和 @ComponentScan 到底差在哪。我自己也踩過不少坑,今天就來把這兩個概念理清楚。
先說結論
簡單講:
- @Bean 是手動註冊,你明確地在 @Configuration 裡面寫程式碼,告訴 Spring 怎麼建立這個 Bean
- @ComponentScan 是自動掃描,Spring 自動找出你用 @Component、@Service、@Repository 這些註解標注的類別,然後註冊成 Bean
兩者各有用途,也可以混用。
@Bean 怎麼用
@Bean 通常用在 @Configuration class 裡面。你寫一個方法,用 @Bean 標注,Spring 就會把這個方法回傳的物件當成 Bean 註冊進去。
1 |
|
看到了沒,方法的名字就變成 Bean 的名字。上面的例子裡,Bean name 分別是 dataSource 和 jdbcTemplate。
如果你想自訂 Bean name,可以這樣:
1 |
|
你也可以指定多個名字:
1 |
|
@ComponentScan 怎麼用
@ComponentScan 就簡單多了,它告訴 Spring 去掃某個 package,把裡面所有用 @Component、@Service、@Repository、@Controller 標注的類別都拿去註冊成 Bean。
1 |
|
或是用 basePackageClasses,這樣可以避免 hardcode package name:
1 |
|
如果你在標注 @Component 的類別上面寫:
1 |
|
Bean name 就會自動用類別名的首字母小寫,所以上面的 Bean name 是 userService。
當然你也可以指定:
1 |
|
差異在哪?
說到關鍵的差異了。
@Bean 最大的優點就是彈性高,你可以處理那些你改不了的第三方 library class。 比如說你用了一個外部的 library,提供了一個 DataSource class,你沒辦法在那個 class 上面加 @Component。這時候 @Bean 就派上用場了:
1 |
|
@ComponentScan 就比較適合你自己寫的 class。 只要你把 @Component 或 @Service 之類的註解標上去,Spring 就會自動掃描註冊,簡潔有力。
可以混用嗎?
可以啊,完全沒問題。一般的專案都是這樣做的:
1 |
|
然後在自己的 service class 上面:
1 |
|
Spring Boot 的預設行為
順便提一下,如果你用 Spring Boot,有個 @SpringBootApplication 註解幫你自動做了很多事。它其實就包含了 @Configuration 和 @ComponentScan。預設會掃描 main class 所在的 package 及其所有子 package。
所以很多時候你根本不用手動寫 @ComponentScan,Spring Boot 已經幫你做好了。但如果你要掃描其他 package,就得自己加設定。
重點整理
- @Bean:手動註冊,適合第三方 library class
- @ComponentScan:自動掃描,適合自己寫的 class
- Bean name:@Bean 用方法名(或自訂),@ComponentScan 用首字母小寫的類別名(或自訂)
- 兩者可以混用,很常見
- Spring Boot 預設已經有 @ComponentScan 了
這樣下次再看到有人糾結 @Bean vs @ComponentScan,你就可以輕鬆解釋了。










