SpringBoot @Condition
@Conditional
注解
这个注解在Spring4中引入,其主要作用就是判断条件是否满足,从而决定是否初始化并向容器注册Bean
1. 定义
@Conditional
注解定义如下,其内部主要就是利用了Condition接口,来判断是否满足条件,从而决定是否需要加载Bean
1 2 3 4 5 6 | @Target ({ElementType.TYPE, ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface Conditional { Class<? extends Condition>[] value(); } |
下面是Condtion
接口的定义,这个可以说是最基础的入口了,其他的所有条件注解,归根结底,都是通过实现这个接口进行扩展的
1 2 3 4 | @FunctionalInterface public interface Condition { boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2); } |
这个接口中,有个参数比较有意思ConditionContext
,它持有不少有用的对象,可以用来获取很多系统相关的信息,来丰富条件判断,接口定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public interface ConditionContext { // 获取Bean定义 BeanDefinitionRegistry getRegistry(); // 获取Bean工程,因此就可以获取容器中的所有bean @Nullable ConfigurableListableBeanFactory getBeanFactory(); // environment 持有所有的配置信息 Environment getEnvironment(); // 资源信息 ResourceLoader getResourceLoader(); // 类加载信息 @Nullable ClassLoader getClassLoader(); } |
2、如何使用Condition和@Conditional
注解,来实现bean的条件加载,自动扫描Bean的条件加载
从使用来讲,和前面的没有什么区别,只是将注解放在具体的类上而言,同样给出一个示例,先定义一个bean
1 2 3 4 5 6 7 8 9 10 11 | @Component @Conditional (ScanDemoCondition. class ) public class ScanDemoBean { @Value ( "${conditional.demo.load}" ) private boolean load; public boolean getLoad() { return load; } } |
对应的判断条件如下,当配置文件中conditional.demo.load
为true时,才会加载这个配置,否则不实例化
1 2 3 4 5 6 | public class ScanDemoCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { return "true" .equalsIgnoreCase(conditionContext.getEnvironment().getProperty( "conditional.demo.load" )); } } |
测试类和前面差不多,稍微注意下的就是自动注入时,改一下必要条件,避免bean不存在时报错
1 2 3 4 5 6 7 8 9 10 11 12 | @Autowired (required = false ) private ScanDemoBean scanDemoBean; @GetMapping (path = "/scan" ) public String showDemo() { String type = environment.getProperty( "conditional.demo.load" ); if (scanDemoBean == null ) { return "not exists! >>>" + type; } else { return "load : " + scanDemoBean.getLoad() + " >>>" + type; } } |
3、Spring框架提供了一系列相关的注解,如下表
注解 | 说明 |
---|---|
@ConditionalOnSingleCandidate |
当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true |
@ConditionalOnMissingBean |
当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系 |
@ConditionalOnBean |
与上面相反,要求bean存在 |
@ConditionalOnMissingClass |
当给定的类名在类路径上不存在时返回true,各类型间是and的关系 |
@ConditionalOnClass |
与上面相反,要求类存在 |
@ConditionalOnCloudPlatform |
当所配置的CloudPlatform为激活时返回true |
@ConditionalOnExpression |
spel表达式执行为true |
@ConditionalOnJava |
运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配 |
@ConditionalOnProperty |
要求配置属性匹配条件 |
@ConditionalOnJndi |
给定的jndi的Location 必须存在一个.否则,返回不匹配 |
@ConditionalOnNotWebApplication |
web环境不存在时 |
@ConditionalOnWebApplication |
web环境存在时 |
@ConditionalOnResource |
要求制定的资源存在 |
@ConditionalOnExpression |
? 当表达式为true的时候,才会实例化一个Bean。 |
@ConditionalOnProperty 注解
1 2 3 4 5 6 7 8 9 | @Configuration public class WebConfig { @Bean @ConditionalOnProperty (prefix = "rest" , name = "auth-open" , havingValue = "true" , matchIfMissing = true ) public AuthFilter jwtAuthenticationTokenFilter() { return new AuthFilter(); } } |
- prefix:application.properties配置的前缀
- name:属性是从application.properties配置文件中读取属性值
- havingValue:配置读取的属性值跟havingValue做比较,如果一样则返回true,否则返回false;如果返回值为false,则该configuration不生效;为true则生效
- matchIfMissing = true:表示如果没有在application.properties设置该属性,则默认为条件符合
上面代码的意思:是否启动jwt的的配置,如果application.properties配置中没有设置就启动jwt,如果设置了true就启动,如果false就关闭。
application.properties 配置如下
1 2 | rest: auth-open: true # jwt鉴权机制是否开启( true 或者 false ) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具