重学SpringBoot3-@ConditionalOnXxx条件注解

重学SpringBoot3-@ConditionalOnXxx条件注解

CoderJia 25 2024-03-02

ConditionalOnXxx

引言

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
    @ConditionalOnMissingBean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

在这个例子中,JdbcTemplateAutoConfiguration 配置类只有在 DataSourceJdbcTemplate 类都在类路径上时才会被激活。同时,jdbcTemplate bean 只有在缺失时才会被创建。

@Configuration
@ConditionalOnWebApplication
public class WebConfig {

    @Bean
    public 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/DataSourceJNDI 资源存在时才会生效。

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.propertiesapplication.yml 中的配置项 spring.resources.chain.enabled 被设置为 true 时,CustomResourceChainConfig 中的配置才会被注册和生效。

5. 自定义条件注解

除了使用 Spring Boot 提供的条件注解外,你还可以创建自己的条件注解。这通常涉及实现 Condition 接口,并使用 @Conditional 注解来应用它。这允许你定义非常具体和细粒度的条件逻辑。

public class OnSystemPropertyCondition implements Condition {

    @Override
    public 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 的自动配置功能。