美文网首页
Spring Boot选择性装配 Condition

Spring Boot选择性装配 Condition

作者: 蓉漂里的小白 | 来源:发表于2021-02-03 15:30 被阅读0次

    我们经常会有根据条件来加载不同的接口。 Spring Boot 能根据不同的实际情况启用不同的配置。这就是@Conditional注解在发挥作用。该注解指定了在什么条件下创建 Bean 并进行装配。

    一: @conditional

    Spring Boot 包含多个 @Conditional 注释,可以在@Configuration注解的类和@Bean注解方法中使用。@Conditional类型的注解,可以注解在类上,可以注解在Bean方法上

    1.1 Class Conditions

    @ConditionalOnClass和@ConditionalOnMissingClass 两个用在类上的注解:
    @ConditionalOnClass:判断指定的类在classpath下是否存在,如果存在则实例化该注解修饰的类,否则不实例化该注解所修饰的类
    ConditionalOnMissingClass: 判断指定的类classpath下是否存在,如果不存在则实例化该注解修饰的类,否则不实例化该注解所修饰的类

    @Configuration
    @ConditionalOnClass({DruidDataSource.class})
    public class DruidDataSourceAutoConfigure {
    }
    

    当classpath中存在DruidDataSource这个类的时候,spring才会实例化DruidDataSourceAutoConfigure这个类

    1.2 Bean Conditions

    @ConditionalOnBean和@ConditionalOnMissingBean 两个用在 Bean 方法上的注解:
    @ConditionalOnBean:判断指定的Bean在ioc是否存在,如果存在则实例化该注解修饰的Bean,否则不实例化该注解所修饰的Bean
    ConditionalOnMissingBean: 判断指定的Bean在ioc中是否存在,如果不存在则实例化该注解修饰的Bean,否则不实例化该注解所修饰的Bean

    @Configuration
    public class ConditionBeanTest {
    
        @Bean
        public Boss createBean(){
            return new Boss();
        }
    
        @Bean
        @ConditionalOnBean(Boss.class)
        public BossBackup createBackupBean(){
            return new BossBackup();
        }
    }
    

    只有当Boss这个Bean被创建后,spring才会实例化BossBackup这个Bean

    1.3 Property Conditions

    @ConditionalOnProperty注解可以基于Spring Environment属性包含的配置进判断,再决定自动配置的执行,使用 prefix 和 name 属性指定检查application.properties/application.yml配置文件的属性值。

    @Configuration
    public class ConditionBeanTest {
    
        @Bean
        @ConditionalOnProperty(prefix="app",name = "test", havingValue = "true")
        public Boss createBean1(){
            return new Boss();
        }
    }
    

    只有配置文件中设置了app.test=true时候才会创建Boss这个类

    1.4 Resource Conditions

    @ConditionalOnResource当指定的资源文件出现在classpath特时执行自动配置

    @Configuration
    public class ConditionBeanTest {
    
        @Bean
        @ConditionalOnResource(resources="classpath:boss.ini")
        public Boss createBean2(){
            return new Boss();
        }
    }
    

    当在classpath下发现了boss.ini文件时候,实例化Boss

    1.5 Web Application Conditions

    @ConditionalOnWebApplication和@ConditionalOnNotWebApplication注解用于判断应用程序是否为Web应用程序。

    @Configuration
    public class ConditionBeanTest {
    
        @Bean
        @ConditionalOnWebApplication
        public BossBackup createBossBackup(){
            return new BossBackup();
        }
    }
    

    当我们的应用程序是Web Application时候,创建BossBackup这个类

    1.6 SpEL Expression Conditions

    @ConditionalOnExpression注解根据SpEL表达式的结果来执行配置。如果满足表达式的结果执行配置,否则不执行配置

    @Configuration
    public class ConditionBeanTest {
    
        @Bean
        @ConditionalOnExpression("#{'true'.equals(environment.getProperty('app.isEnableBackup'))}")
        public BossBackup createBossBackup1(){
            return new BossBackup();
        }
    
     }
    

    上面的配置就是代表党配置文件中设置了app.isEnableBackup 属性并设置为true时,才开始实例化BossBackup这个类,也可以这样写

        @Bean
        @ConditionalOnExpression("#{!'false'.equals(environment.getProperty('app.isEnableBackup'))}")
        public BossBackup createBossBackup2(){
            return new BossBackup();
        }
    

    二:自定义 Condition

    如果上面几种都不能满足你的需要。那么我们可以通过实现Condition接口,并重写其matches方法来构造判断条件。
    比如我们需要依赖配置文件中的条件决定是否开启Spring 自带的一些Enable注解(@EnableScheduling,@EnableAsync)然后通过condition接口来实现。@EnableScheduling,@EnableAsync的选择性启动。

    1:定义ShouldEnableSchedule 类并实现condition接口
    public class ShouldEnableSchedule implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            String v = conditionContext.getEnvironment().getProperty("app.isEnableSchedule");
            return v.equals("enable");
        }
    }
    
    2:创建一个条件配置configuration类,当满足matches条件创建,并在配置类上添加@EnableScheduling, @EnableAsync注解
    @Configuration
    @Conditional(ShouldEnableSchedule.class)
    @EnableScheduling
    @EnableAsync
    public class EnableScheduleConfig {
    }
    
    3:创建一个任务类
    @Component
    public class DeviceHealthTask {
    
        @Autowired
        private ActuatorDetail actuatorDetail;
    
        @Scheduled(cron = "*/1 * * * * ?")
        public void getHealthStatusInfo(){
            this.actuatorDetail.getHealthDetailByJmx();
            this.actuatorDetail.startMyTreadTask();
            for (int i=0;i < 20;i++){
                System.out.println("DDDDDD");
            }
        }
    }
    

    同时把actuatorDetail.startMyTreadTask()修饰为异步任务

    @Service
    public class ActuatorDetail {
    
        @Async
        public void startMyTreadTask() {
            for (int j=0;j< 20;j++) {
                System.out.println("this is my async task");
            }
        }
    
    public void  getHealthDetailByJmx() {
           System.out.println("#######@@@@@@@@@@$$$$$$$$$4");
    }
    }
    
    4:运行spring 程序
    image.png

    从执行结果可以看到,定时任务启动了,并且方法startMyTreadTask是异步执行的。

    相关文章

      网友评论

          本文标题:Spring Boot选择性装配 Condition

          本文链接:https://www.haomeiwen.com/subject/ftaptltx.html