spring+dubbo集成redis错误解决

异常堆栈信息 原文链接

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisServiceImpl': Unsatisfied dependency expressed through field 'stringRedisTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.StringRedisTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1348)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
	at com.yyl.BlogServiceStart.main(BlogServiceStart.java:18)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.core.StringRedisTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584)
	... 14 more
[INFO ] 2019-09-17 10:10:34,406(6072) --> [DubboShutdownHook] com.alibaba.dubbo.config.AbstractConfig$1.run(AbstractConfig.java:81): [INFO ] 2019-09-17 10:10:34,408(6074) --> [DubboShutdownHook] com.alibaba.dubbo.registry.support.AbstractRegistryFactory.destroyAll(AbstractRegistryFactory.java:64): Disconnected from the target VM, address: '127.0.0.1:65110', transport: 'socket'

异常原因分析

@Service
 public class RedisServiceImpl implements RedisService {
		@Autowired
		private StringRedisTemplate stringRedisTemplate;
		@Override
		public void set(String key, String value) {
				stringRedisTemplate.opsForValue().set(key, value);
		}

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

		@Override
		public boolean expire(String key, long expire) {
			return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
		}

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

		@Override
		public Long increment(String key, long delta) {
			return stringRedisTemplate.opsForValue().increment(key,delta);   
        }
 }

由代码和异常堆栈信息可知我想在service中注入一个stringRedisTemplate但是这个bean并没有被spring管理到。所以我就看源码查spring什么情况下会加载这个bean。经查源码发现:

@Configuration
@EnableDubbo(scanBasePackages = "com.yyl.service")
@ComponentScan("com.yyl")
@MapperScan("com.yyl.mapper")
@PropertySource(value = {"classpath:/dubbo.properties"})
//我的错误的原因就是没有在我的配置文件中开启自动配置和开启缓存。也就是下面的注解
 //@EnableAutoConfiguration
//@EnableCaching

剖析

  • spring会扫描@EnableAutoConfiguration这个注解。会加载spring-boot-autoconfigure这个jar包

  • 当扫描到@EnableCaching这个注解会通过spi加载spring.factories 的org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\这个类

  • RedisAutoConfiguration会加载application.properties
    spring.redis.database=0
    #redis服务器名称
    spring.redis.host=127.0.0.1
    #redis服务器密码
    #spring.redis.password=123456
    #redis服务器连接端口号
    spring.redis.port=6379
    #redis连接池设置
    spring.redis.jedis.pool.max-idle=8
    spring.redis.jedis.pool.min-idle=0
    #spring.redis.sentinel.master=
    #spring.redis.sentinel.nodes=
    spring.redis.timeout=60000``

  • 接下来再看RedisAutoConfiguration这个类

@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class,JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
		public 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) throwsUnknownHostException {
                 StringRedisTemplate template = new StringRedisTemplate();
                template.setConnectionFactory(redisConnectionFactory);
              return template;
		 	}
}
  • RedisProperties类会将application.properties这个redis相关的配置加载
  • 然后将StringRedisTemplate实例化被spirng加载
  • 然后我们就能注入啦
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章