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
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类
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
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
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
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
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
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
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。
@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

浙公网安备 33010602011771号