SpringBoot-----SpringBoot @Conditional注解自动配置报告
一、@Conditional简介
@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册Bean。SpringBoot是根据配置文件的内容决定是否创建Bean,以及如何创建bean到Spring容器中,而Spring Boot自动化配置的核心控制,就是@Conditional注解。二、@ConditionalOnXX注解
@ConditionalOnXX注解被定义在org.springframework.boot.autoconfigure包下面的condition文件夹下,它是一种条件装配,满足Conditional指定的条件,则进行组件注入
在ideal中使用ctrl+H可以看到@Conditional的根注解和派生注解,这个根注解下派生了很多派生注解
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
@ConditionalOnJava | 系统的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
@ConditionalOnResource | 路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
举例说明:
一、加载2个Bean
1、新建一个BeanConfig.java,利用@Configuration+@Bean加载2个Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package com.zk.autoconfigdemo; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class BeanConfig { /* *如果windowsCondition的实现方法返回true,则注入这个bean */ @Bean public Person person1(){ return new Person( "BillGates" , 62 ); } /** * 如果LinuxCondition的实现方法返回true,则注入这个Bean */ @Bean public Person person2(){ return new Person( "Linus" , 50 ); } } |
2、新建一个Person.java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | package com.zk.autoconfigdemo; public class Person { private String name; private Integer age; public Person(String name, int age) { this .name=name; this .age=age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this .age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\ '' + ", age=" + age + '}' ; } } |
3、测试是否都加载到Spring容器中
AutoconfigdemoApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.zk.autoconfigdemo; import org.apache.catalina.core.ApplicationContext; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import java.util.Map; @SpringBootApplication public class AutoconfigdemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run=SpringApplication.run(AutoconfigdemoApplication. class ,args); Map<String,Person> personMap=run.getBeansOfType(Person. class ); System.out.println(personMap); } } |
运行结果如下:
三、利用@Conditional根据条件加载Bean
1、创建条件判断的类
如果是Windows系统则加载Bean
WindowsCondition.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package com.zk.autoconfigdemo; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; public class WindowsCondition implements Condition { /** * * @param context:判断条件能使用的上下文环境 * @param metadata:注解所在位置的注释信息 * @return */ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //获取ioc使用的BeanFactory ConfigurableListableBeanFactory beanFactory=context.getBeanFactory(); //获取类加载器 ClassLoader classLoader=context.getClassLoader(); //获取当前环境信息 Environment environment=context.getEnvironment(); //获取bean定义的注册类 BeanDefinitionRegistry registry=context.getRegistry(); //获取当前系统名 String property=environment.getProperty( "os.name" ); //包含windows说明是windows系统,返回true if (property.contains( "Windows" )){ return true ; } return false ; } } |
如果是Linux系统则加载Bean
LinuxCondition.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package com.zk.autoconfigdemo; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; 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 ; } } |
2、将@Conditional放在方法上
BeanConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.zk.autoconfigdemo; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class BeanConfig { /* *如果windowsCondition的实现方法返回true,则注入这个bean */ @Bean @Conditional (WindowsCondition. class ) public Person person1(){ return new Person( "BillGates" , 62 ); } /** * 如果LinuxCondition的实现方法返回true,则注入这个Bean */ @Bean @Conditional (LinuxCondition. class ) public Person person2(){ return new Person( "Linus" , 50 ); } } |
运行AutoconfigdemoApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.zk.autoconfigdemo; import org.apache.catalina.core.ApplicationContext; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import java.util.Map; @SpringBootApplication public class AutoconfigdemoApplication { public static void main(String[] args) { ConfigurableApplicationContext run=SpringApplication.run(AutoconfigdemoApplication. class ,args); Map<String,Person> personMap=run.getBeansOfType(Person. class ); System.out.println(personMap); } } |
得到的结果如下:
因为当前系统为windows,所以只返回一个值。
3、将@Conditional注解放在类上
BeanConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.zk.autoconfigdemo; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration @Conditional (WindowsCondition. class ) public class BeanConfig { /* *如果windowsCondition的实现方法返回true,则注入这个bean */ @Bean public Person person1(){ return new Person( "BillGates" , 62 ); } /** * 如果LinuxCondition的实现方法返回true,则注入这个Bean */ @Bean public Person person2(){ return new Person( "Linus" , 50 ); } } |
因为所运行的设备为windows10,所以@Conditional(WindowsCondition.class) 生效可用,运行结果如下:
4、@Conditional传多个条件,是且关系
@Conditional接受一个Class数组,可以传多个条件,当所有条件都是true时,才生效。
可想项目的代码是不会加载Person对象的,因为
WindowsCondition.class返回true,LinuxCondition.class返回false,所以MyBeanConfig整个类失效,不能加载它下面的Bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Configuration @Conditional ({WindowsCondition. class , LinuxCondition. class }) public class MyBeanConfig { @Bean //@Conditional(WindowsCondition.class) public Person person1(){ return new Person( "Bill Gates" , 66 ); } @Bean //@Conditional(LinuxCondition.class) public Person person2(){ return new Person( "Linus" , 50 ); } } |
自动配置类必须在一定的条件下才能生效。
三、debug=true
我们可以在配置文件中启动debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效。
参考文档:https://blog.csdn.net/winterking3/article/details/114819184
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)