SpringBoot中的條件注解使用示例詳解
前言
在SpringBoot開發(fā)中,我們經(jīng)常會(huì)遇到這樣的場(chǎng)景:某些Bean只有在特定條件下才需要被創(chuàng)建,或者根據(jù)不同的環(huán)境加載不同的配置。SpringBoot的條件注解就是為了解決這類問(wèn)題而設(shè)計(jì)的。
什么是條件注解
條件注解是SpringBoot提供的一套機(jī)制,允許我們根據(jù)特定條件來(lái)決定是否創(chuàng)建Bean、加載配置或執(zhí)行某些邏輯。這些注解基于Spring 4.0引入的@Conditional注解,SpringBoot在此基礎(chǔ)上擴(kuò)展了更多實(shí)用的條件注解。
核心原理
所有的條件注解都基于@Conditional注解,該注解需要指定一個(gè)Condition接口的實(shí)現(xiàn)類。Condition接口只有一個(gè)方法:
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
當(dāng)Spring容器加載Bean時(shí),會(huì)調(diào)用這個(gè)方法來(lái)判斷條件是否滿足。如果返回true,則創(chuàng)建Bean;如果返回false,則跳過(guò)。
常用條件注解詳解
1. @ConditionalOnClass和@ConditionalOnMissingClass
這兩個(gè)注解用于檢查類路徑中是否存在指定的類。
@Configuration
public class DatabaseConfig {
// 當(dāng)類路徑中存在DataSource類時(shí)才創(chuàng)建這個(gè)Bean
@Bean
@ConditionalOnClass(DataSource.class)
public DataSource dataSource() {
return new HikariDataSource();
}
// 當(dāng)類路徑中不存在Redis相關(guān)類時(shí)才創(chuàng)建內(nèi)存緩存
@Bean
@ConditionalOnMissingClass("org.springframework.data.redis.core.RedisTemplate")
public CacheManager memoryCache() {
return new ConcurrentMapCacheManager();
}
}2. @ConditionalOnBean和@ConditionalOnMissingBean
這兩個(gè)注解根據(jù)Spring容器中是否存在指定的Bean來(lái)決定是否創(chuàng)建。
@Configuration
public class ServiceConfig {
// 當(dāng)容器中存在UserRepository Bean時(shí)才創(chuàng)建UserService
@Bean
@ConditionalOnBean(UserRepository.class)
public UserService userService(UserRepository userRepository) {
return new UserServiceImpl(userRepository);
}
// 當(dāng)容器中不存在CacheManager時(shí)才創(chuàng)建默認(rèn)的
@Bean
@ConditionalOnMissingBean(CacheManager.class)
public CacheManager defaultCacheManager() {
return new NoOpCacheManager();
}
}3. @ConditionalOnProperty
根據(jù)配置屬性來(lái)決定是否創(chuàng)建Bean,這是最常用的條件注解之一。
@Configuration
public class FeatureConfig {
// 當(dāng)spring.feature.enabled=true時(shí)才啟用這個(gè)功能
@Bean
@ConditionalOnProperty(
prefix = "spring.feature",
name = "enabled",
havingValue = "true",
matchIfMissing = false // 默認(rèn)false,即屬性不存在時(shí)不匹配
)
public FeatureService featureService() {
return new FeatureServiceImpl();
}
}應(yīng)用場(chǎng)景:多數(shù)據(jù)源配置
@Configuration
public class DataSourceConfig {
@Primary
@Bean
@ConditionalOnProperty(name = "app.datasource.primary.enabled", havingValue = "true")
public DataSource primaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/primary")
.build();
}
@Bean
@ConditionalOnProperty(name = "app.datasource.secondary.enabled", havingValue = "true")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://localhost:3306/secondary")
.build();
}
}在SpringBoot自動(dòng)配置中的核心作用
SpringBoot的自動(dòng)配置是其最核心的特性之一,而條件注解正是自動(dòng)配置得以智能化的關(guān)鍵所在。讓我們深入了解條件注解在自動(dòng)配置中是如何發(fā)揮作用的。
自動(dòng)配置的工作原理
SpringBoot通過(guò)spring.factories文件定義了所有的自動(dòng)配置類,啟動(dòng)時(shí)會(huì)加載這些配置。但是,并不是所有的配置都應(yīng)該被激活,這就需要條件注解來(lái)控制。
# META-INF/spring.factories示例 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
經(jīng)典自動(dòng)配置示例分析
讓我們看看SpringBoot內(nèi)置的一些自動(dòng)配置是如何使用條件注解的:
- RedisAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class) // Redis類存在時(shí)才配置
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate") // 用戶沒(méi)有自定義時(shí)才創(chuàng)建
@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);
}
}- DataSourceAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "javax.sql.DataSource") // 沒(méi)有數(shù)據(jù)源時(shí)才自動(dòng)配置
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class) // 自定義條件判斷
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ HikariConfiguration.class, TomcatConfiguration.class,
DbcpConfiguration.class, OracleUcpConfiguration.class,
GenericConfiguration.class, DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
}總結(jié)
SpringBoot的條件注解是一個(gè)非常強(qiáng)大的特性,它讓我們能夠構(gòu)建更加靈活和智能的應(yīng)用程序。通過(guò)合理使用這些注解,不僅能讓我們寫出更優(yōu)雅的代碼,也能讓我們的應(yīng)用在面對(duì)不同場(chǎng)景時(shí)表現(xiàn)得更加智能。希望這篇文章能幫助大家更好地理解和使用SpringBoot的條件注解。
到此這篇關(guān)于SpringBoot中的條件注解的文章就介紹到這了,更多相關(guān)SpringBoot條件注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
@Scheduled中的參數(shù)及Cron時(shí)間表達(dá)式用法詳解
在SpringBoot中使用@Scheduled注解設(shè)置定時(shí)任務(wù),可設(shè)置fixedDelay、fixedRate、initialDelay和cron參數(shù),首句概括,后續(xù)分條列出參數(shù)解釋和Cron表達(dá)式格式,最后給出示例2026-05-05
MapStruct @Mapping注解之處理映射中的Null值方式
這篇文章主要介紹了MapStruct @Mapping注解之處理映射中的Null值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03
最新IntelliJ?IDEA?2022配置?Tomcat?8.5?的詳細(xì)步驟演示
這篇文章主要介紹了IntelliJ?IDEA?2022?詳細(xì)配置?Tomcat?8.5?步驟演示,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
mybatis條件構(gòu)造器(EntityWrapper)的使用方式
這篇文章主要介紹了mybatis條件構(gòu)造器(EntityWrapper)的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java高級(jí)語(yǔ)法學(xué)習(xí)之反射詳解
java的泛型和反射機(jī)制一直很難理解和應(yīng)用,下面這篇文章主要給大家介紹了關(guān)于Java高級(jí)語(yǔ)法學(xué)習(xí)之反射的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-01-01
Intellij idea使用Statistic統(tǒng)計(jì)代碼行數(shù)的方法
這篇文章主要介紹了Intellij idea使用Statistic統(tǒng)計(jì)代碼行數(shù)的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
Java 基于TCP Socket 實(shí)現(xiàn)文件上傳
這篇文章主要介紹了Java 基于TCP Socket 實(shí)現(xiàn)文件上傳的示例代碼,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12

