Spring創(chuàng)建Bean的八種主要方式詳解
引言
Spring(尤其是 Spring Boot)提供了多種方式來讓容器創(chuàng)建和管理 Bean。@Component、@Configuration + @Bean、@EnableConfigurationProperties 都是常見方式。
下面我為你系統(tǒng)地梳理 Spring 創(chuàng)建 Bean 的所有主要方式,并說明它們的使用場景和區(qū)別。
一、Spring 創(chuàng)建 Bean 的 8 種主要方式
| 方式 | 注解/方法 | 適用場景 |
|---|---|---|
| 1 | @Component 及其衍生注解 | 掃描普通類為 Bean |
| 2 | @Configuration + @Bean | 手動配置第三方類或復雜對象 |
| 3 | @EnableConfigurationProperties + @ConfigurationProperties | 將配置文件映射為 Bean |
| 4 | @Import | 導入配置類或直接注冊 Bean |
| 5 | 實現(xiàn) FactoryBean<T> | 創(chuàng)建復雜或條件性對象 |
| 6 | 使用 @Conditional 系列注解 | 條件化注冊 Bean |
| 7 | 編程式注冊:BeanDefinitionRegistryPostProcessor | 動態(tài)注冊 Bean(高級) |
| 8 | XML 配置(傳統(tǒng)方式) | 老項目兼容 |
1. @Component 及其衍生注解(最常用)
@Component @Service @Repository @Controller @RestController @Configuration // @Configuration 也是 @Component
- 原理:配合
@ComponentScan,Spring 會掃描這些類并注冊為 Bean。 - 適用:你自己寫的業(yè)務(wù)類(Service、DAO、Controller 等)。
@Service
public class UserService {
public void save() { ... }
}
? 自動注冊為 userService Bean。
2. @Configuration + @Bean(手動注冊)
用于注冊不能加 @Component 的類(如第三方庫的類)。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
}
- 適用:數(shù)據(jù)源、RedisTemplate、RabbitMQ、RocketMQ、OkHttp、HttpClient 等第三方組件。
3. @EnableConfigurationProperties + @ConfigurationProperties
將 application.yml 中的配置自動綁定為 Bean。
app: title: MyApp version: 1.0.0
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String title;
private String version;
// getter/setter
}
@Configuration
@EnableConfigurationProperties(AppProperties.class)
public class AppConfig {
}
? AppProperties 會被 Spring 創(chuàng)建并注入配置值,且可被 @Autowired。
在 Spring Boot 2.2+ 中,@EnableConfigurationProperties 通??梢允÷?,只要類加了 @ConfigurationProperties 并被掃描到即可。
4. @Import(導入配置類或直接注冊)
三種用法:
(1) 導入 @Configuration 類
@Import(DatabaseConfig.class)
@SpringBootApplication
public class Application { }
(2) 導入 @Component 類
@Import(UserService.class)
(3) 導入 ImportSelector 或 ImportBeanDefinitionRegistrar
@Import(MyImportSelector.class)
public class Application { }
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{MyService.class.getName()};
}
}
? 用于實現(xiàn)“條件導入”、“SPI 擴展”等高級功能。
5. 實現(xiàn) FactoryBean<T>(創(chuàng)建復雜對象)
當你需要復雜的創(chuàng)建邏輯時使用。
public class MyFactoryBean implements FactoryBean<MyService> {
@Override
public MyService getObject() throws Exception {
MyService service = new MyService();
service.init(); // 復雜初始化
return service;
}
@Override
public Class<?> getObjectType() {
return MyService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
@Component
public class MyFactoryBean { } // Spring 會調(diào)用 getObject() 創(chuàng)建 MyService Bean
? 適合創(chuàng)建代理對象、動態(tài)對象、SPI 實現(xiàn)等。
6. @Conditional 系列注解(條件化注冊)
只有滿足條件時才創(chuàng)建 Bean。
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource dataSource() {
return new HikariDataSource();
}
常見條件注解:
| 注解 | 說明 |
|---|---|
| @ConditionalOnClass | 類路徑存在某個類 |
| @ConditionalOnMissingBean | 容器中沒有某個 Bean |
| @ConditionalOnProperty | 配置文件中有某個屬性 |
| @ConditionalOnWebApplication | 是 Web 應用 |
| @ConditionalOnExpression | SpEL 表達式為 true |
? 這是 Spring Boot 自動配置的核心機制。
7. 編程式注冊:BeanDefinitionRegistryPostProcessor
最強大、最靈活的方式,可以在容器啟動時動態(tài)注冊 Bean。
@Component
public class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(UserService.class);
AbstractBeanDefinition definition = builder.getBeanDefinition();
registry.registerBeanDefinition("userService", definition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do nothing
}
}
? 適合插件化、動態(tài)加載、AOP 增強等場景。
8. XML 配置(傳統(tǒng)方式)
<bean id="userService" class="com.example.UserService"/>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
? 現(xiàn)在已不推薦,但在老項目中仍可見。
總結(jié)對比
| 方式 | 何時使用 | 推薦度 |
|---|---|---|
| @Component | 自己寫的類 | ????? |
| @Configuration + @Bean | 第三方類、復雜配置 | ????? |
| @ConfigurationProperties | 配置文件映射 | ???? |
| @Import | 模塊化導入 | ??? |
| FactoryBean | 復雜對象創(chuàng)建 | ??? |
| @Conditional | 條件注冊 | ????(自動配置核心) |
| BeanDefinitionRegistryPostProcessor | 動態(tài)注冊 | ??(高級) |
| XML | 老項目 | ? |
最佳實踐建議
- 優(yōu)先使用
@Component和@Bean,簡單直接; - 配置參數(shù)用
@ConfigurationProperties,類型安全; - 避免重復注冊,善用
@ConditionalOnMissingBean; - 復雜邏輯用
@Import或FactoryBean; - 動態(tài)場景用
BeanDefinitionRegistryPostProcessor(謹慎使用)。
以上就是Spring創(chuàng)建Bean的八種主要方式詳解的詳細內(nèi)容,更多關(guān)于Spring創(chuàng)建Bean方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring-boot-maven-plugin插件爆紅問題及解決方案
這篇文章主要介紹了spring-boot-maven-plugin插件爆紅問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05
SpringBoot整合Mongodb實現(xiàn)增刪查改的方法
這篇文章主要介紹了SpringBoot整合Mongodb實現(xiàn)簡單的增刪查改,MongoDB是一個以分布式數(shù)據(jù)庫為核心的數(shù)據(jù)庫,因此高可用性、橫向擴展和地理分布是內(nèi)置的,并且易于使用。況且,MongoDB是免費的,開源的,感興趣的朋友跟隨小編一起看看吧2022-05-05
Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼
這篇文章主要介紹了Mybatis如何傳入多個參數(shù)的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12
使用Java動態(tài)創(chuàng)建Flowable會簽模型的示例代碼
動態(tài)創(chuàng)建流程模型,尤其是會簽(Parallel Gateway)模型,是提升系統(tǒng)靈活性和響應速度的關(guān)鍵技術(shù)之一,本文將通過Java編程語言,深入探討如何在運行時動態(tài)地創(chuàng)建包含會簽環(huán)節(jié)的Flowable流程模型,需要的朋友可以參考下2024-05-05

