SpringBoot条件装配

上一篇写到了SpringBoot的自动装配:SpringBoot自动装配 - (jianshu.com)。

springboot通过@EnableAutoConfiguration实现自动装配;可以将标注了@Configuration的配置类“一股脑的”的添加到ApplicationContext中。但是有时候我们需要自动装配更自能一些,需要在装配时满足一些条件或者调整加载顺序,这时,就需要在自动装配的基础上实现条件装配了。
目前接触到的实现条件装配有2种办法:

  1. @Profile注解
  2. @Conditional注解

1. @Profile注解

@Profile注解的目的是为了多环境开发,可以根据不同的环境动态的加载一系列组件。比如开发环境使用dev, 生产环境使用prod。
@Profile是在Spring3.1的时候引入的,一开始注解用在类上,在Spring3.2之后,注解也可用在方法上。
1. 使用示例:

/**
 * @Profile用在类上
 */
@Configuration
@EnableSwagger2
@Profile("dev")
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                // 指定扫描1个包
                .apis(RequestHandlerSelectors.basePackage("com.test.controller"))
                // 只有标记了@Api的类方法才会暴露出给swagger
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
                // 只有标记了@ApiOperation的方法才会暴露出给swagger
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .build()
                .apiInfo(apiInfo());
    }
    
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("接口文档")
                .description("Demo接口测试")
                .version("1.0")
                .termsOfServiceUrl("")
                .build();
    }
}
/**
 *  @Profile注解用在方法上
 */
@Configuration
public class DataSourceConfig {

    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        System.out.println(" dev DataSource !!");
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3308/zszxz");
        basicDataSource.setUsername("root");
        basicDataSource.setPassword("1234");
        return basicDataSource;
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        System.out.println(" prod DataSource !!");
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/zszxz");
        basicDataSource.setUsername("root");
        basicDataSource.setPassword("1234");
        return basicDataSource;
    }
}


        


        

2. 开启方式

  • SpringBoot项目
    • 方式一 在application.yml(properties)文件中添加配置:
      spring: 
        profiles: 
          active: dev
      
    • 方式二 将@Profile("dev")换成@ActiveProfiles("dev")会自动生效
  • SpringMVC项目
    在web.xml 中配置

        spring.profiles.active
        dev


        test
        org.springframework.web.servlet.DispatcherServlet
        
            spring.profiles.default
            dev
        
        1


    test
    /

2. @Conditional注解

1. @Conditional
@Conditional是Spring4.0引入的,它可以根据代码中设置的条件装载不同的bean。比如说当一个接口有两个实现类时,我们要把这个接口交给Spring管理时通常会只选择实现其中一个实现类,这个时候我们总不能使用if-else吧,所以@Conditional的注解就出现了,它配合@Configuration或者@Bean等注解来控制配置是否生效。
@Conditional注解的value通常是一个实现了Condition接口的自定义类,自定义类要重写Condition的matches方法:若返回true,则@Conditional注解的bean装配;返回false,不装配。
示例如下:

/**
 * 自定义的类,自定义了2个
 */
public class DevEvn implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String dataBase = context.getEnvironment().getProperty("dataBase");
        if ("mysql".equals(dataBase)) {
            return true;
        }
        return false;
    }
}

public class ProdEvn implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String dataBase = context.getEnvironment().getProperty("dataBase");
        if ("oracle".equals(dataBase)) {
            return true;
        }
        return false;
    }
}

/** ************************************************ */
/**
 * 有@Conditional注解的bean
 * 哪个是true就初始化哪个数据库
 */
@Configuration
public class DataBaseConfig {
    
    @Bean
    @Conditional(DevEvn.class)
    public MysqlConfig mysqlConfig() {
        return new MysqlConfig();
    }
    
    @Bean
    @Conditional(ProdEvn.class)
    public OracleConfig oracleConfig() {
        return new OracleConfig();
    }

}

2. @Conditional扩展注解

    1. @ConditionalOnBean
    @Bean
    @ConditionalOnBean(RedisConnectionFactory.class)
    public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
         RedisTemplate template = new RedisTemplate();
         template.setConnectionFactory(connectionFactory);
         template.setKeySerializer(new StringRedisSerializer());
         template.afterPropertiesSet();
         return template;
     }
    
    它的意思就是说如果你配置了redis的相关配置信息那么我就实例化RedisTemplate供你进行操作,如果你没有配置redis的相关配置那么我就不实例化。
    1. @ConditionalOnMissingBean
      这个仅仅比1多了个Missing,啥意思呢,见名知意,就是不存在某个bean的时候实例化。
    1. @ConditionalOnClass
      存在某个类时,才会实例化一个Bean
    1. @ConditionalOnMissingClass
      不存在某个类时,才会实例化一个Bean
    1. @ConditionalOnProperty(prefix = “test”, name = “testname”, havingValue = “token”, matchIfMissing = true)
      这个就稍微复杂了一点,它的意思呢就是当存在配置文件中以test为前缀的属性,属性名称为testname,然后它的值为token时才会实例化一个类。
      matchIfMissing的意思呢就是说如果所有的都不满足的话就默认实现,不管这个属性test.testname是不是等于token
      了解更多,查看org.springframework.boot.autoconfigure.condition

你可能感兴趣的:(SpringBoot条件装配)