问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Spring Boot条件注解详解:从基础概念到实战应用

创作时间:
作者:
@小白创作中心

Spring Boot条件注解详解:从基础概念到实战应用

引用
CSDN
1.
https://blog.csdn.net/lishangke/article/details/145979619

在Spring Boot开发中,条件化Bean装配是一个非常实用的功能,它可以根据不同的环境和配置动态加载Bean。本文将详细介绍Spring Boot中@Conditional注解的使用及其相关衍生注解,包括@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty等,并通过具体示例帮助读者理解如何根据不同的条件来控制Bean的加载。

1、简述

在 Spring Boot 中,@Conditional注解用于实现条件化 Bean 装配,即根据特定的条件来决定是否加载某个 Bean。它是 Spring 框架中的一个扩展机制,常用于实现模块化、可配置的组件加载。
本文将详细介绍@Conditional相关的注解,包括@ConditionalOnClass@ConditionalOnMissingBean@ConditionalOnProperty等,并结合实际应用示例讲解其使用方式。

2、@Conditional 注解概述

@Conditional是 Spring 4 引入的条件装配注解,它可以根据外部环境或配置的状态,决定是否创建 Bean。
其核心接口是:


public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

任何实现
Condition
接口的类,都可以用于自定义条件判断


@Configuration
public class MyConfig {
    @Bean
    @Conditional(MyCondition.class) 
    public MyService myService() {
        return new MyService();
    }
}

其中
MyCondition.class
需要实现
Condition
接口,并提供判断逻辑。

3、Spring Boot 内置 @Conditional 相关注解

Spring Boot 提供了一些常见的
@Conditional
注解,简化了条件判断的逻辑:

注解
作用
@ConditionalOnClass
类路径下存在某个类时,才加载该 Bean
@ConditionalOnMissingClass
类路径下不存在某个类时,才加载该 Bean
@ConditionalOnBean
当容器中存在指定 Bean 时,才加载当前 Bean
@ConditionalOnMissingBean
当容器中不存在指定 Bean 时,才加载当前 Bean
@ConditionalOnProperty
当指定的配置属性满足条件时,才加载当前 Bean
@ConditionalOnExpression
当指定的 SpEL 表达式为true时,才加载当前 Bean
@ConditionalOnJava
当 Java 版本符合要求时,才加载当前 Bean
@ConditionalOnWebApplication
当应用是 Web 应用时,才加载当前 Bean
@ConditionalOnNotWebApplication
当应用不是Web 应用时,才加载当前 Bean

3.1 @ConditionalOnClass 使用示例(类路径检测)

我们希望在Spring Boot 项目中,当类路径下存在
com.example.MyLibrary
这个类时,才注册
MyService
这个 Bean。


import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnClass(name = "com.example.MyLibrary")
    public MyService myService() {
        return new MyService();
    }
}

解释:

  • 如果
    com.example.MyLibrary
    存在,则
    MyService
    会被创建。
  • 如果
    com.example.MyLibrary
    不存在,则
    MyService
    不会被加载

3.2 @ConditionalOnMissingBean(Bean 缺失时加载)

如果用户没有手动定义
MyService
,则提供一个默认实现。


import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public MyService myService() {
        return new MyService("Default Implementation");
    }
}

解释:

  • 如果 Spring 容器中已经存在
    MyService
    ,则不会创建新的 Bean。
  • 只有当
    MyService
    不存在时,才会注册默认实现。

3.3 @ConditionalOnProperty(基于配置项条件加载 Bean)

我们希望
MyService
只有在
app.feature.enabled=true
时才被创建。


import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnProperty(name = "app.feature.enabled", havingValue = "true", matchIfMissing = false)
    public MyService myService() {
        return new MyService();
    }
}

解释:

  • 如果
    application.properties
    中包含
    app.feature.enabled=true
    ,则
    MyService
    会被创建。
  • 如果
    app.feature.enabled=false
    ,或者该属性未定义,则
    MyService
    不会被加载


application.properties
中启用:


app.feature.enabled=true

3.4 @ConditionalOnBean(存在特定 Bean 时才加载)


UserService
存在时,才创建
OrderService


import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OrderServiceConfiguration {
    @Bean
    @ConditionalOnBean(UserService.class)
    public OrderService orderService() {
        return new OrderService();
    }
}

解释:

  • 如果
    UserService
    存在,则
    OrderService
    也会被创建。
  • 如果
    UserService
    不存在,则
    OrderService
    不会被加载

3.5 @ConditionalOnExpression(基于 SpEL 表达式加载)


server.port
大于 8080 时,才创建
AdvancedService


import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AdvancedConfig {
    @Bean
    @ConditionalOnExpression("#{T(java.lang.Integer).parseInt('${server.port:8080}') > 8080}")
    public AdvancedService advancedService() {
        return new AdvancedService();
    }
}

解释:

  • server.port

    8080 时,
    AdvancedService
    会被加载。

  • 其他情况下,不会创建该 Bean。


application.properties
中配置:


server.port=9090

3.6 结合 @ConditionalOnClass 实现 Starter 组件的热拔插

我们要创建一个Spring Boot Starter 组件,如果用户的
classpath
下存在
RedisTemplate
,则自动加载 Redis 相关的 Bean。

步骤:

创建 Starter 组件


@Configuration
@ConditionalOnClass(RedisTemplate.class)
public class RedisAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        return template;
    }
}

应用使用 Starter


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 如果引入 Redis 依赖
    RedisAutoConfiguration
    会自动生效。
  • 如果不引入 Redis 依赖,则
    RedisTemplate
    不会被创建。

4、总结

  • @Conditional
    及其衍生注解使 Spring Boot 具备了自动配置热拔插的能力。
  • @ConditionalOnClass
    可用于判断某个类是否存在,常用于 Starter 组件的自动装配
  • @ConditionalOnProperty
    适用于基于配置的条件加载,增强灵活性。
  • @ConditionalOnBean

    @ConditionalOnMissingBean
    适用于组件依赖管理
    合理使用这些注解,可以构建更加模块化、灵活、可配置的 Spring Boot 应用。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号