0
点赞
收藏
分享

微信扫一扫

SpringBoot2.x常用的ConditionalXX注解

1. @ConditionalOnMissingBean

案例:
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}

2. @ConditionalOnProperty

注意点:

  1. @Bean的方法名字不能相同,否则@ConditionalOnProperty配置失效;
  2. 配置中使用枚举类型时,@ConditionalOnProperty中的值是小写;
  3. 当配置文件中没有对应配置项时,可以使用@ConditionalOnProperty的matchIfMissing = true表示,未配置时默认初始化某bean。

场景:实现了Cache,可以根据配置文件的值灵活的切换缓存。

@Getter
public enum CacheEnum {
    MEMORY, REDIS;
}

配置文件:

@Data
@ConfigurationProperties("base")
public class BaseConfigProperties {
    /**
     * 缓存类型,默认内存级别的缓存
     * 默认支持本地缓存和Redis分布式缓存
     */
    private CacheEnum cache;

}
@Slf4j
@Configuration
@EnableConfigurationProperties(value = BaseConfigProperties.class)
public class OSAutoConfiguration {


    @Configuration
    @ConditionalOnClass(org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class)
    @ConditionalOnProperty(name = "base.cache", havingValue = "redis")
    protected static class RedisCacheManagerConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public CacheManager redisCacheManager(StringRedisTemplate stringRedisTemplate) {
            log.info("启用redis缓存...");
            return new CacheManager() {
                @Override
                public void put(String key, String value, long time) {
                    stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
                }

                @Override
                public String get(String key) {
                    return stringRedisTemplate.opsForValue().get(key);
                }

                @Override
                public void remove(String key) {
                    stringRedisTemplate.delete(key);
                }
            };
        }
    }

    /**
     * 内存级别的缓存
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "base.cache", havingValue = "memory", matchIfMissing = true)
    public CacheManager localCacheManager() {
        log.info("启用memory缓存");
        return new MemoryCacheManager();
    }

}

如上述代码:当配置文件存在base.cache: redis时,则初始化Redis缓存,若不配置,则初始化memory缓存。

3. @ConditionalOnClass

注意该类注解需要用在类上,即不允许JVM加载该类。若用在方法上,且项目没有对应class,则项目启动时出现异常。

案例:如2中所示,可以构造静态内部类实现。这也是为什么源码的Config中存在大量静态内部类声明bean的原因。

项目实战:

    /**
     * 原生Redis的缓存
     */
    @Configuration
    @ConditionalOnClass(org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class)
    @ConditionalOnProperty(name = "seal.os.cache", havingValue = "redis")
    protected static class RedisCacheManagerConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public CacheManager redisCacheManager(StringRedisTemplate stringRedisTemplate) {
            return new RedisCacheManager(stringRedisTemplate);
        }
    }

4. @ConditionalOnBean

5. @EnableConfigurationProperties

案例:如2中所示。

6. @Import

案例:
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

}

上述注解:@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })会按照顺序导入LettuceConnectionConfiguration和JedisConnectionConfiguration配置。

LettuceConnectionConfiguration的优先级高于JedisConnectionConfiguration。
最终是由了LettuceConnectionConfiguration的RedisConnectionFactory。

举报

相关推荐

0 条评论