• @Conditional & @Profile SpringBoot中自动化配置条件注解。


    定义

    Spring4 中提供了更加通用的条件注解,让我们可以在满足不同条件时创建不同的 Bean,这种配置方式在 Spring Boot 中得到了广泛的使用,大量的自动化配置都是通过条件注解来实现的。条件注解作用是让Spring根据不同条件生产不同的Bean。

    注意:这里不同的Bean应该是指同一类不同对象(个人理解)。

    实践

    Condition注解

    首先建立一个普通Maven项目,引入Spring-context相关依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
    </dependencies>
    

    再定义定义一个World接口,同时定义俩个实现类China和American:

    // World接口
    public interface World {
        String showName();
    }
    
    //China实现类
    public class China implements World{
        public String showName(){
            return "China";
        }
    }
    
    //American实现类
    public class American implements World{
        public String showName(){
            return "American";
        }
    }
    

    这里也可以直接定义一个类写上完整的构造方法,后面在生产Bean中通过不同构造参数产生不同实例进行模拟。

    分别为China和American配置条件类:

    public class ChinaCondition implements Condition {
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
            return context.getEnvironment().getProperty("country").equals("中国");
        }
    }
    
    public class AmericanCondition implements Condition {
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
            return context.getEnvironment().getProperty("country").equals("美国");
        }
    }
    

    注意:此处Condition接口是来自:

    import org.springframework.context.annotation.Condition;
    

    接下来还需要个配置类:

    @Configuration
    public class ConditionConfig {
        @Bean("country")
        @Conditional(ChinaCondition.class)
        World china(){
            return new China();
        }
    
        @Bean("country")
        @Conditional(AmericanCondition.class)
        World american(){
            return new American();
        }
    }
    
    • @Bean("country")等同于@Bean(name = "country"),表示对产生的Bean进行命名(个人理解)

    • @Condition就是我们此次所讲的关键,这个注解中的必须继承Condition接口,如果该类的matches()返回true则生产Bean,否则忽视后面的函数。

    最后,我们需要一个主函数:

    public class ConditionMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext actx = new AnnotationConfigApplicationContext();
            actx.getEnvironment().getSystemProperties().put("country", "中国");
            actx.register(ConditionConfig.class);
            actx.refresh();
    
            World world = (World) actx.getBean("country");
            System.out.println(world.showName());
        }
    }
    

    首先我们创建一个AnnotationConfigApplicationContext的实例化对象 actx,对actx中注入相关参数,put()接受的是一个键值对,再注册配置类ConditionConfig,最后刷新容器。

    容器刷新时Spring才会开始调用ConditionConfig对之前信息进行处理,然后根据插入的键值对产生相应的Bean。最后用一个将名为country的Bean赋值给World实例。

    对于AnnotationConfigApplicationContext可以理解为:

    AnnotationConfigApplicationContext可以实现基于Java的配置类加载Spring的应用上下文。从而代替Xml文件。

    @Profile

    使用注解@Profile可以避免自己在matches()中写业务逻辑的过程,更简单的实现以上过程。

    对于World接口,China、American实现类我们不做改变,现在已不再需要ChinaCondition类和AmericanCondition类,我们直接构建ProfileCondition类:

    @Configuration
    public class ProfileConfig {
        @Bean("country")
        @Profile("中国")
        World china(){
            return new China();
        }
    
        @Bean("country")
        @Profile("美国")
        World american(){
            return new American();
        }
    }
    

    再配置一个运行主函数ProfileMain加载对应Bean:

    public class ProfileMain {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext actx = new AnnotationConfigApplicationContext();
            actx.getEnvironment().setActiveProfiles("美国");
            actx.register(ProfileConfig.class);
            actx.refresh();
    
            World world = (World) actx.getBean("country");
            System.out.println(world.showName());
        }
    }
    

    效果和上面是一样的。

    @Profile内部使用的也是@Conditional,只是他将matches函数中需要写的业务逻辑封装,我们直接使用就可以了。

    总结

    条件注解在 Spring 中的使用,它的一个核心思想就是当满足某种条件的时候,某个 Bean 才会生效,而正是这一特性,支撑起了 Spring Boot 的自动化配置。

    参考资料:SpringBoot教程@江南一点雨

  • 相关阅读:
    Android开发之日历控件实现
    聚集索引和非聚集索引(整理)
    Android调用WebService(转)
    Android Design
    Android应用的自动升级、更新模块的实现
    Row_Number() OVER 的用法
    WITH AS短语,也叫做子查询部分(subquery factoring)
    创建安卓项目图解
    Android权限设置android.permission
    类型初始值设定项引发异常
  • 原文地址:https://www.cnblogs.com/AkimotoAkira/p/13573557.html
Copyright © 2020-2023  润新知