重學SpringBoot3-@ConditionalOnXxx條件注解
- 引言
- 常見的條件注解
- 常見的條件注解示例
- 擴展條件注解
- 1. @ConditionalOnJndi
- 2. @ConditionalOnJava
- 3. @ConditionalOnCloudPlatform
- 4. @ConditionalOnEnabledResourceChain
- 5. 自定義條件注解
- 總結
引言
Spring Boot 提供了一組強大的條件注解(形如 @ConditionalOnXxx
),這些注解允許開發者根據特定的條件來控制配置類或者 bean 的創建。這種機制支持靈活的配置和自動配置,是 Spring Boot “約定優于配置”理念的體現。
常見的條件注解
以下是一些 Spring Boot 中常見的條件注解及其作用:
-
@ConditionalOnBean 和 @ConditionalOnMissingBean:這兩個注解控制一個 bean 的創建是否依賴于容器中是否存在另一個 bean。例如,只有當容器中存在
DataSource
類型的 bean 時,某個數據訪問相關的 bean 才會被創建。 -
@ConditionalOnClass 和 @ConditionalOnMissingClass:這些注解根據類路徑上是否存在某個類來控制配置類或 bean 的創建。這對于基于可用依賴自動配置組件非常有用。
-
@ConditionalOnProperty:這個注解允許基于 Spring Environment 的屬性值來控制 bean 的創建。例如,你可以根據某個特定的屬性是否存在或值為何來決定是否創建一個 bean。
-
@ConditionalOnResource:當一個特定的資源存在于類路徑上時,相關的配置或 beans 才會被創建。
-
@ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication:這兩個注解基于應用是否是一個 web 應用來控制配置或 beans 的創建。
-
@ConditionalOnExpression:基于 SpEL 表達式的評估結果來控制 bean 的創建。
常見的條件注解示例
下面是一些使用 Spring Boot 條件注解的示例:
@Configuration
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
public class JdbcTemplateAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}
}
在這個例子中,JdbcTemplateAutoConfiguration
配置類只有在 DataSource
和 JdbcTemplate
類都在類路徑上時才會被激活。同時,jdbcTemplate
bean 只有在缺失時才會被創建。
@Configuration
@ConditionalOnWebApplication
public class WebConfig {@Beanpublic User myUser() {return new User();}
}
在這個例子中,WebConfig
配置類只有在應用是一個 web 應用時才會生效。
@Bean
@ConditionalOnProperty(name = "user.show", havingValue = "true")
public User myUser1() {return new User();
}
這里,myUser1
只有在 application.properties
文件中設置了 use.my.bean=true
時才會被創建。
@Bean
@ConditionalOnExpression("#{environment['spring.profiles.active'] == 'dev' && systemProperties['user.country'] == 'CN'}")
public User myUser2() {return new User();
}
這里,myUser2
只在當前激活的 Spring
配置文件為 dev
且系統屬性 user.country
設置為 CN
時創建。
擴展條件注解
還有一些不常用但可以幫助開發者根據不同的環境或條件靈活配置應用。下面是一些額外的條件注解及其用法:
1. @ConditionalOnJndi
@ConditionalOnJndi
注解可以控制配置或 beans 的創建,依賴于 JNDI (Java Naming and Directory Interface) 的存在。例如,只有當特定的 JNDI 資源可用時,某個 bean 才會被創建。
@Configuration
@ConditionalOnJndi("java:comp/env/jdbc/DataSource")
public class JndiDataConfig {// 配置類定義
}
這里,JndiDataConfig
配置類只有在名為 java:comp/env/jdbc/DataSource
的 JNDI
資源存在時才會生效。
2. @ConditionalOnJava
@ConditionalOnJava
控制配置或 bean 的創建,基于 Java 版本。這允許你編寫只在特定版本的 Java 環境下才激活的配置。
@Configuration
@ConditionalOnJava(JavaVersion.EIGHT)
public class Java8Config {// 配置類定義
}
在這個例子中,Java8Config
配置類只有在 Java 8 環境中才會生效。
3. @ConditionalOnCloudPlatform
@ConditionalOnCloudPlatform
是 Spring Boot 2.2 引入的注解,用于根據應用運行的云平臺環境來控制配置或 bean 的創建。例如,你可以基于應用是否在 AWS 或 Azure 上運行來進行不同的配置。
@Configuration
@ConditionalOnCloudPlatform(CloudPlatform.AWS)
public class AwsConfig {// 配置類定義
}
在這個例子中,AwsConfig
只在 AWS 環境下才會生效。
4. @ConditionalOnEnabledResourceChain
@ConditionalOnEnabledResourceChain
是 Spring Boot 中的一個條件注解,主要用于 Web 資源優化配置。它用于條件性地配置資源鏈(Resource Chain),以提高 Web 應用程序中靜態資源(如 JavaScript、CSS 文件)的服務效率。
@Configuration
@ConditionalOnEnabledResourceChain
public class CustomResourceChainConfig {// 在這里定義資源鏈相關的 bean 或配置
}
只有當 application.properties
或 application.yml
中的配置項 spring.resources.chain.enabled
被設置為 true 時,CustomResourceChainConfig
中的配置才會被注冊和生效。
5. 自定義條件注解
除了使用 Spring Boot 提供的條件注解外,你還可以創建自己的條件注解。這通常涉及實現 Condition
接口,并使用 @Conditional
注解來應用它。這允許你定義非常具體和細粒度的條件邏輯。
public class OnSystemPropertyCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {return "true".equals(System.getProperty("my.custom.property"));}
}@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {// 注解定義
}
使用這個自定義注解,你可以控制只有當系統屬性 my.custom.property
設置為 true
時,相關的配置或 beans 才會被創建。
總結
Spring Boot 的條件注解提供了一種強大且靈活的方式來根據不同的條件動態地配置 Spring 應用。通過使用這些注解,開發者可以輕松實現基于條件的自動配置,這使得應用配置更加簡潔和高效。掌握這些條件注解,將有助于你更好地理解和使用 Spring Boot 的自動配置功能。