10、底层注解-@Conditional条件装配

10、底层注解-@Conditional条件装配

`@Conditional`是Spring框架中用于条件装配的核心注解,它允许根据特定条件决定是否将某个组件或配置加载到Spring容器中。通过在类或方法上使用`@Conditional`,可以实现灵活的自动化配置,适应不同的环境和需求。

基本用法

`@Conditional`注解需要指定一个或多个实现了`Condition`接口的条件类。`Condition`接口的`matches`方法用于编写条件判断逻辑,返回`true`表示条件满足,组件将被加载;返回`false`则表示条件不满足,组件将被忽略。

```java

public class MyCondition implements Condition {

@Override

public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

// 编写条件判断逻辑,例如:

return context.getEnvironment().getProperty("my.property") != null;

}

}

@Configuration

public class AppConfig {

@Bean

@Conditional(MyCondition.class)

public MyComponent myComponent() {

return new MyComponent();

}

}

```

在上述例子中,只有当`my.property`属性在配置文件中存在时,`MyComponent`才会被创建并注册到容器中。

常用内置条件注解

Spring Boot提供了一系列内置的条件注解,简化了常见的条件判断:

`@ConditionalOnProperty`

根据配置属性的值决定是否加载组件。

```java

@Bean

@ConditionalOnProperty(name = "my.feature.enabled", havingValue = "true")

public MyFeatureComponent myFeatureComponent() {

return new MyFeatureComponent();

}

```

只有当`my.feature.enabled`属性值为`true`时,`MyFeatureComponent`才会被创建。

`@ConditionalOnClass`

当类路径中存在指定的类时,条件满足。

```java

@Bean

@ConditionalOnClass(name = "com.example.SomeClass")

public MyComponent myComponent() {

return new MyComponent();

}

```

如果类路径中存在`com.example.SomeClass`,则`MyComponent`会被加载。

`@ConditionalOnMissingClass`

与`@ConditionalOnClass`相反,当类路径中**不存在**指定的类时,条件满足。

`@ConditionalOnBean`

当容器中已经存在指定类型的Bean时,条件满足。

```java

@Bean

@ConditionalOnBean(MyDependency.class)

public MyComponent myComponent() {

return new MyComponent();

}

```

如果容器中已有`MyDependency`类型的Bean,`MyComponent`才会被创建。

`@ConditionalOnMissingBean`

与`@ConditionalOnBean`相反,当容器中**不存在**指定类型的Bean时,条件满足。

`@ConditionalOnExpression`

根据SpEL表达式的结果决定是否加载组件。

```java

@Bean

@ConditionalOnExpression("${my.expression} == true")

public MyComponent myComponent() {

return new MyComponent();

}

```

当SpEL表达式`my.expression`的值为`true`时,`MyComponent`会被创建。

自定义条件注解

除了使用内置条件注解,还可以创建自定义条件注解,增强代码的可读性和复用性。

```java

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Conditional(MyCondition.class)

public @interface MyCustomCondition {

// 可添加自定义属性

}

@Configuration

public class AppConfig {

@Bean

@MyCustomCondition

public MyComponent myComponent() {

return new MyComponent();

}

}

```

注意事项

  • **避免循环依赖**:在条件判断中应避免引用尚未初始化的组件,防止循环依赖。

  • **性能考虑**:条件判断可能涉及较复杂的逻辑,应确保性能合理,避免影响应用启动速度。

  • **缓存结果**:对于耗时的条件判断,可以利用`Condition`接口中的`getConfigurationPhase`方法,在配置阶段缓存结果,提升性能。

应用场景

  • **多环境配置**:根据不同环境(开发、测试、生产)加载相应的组件。

  • **特性开关**:根据配置决定是否启用某些功能模块。

  • **依赖检测**:根据类路径中是否存在特定依赖,选择性地加载组件。

  • **动态配置**:根据运行时条件动态调整组件的加载。

通过`@Conditional`注解,可以实现灵活的条件装配,提高Spring应用的配置灵活性和可维护性,适应各种复杂的业务场景。

相关推荐
码农小卡拉几秒前
数据库:主键 VS 唯一索引 区别详解
java·数据库·sql
e***985720 分钟前
Java性能优化实战:从原理到案例
java·开发语言·性能优化
焦糖玛奇朵婷41 分钟前
盲盒小程序:开发视角下的功能与体验
java·大数据·jvm·算法·小程序
济6171 小时前
linux 系统移植(第六期)--Uboot移植(5)--bootcmd 和 bootargs 环境变量-- Ubuntu20.04
java·前端·javascript
温暖小土1 小时前
深度解析 Spring Boot 自动配置:从原理到实践
java·springboot
Marktowin1 小时前
Mybatis-Plus更新操作时的一个坑
java·后端
R-sz1 小时前
如何将json行政区划导入数据库,中国行政区域数据(省市区县镇乡村五级联动)
java·数据库·json
定仙游4531 小时前
Java StringBuilder 超详细讲解
java
haiyu柠檬1 小时前
IDEA和VSCode中好用的插件推荐
java·vscode·intellij-idea
赵文宇2 小时前
CNCF Dragonfly 毕业啦!基于P2P的镜像和文件分发系统快速入门,在线体验
后端