Spring 注解之 @Conditional
一、@Conditional 注解简介
@Conditional 注解是 Spring4 新提供的注解,它的作用是按照一定的条件进行判断,如果满足条件给 IOC 容器注入相应的 bean
@Conditional 注解源码如下:
1 2 3 4 5 6 7 8 9 | // 该注解可以标注在 类、接口、枚举声明、方法上 @Target ({ElementType.TYPE, ElementType.METHOD}) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface Conditional { // @Conditional 注解只有一个属性值 value ,它的类型是一个 Class[] // 该数组中的元素是 Condition 的一个子类 Class<? extends Condition>[] value(); } |
我们点开 Condition 进去看一下它到底是什么
1 2 3 | public interface Condition { boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); } |
点开之后发现它是一个接口,并且有一个 matches(...) 的方法,该方法的返回值如果是 true,则判断条件成立,反之,则条件不成立.这样就很明确了,原来 @Conditional() 注解中的属性值是一个 Class 类型的数组,并且该数组中的元素就是 Condition 的实现类
类似于这样 @Conditional({A.class,B.class,C.class}) (注: 这里的类 A、B、C 是 Condition 的实现类)
二、现有需求:通过操作系统作为条件来筛选注册对象
1、编写自定义类 WindowsCondition 实现 Condition 接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获取环境信息 Environment environment = context.getEnvironment(); // 获取操作系统信息 String property = environment.getProperty( "os.name" ); // 如果操作系统信息中包含 Windows ,那么返回 true,也就是判断条件成立 if (property.contains( "Windows" )){ return true ; } return false ; } } |
2、编写自定义类 LinuxCondition 实现 Condition 接口
1 2 3 4 5 6 7 8 9 10 11 | public class LinuxCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment environment = context.getEnvironment(); String property = environment.getProperty( "os.name" ); if (property.contains( "Linux" )){ return true ; } return false ; } } |
3、配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Configuration public class SpringConfiguration { @Bean ( "bill" ) // 如果只有一个参数,那么 {} 可以省略 @Conditional ({WindowsCondition. class }) public Person person01() { return new Person( "Bill Gates" , 66 ); } @Bean ( "linus" ) @Conditional (LinuxCondition. class ) public Person person02() { return new Person( "Linus Torvalds" , 44 ); } } |
4、测试类
1 2 3 4 5 6 7 8 9 | public class SpringTest { public static void main(String[] args) { AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfiguration. class ); String[] beanDefinitionNames = ioc.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { System.out.println(beanDefinitionName); } } } |
5、测试结果
1 2 3 4 5 6 7 8 9 10 | org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory // 配置类 springConfiguration // 由于本机操作系统是 Windows8.1 ,可以看到 linus 没有注册进 Spring 容器 bill |
6、更换一下虚拟机参数,切换为 Linux 环境,看一下测试结果
Run---->Edit Configurations----> -Dos.name=Linux
再次启动项目测试结果如下:
1 2 3 4 5 6 7 8 9 | org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory springConfiguration // linus 这个 bean 就注入了 Spring 容器中,而 bill 就没有注入进来 linus |
三、@Conditional 注解标注位置
通过上面的例子我们可以看到,我们都是将 @Conditional 注解标注在了方法上面,但是我们查看源码的时候可以知道,该注解不但可以标注在方法上,还可以标注在类、接口、枚举声明上面,那么标注在其它地方的时候代表的意思又是什么呢?
1、标注在方法上:由于一个方法只能注入一个 bean 实例,所以 @Conditional 注解标注在方法上只能控制一个 bean 实例是否注入
2、标注在类上:一个类上可以注入很多的 bean 实例,所以 @Conditional 注解标注在类上就能控制一批 bean 实例是否注入
自己测试了一下,结论如下:
1 2 3 4 5 | @Conditional ({A. class ,B. class ,C. class ,D. class ...}) @Configuration public class SpringConfiguration { ...... } |
A、B、C、D、....都是 Condition 接口的实现类,如果它们中有一个类的 matches(...) 方法返回值为 false,那么该配置类所有的 bean 都不会注入到 spring 容器中,只有所有类的 matches(...) 方法返回值为 true,那么该配置类才生效
个人猜测,标注在类上的 @Conditional 注解的判断条件为 false,那么整个类所有执行的行为将失效.(我们这里是注入容器的行为,这个以后看了源码再来验证.)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?