美文网首页
RedisConfig配置注入不进项目中

RedisConfig配置注入不进项目中

作者: 墨色尘埃 | 来源:发表于2019-08-28 14:30 被阅读0次
    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<String, Object> redisTemplate() {
            RedisTemplate<String, Object> 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<String, Object> redisSerizlizerObj1() {
    //        RedisTemplate<String, Object> 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<String, Object> redisTemplate() {
            RedisTemplate<String, Object> 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;注入,启动项目报错了。

    image.png
    报错信息如下:
    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注解(该注解不能修饰属性)

    正确的

    image.png

    错误的

    image.png
    1. 配置类中注入的该类的方法名作为属性名
      该方法名为 redisTemplate(),RedisTemplate类在项目中的 组件ID 与该方法名同名,在control中 private RedisTemplate redisTemplate; 也使用改名作为属性,经过测试也是可以的。
      测试方法是:System.out.println(redisTemplate.getValueSerializer()); 查看打印出来的序列化方式是什么,默认序列化方式是JdkSerializationRedisSerializer
        @Bean
        public RedisTemplate<String, Object> redisTemplate() {
            RedisTemplate<String, Object> 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,下面我们简单来看一下。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
        <bean class="com.jimisun.spring.example.User" id="user">
            <constructor-arg ref="myArticle"/>
        </bean>
    
        <bean class="com.jimisun.spring.example.MyArticle" id="myArticle"></bean>
    
    </beans>
    

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

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

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

    相关文章

      网友评论

          本文标题:RedisConfig配置注入不进项目中

          本文链接:https://www.haomeiwen.com/subject/wyppectx.html