• SpringBootSpringBoot @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

      

  • 相关阅读:
    [转载]DBA的特质第一部分:技术
    DPA/Ignite由于DNS问题导致连接不上被监控的数据库服务器
    ORACLE计算表引占用空间大小
    Reporting Services 错误案例一则
    SQL SERVER Transactional Replication中添加新表如何不初始化整个快照
    TNS-12540: TNS:internal limit restriction exceeded
    Error: 9001, Severity: 21, State: 5 The log for database 'xxxx' is not available
    ORA-01012: not logged on
    -bash: .bash_profile: command not found
    -bash: ulimit: pipe size: cannot modify limit: Invalid argument
  • 原文地址:https://www.cnblogs.com/longlyseul/p/16586102.html
Copyright © 2020-2023  润新知