RedisConfig配置注入不进项目中

RedisConfig配置注入不进项目中_第1张图片
image.png
@Configuration
public class RedisConfig {
    @Bean
    public CachingConfigurerSupport keyGenerator() {
        return new MyCachingConfigurerSupport();
    }

    public class MyCachingConfigurerSupport extends CachingConfigurerSupport {
        @Override
        public KeyGenerator keyGenerator() {
            return new KeyGenerator() {
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(target.getClass().getName());
                    sb.append(method.getName());
                    for (Object obj : params) {
                        sb.append(obj.toString());
                    }
                    return sb.toString();
                }
            };
        }
    }

    //缓存管理器
    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间
        rcm.setDefaultExpiration(300);//秒
        return rcm;
    }

    /**
     * 存入对象tostring后的信息
     */
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式,需要配置一下StringSerializer,不然key会乱码 /XX/XX
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }


//    /**
//     * 存入对象序列化信息
//     *
//     * @return
//     */
//    @Bean
//    public RedisTemplate redisSerizlizerObj1() {
//        RedisTemplate redisTemplate = new RedisTemplate<>();
//        redisTemplate.setConnectionFactory(jedisConnectionFactory());
//        // key采用String的序列化方式
//        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        // value序列化方式采用jackson
//        redisTemplate.setValueSerializer(new RedisObjectSerializer());
//
//        // hash的key也采用String的序列化方式
//        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
//        // hash的value序列化方式采用jackson
//        redisTemplate.setHashValueSerializer(new RedisObjectSerializer());
//        return redisTemplate;
//    }

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setPassword("jihy");
        return jedisConnectionFactory;
    }
}

@Configuration注解未生效,@Bean无法注入。
这个配置类和别的配置类没有任何区别,@Configuration和@Bean注解都有,无论怎么启动就是注入不进项目中,后来试着将该配置类先移动到其他(可以注入其他配置类的)包中,启动服务发现可以被扫描到。然后再将该配置类拖回原来的包中再重新启动服务,发现也可以了。没想明白为什么,这里记录一下。

看这个方法

修改了RedisTemplate的默认序列化方式,默认序列化方式是JdkSerializationRedisSerializer,这里改成Jackson2JsonRedisSerializer序列化方式,可以序列化object对象为json字符串。

    /**
     * 存入对象tostring后的信息
     */
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式,需要配置一下StringSerializer,不然key会乱码 /XX/XX
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

修改完序列化方式之后,control中还需要使用该类RedisTemplate,通过@Autowired private RedisTemplate template;注入,启动项目报错了。

RedisConfig配置注入不进项目中_第2张图片
image.png

报错信息如下:
RedisConfig配置注入不进项目中_第3张图片
image.png

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
意思是两个bean不知道注入哪一个,需要给其中一个更高的优先级。那为什么会出现这种情况呢?

首先需要了解Spring装配bean组件的三种方式:

  1. 隐式的Bean发现机制和自动装配
  2. 在Java中进行装配
  3. 在XML中进行装配
    值得一提的是,我们在项目中应该优先实用隐式的Bean发现机制和自动装配,其次使用在Java中进行装配,最后再使用在XML中进行装配。

对于本项目

使用了 @Configuration+@Bean的基于Java的Bean装配 RedisTemplate类,
然后在control类中又通过@Autowired 隐式的Bean发现机制和自动装配 RedisTemplate类
两种方式导致框架不知道使用哪一个

所以有两种解决方法:

  1. 使用@Primary注解(该注解不能修饰属性)

正确的

RedisConfig配置注入不进项目中_第4张图片
image.png

错误的

image.png
  1. 配置类中注入的该类的方法名作为属性名
    该方法名为 redisTemplate(),RedisTemplate类在项目中的 组件ID 与该方法名同名,在control中 private RedisTemplate redisTemplate; 也使用改名作为属性,经过测试也是可以的。
    测试方法是:System.out.println(redisTemplate.getValueSerializer()); 查看打印出来的序列化方式是什么,默认序列化方式是JdkSerializationRedisSerializer
    @Bean
    public RedisTemplate redisTemplate() {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式,需要配置一下StringSerializer,不然key会乱码 /XX/XX
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

Spring容器装配Bean的三种方式

隐式的Bean发现机制和自动装配

Spring从两个角度来实现自动化装配;组件扫描(Spring自动发现应用中上下文所需要的创建的Bean),自动装配(Spring自动满足Bean之间的依赖)

使用@Component将普通Java类配置成SpringBean
使用@Autowired(自动装配)使Spring满足Bean的依赖

@Component
public class User {

    @Autowired
    private Article article;

    public void action() {
        article.action();
    }
}
基于Java的Bean装配

使用 @Bean 注解将方法返回的实例对象添加到上下文中
在@Bean返回的实例对象中可以通过构造器注入传入相关依赖

@Configuration
@ComponentScan("com.jimisun")
public class WebConfig {

    @Bean
    public User user() {
        return new User(myArticle());
    }

    @Bean
    public MyArticle myArticle() {
        return new MyArticle();
    }

}
基于XML的Bean装配

对于在XML中进行配置可能使我们经常使用的,在以前的Spring版本中几乎我们都是使用XML进行配置Spring,下面我们简单来看一下。




    
        
    

    


注意:在实际应用中如何不想被海量的标签埋没前,你应当优先使用隐式的Bean发现机制和自动装配和在Java中进行装配,最后再选择使用在XML中配置。

最后值得一提的是在实际项目中我们通常都会选择组合使用

隐式的Bean发现机制和Java中进行装配进行组合
隐式的Bean发现机制和XML配置进行组合

你可能感兴趣的:(RedisConfig配置注入不进项目中)