redisConfig配置重復問題


背景:引用的jar包中與項目中同時存在redisConfig情況

最近同事在引用我的jar包的時候,出現了如下的錯誤:

Annotation-specified bean name 'redisConfig' for bean class [com.xxx.RedisConfig] conflicts with existing, non-compatible bean definition of same name and class [com.xxx1.RedisConfig]

經過交流后得知,因為我這邊配置了RedisConfig以方便操作redisTemplate。(之前我未考慮到我提供的RedisConfig是簡易配置,用戶可能需要擴展的情況)

既然遇到了沖突問題,那么就解決吧!

spring提供了一個注解:@ConditionalOnMissingBean,這個注解的作用是當上下文(可以通過search屬性指定上下文范圍)中存在相應的bean的時候,不采用當前名稱的bean

官方api

@Target(value={TYPE,METHOD})
@Retention(value=RUNTIME)
@Documented
@Conditional(value=org.springframework.boot.autoconfigure.condition.OnBeanCondition.class)
public @interface ConditionalOnMissingBean
Conditional that only matches when no beans of the specified classes and/or with the specified names are already contained in the BeanFactory.
When placed on a @Bean method, the bean class defaults to the return type of the factory method:

 @Configuration
 public class MyAutoConfiguration {

     @ConditionalOnMissingBean
     @Bean
     public MyService myService() {
         ...
     }

 }
In the sample above the condition will match if no bean of type MyService is already contained in the BeanFactory.

The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

解決問題,步驟如下

  1. 首先我修改了自己RedisConfig類的名稱,加上我項目的前綴,例:VsRedisConfig
  2. 因為配置自定義RedisConfig最關鍵的兩個方法是redisTemplate和connectionFactory:
    @Bean(name = "rt")
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(connectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return template;
    }

    @Bean
    public JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(Integer.parseInt(port));
        factory.setPassword(password);
        factory.setTimeout(5000);
        return factory;
    }

所以,在兩個方法上分別加上:

@ConditionalOnMissingBean(value = RedisTemplate.class)  // search策略默認為All,所以可以不寫上去
@ConditionalOnMissingBean(value = JedisConnectionFactory.class)

這樣,用戶在引用我的jar包的時候,就不會訪問我的RedisConfig了(因為Springboot在加載類的順序上,是當前項目優先,其次是jar包中的),而是會去訪問使用方的RedisConfig


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM