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加載
  • 然後我們就能注入啦
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章