I want to use RedisTemplate on spring boot. I can use StringRedeisTemplate successfully, but when i cant use RedisTemplate . here is the code.
@Service
public class MyService {
@Autowired
private RedisTemplate<String, Long> template;
public void execute() {
template.opsForValue().set("hoge", 1l);
}
}
But, when start apps, get errors.
> Exception in thread "main"
> org.springframework.beans.factory.BeanCreationException: Error
> creating bean with name 'MyService': Injection of autowired
> dependencies failed; nested exception is
> org.springframework.beans.factory.BeanCreationException: Could not
> autowire field: private
> org.springframework.data.redis.core.RedisTemplate
> org.hoge.service.MyService.template; nested exception is
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
> at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
> at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)
> at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
> at
> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
> at
> org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
> at
> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
> at
> org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
> at
> org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
> at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
> at
> org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
> at
> org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
> at
> org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
> at
> org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
> at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
> at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:961)
> at
> org.springframework.boot.SpringApplication.run(SpringApplication.java:950)
> at
> jp.bizreach.davide.recommend.application.DavimendApplication.main(DavimendApplication.java:11)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:483) at
> com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
> Caused by: org.springframework.beans.factory.BeanCreationException:
> Could not autowire field: private
> org.springframework.data.redis.core.RedisTemplate
> org.hoge.service.MyService.template; nested exception is
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
> at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:558)
> at
> org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
> at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
> ... 21 more Caused by:
> org.springframework.beans.factory.NoSuchBeanDefinitionException: No
> qualifying bean of type
> [org.springframework.data.redis.core.RedisTemplate] found for
> dependency: expected at least 1 bean which qualifies as autowire
> candidate for this dependency. Dependency annotations:
> {@org.springframework.beans.factory.annotation.Autowired(required=true)}
> at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
> at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
> at
> org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
> at
> org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:530)
> ... 23 more
The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean autowiring.
Spring @Autowired annotation is used for automatic dependency injection. Spring framework is built on dependency injection and we inject the class dependencies through spring bean configuration file.
The @Autowired annotation provides more fine-grained control over where and how autowiring should be accomplished. The @Autowired annotation can be used to autowire bean on the setter method just like @Required annotation, constructor, a property or methods with arbitrary names and/or multiple arguments.
@Autowired annotation is optional for constructor based injection. Here, the person object from the container is passed to the constructor while creating the Customer object. The setter method will be called with the Person object at runtime by the container.
Give something different, as now is 2018(something changes a lot which blocks me for a long time)
First Dependency
(Gradle)
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-data-redis-reactive')
Remember to use the latest version, you can use gradle-use-latest-versions-plugin to check whether the dependency is latest.
RedisServer
[Linux]
redis-server
[spring.properties]
spring.redis.host=localhost
spring.redis.port=6379
spring.cache.cache-names=orderIdPool,users
spring.cache.redis.cache-null-values=true
spring.cache.redis.time-to-live=600000ms
Redis config
@Configuration
public class RedisConfig {
/**
* create a lettuceConnectionFactory for redisTemplate {@link
#redisUserTemplate()}
* @return LettuceConnectionFactory, the old version use Jedis
*/
@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
return new LettuceConnectionFactory();
}
/**
* Description: aiming to create a template for Long and user(To be a user cache)
* @return redisTemplate<Long,User>
*/
@Bean
@Qualifier("redisUserTemplate")
public RedisTemplate<Long, User> redisUserTemplate() {
RedisTemplate<Long, User> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(new LettuceConnectionFactory());
return redisTemplate;
}
use RedisTemplate
private RedisTemplate redisTemplate
//@Qualifier to choose the bean you actually want.
@Autowired
public constructor(@Qualifier("xxxRedisTemplate")RedisTemplate redisTemplate){
this.redisTemplate=redisTemplate;
}
use redisTemplate
private HashOperations<Long, byte[], byte[]> hashOperations = redisUserTemplate.opsForHash();
private HashMapper<Object, byte[], byte[]> hashMapper = new ObjectHashMapper();
@Nullable
public void saveObject(Long key, User user) {
Map<byte[], byte[]> mappedHash = hashMapper.toHash(user);
hashOperations.putAll(key, mappedHash);
}
public Object loadObject(Long key) {
Map<byte[], byte[]> loadedHash = hashOperations.entries(key);
return hashMapper.fromHash(loadedHash);
}
If you encounter the circular spring injection error, consider setter injection, @Lazy, @PostConstructor or implements ApplicationContextAware, InitalizingBean, for more information surf this link how to fix this
The stacktrace suggest that you haven't defined the Bean which you will like to use for injecting in RedisTemplate
.You can resolve it creating a configuration file, E.g.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class AppConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
RedisTemplate< String, Long > redisTemplate() {
final RedisTemplate< String, Long > template = new RedisTemplate< String, Long >();
template.setConnectionFactory( jedisConnectionFactory() );
template.setKeySerializer( new StringRedisSerializer() );
template.setHashValueSerializer( new GenericToStringSerializer< Long >( Long.class ) );
template.setValueSerializer( new GenericToStringSerializer< Long >( Long.class ) );
return template;
}
}
Once you have the configuration file then you need to pass it to SpringApplication.run
E.g.
Object[] sources = {AppConfig.class};
ApplicationContext ctx = SpringApplication.run(sources, args);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With