我正在学习Redis。现在面临redis缓存问题。我正在调用具有相同值的服务类的方法,但似乎每次都执行。
当我从ThreadService调用EmployeeService的getEmployeesByClient()方法时,我期望有一个新客户端,我会在getEmployeeByClient内部看到日志 。但是对于下一次调用,我将从缓存中获取列表,然后它将不会从存储库中提供数据。
但是每次我使用相同的参数调用EmployeeService的getEmployeesByClient()方法时,都会在getEmployeeByClient内部获取日志。本节末尾也提供了我的日志。
我已经看到这个网站的一些问题,例如: Spring boot caching in @Service class does not work
但是还没有解决办法。
我正在提供相关代码:
我的ThreadService类:
@Service
@Slf4j
public class ThreadService implements Runnable {
@Autowired
private EmployeeService employeeService;
public static boolean isRunning = true;
@PostConstruct
@Override
public void run() {
log.debug("Service Thread Started");
while(isRunning) {
log.debug("repository calling...");
List<Employee> employees = employeeService.getEmployeesByClient("FastVoiz");
log.debug("Employee Size: " + employees.size());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
log.error("Exception: ", e);
}
}
}
}
EmployeeService类:
@Service
@Slf4j
public class EmployeeService {
@Autowired
private EmployeeRepository repository;
@Cacheable(value = "employeeCache", key = "#client")
public List<Employee> getEmployeesByClient(String client) {
log.debug("Inside of getEmployeeByClient");
return repository.findEmployeesByClient(client);
}
}
RedisConfiguration类:
@Configuration
@EnableCaching
@PropertySource("classpath:application.properties")
public class RedisConfiguration {
@Autowired
private Environment env;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
redisConf.setHostName(env.getProperty("spring.redis.host"));
redisConf.setPort(Integer.parseInt(env.getProperty("spring.redis.port")));
redisConf.setPassword(RedisPassword.of(env.getProperty("spring.redis.password")));
return new LettuceConnectionFactory(redisConf);
}
@Bean
public RedisCacheConfiguration cacheConfiguration() {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.disableCachingNullValues();
return cacheConfig;
}
@Bean
public RedisCacheManager cacheManager() {
RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(cacheConfiguration())
.transactionAware()
.build();
return rcm;
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demoNaz</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demoNaz</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven.test.skip>true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!--to run jar file-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>demoNaz</finalName>
</build>
</project>
application.properties文件:
#JPA configuration
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true
spring.data.jpa.repositories.enabled=true
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.properties.hibernate.id.new_generator_mappings=false
spring.jpa.properties.hibernate.format_sql=true
#datasource
spring.datasource.url=jdbc:postgresql://localhost:5432/testDB
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.initialization-mode=always
#spring.datasource.initialize=true
#spring.datasource.schema=classpath:/schema.sql
spring.datasource.continue-on-error=true
spring.datasource.platform=postgres
#redis
spring.redis.host=localhost
spring.redis.timeout=2000
spring.redis.password=password
spring.redis.port=6379
#redis cache manager configuration
spring.cache.type=redis
spring.cache.redis.cache-null-values=false
spring.cache.redis.time-to-live=600000
spring.cache.redis.use-key-prefix=true
#redis-lettuce configuration
spring.redis.lettuce.pool.max-active=7
spring.redis.lettuce.pool.max-idle=7
spring.redis.lettuce.pool.min-idle=2
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.shutdown-timeout=200ms
#logging
logging.level.root=DEBUG
logging.file=demoApp.log
#others
spring.main.allow-bean-definition-overriding=true
这是我的一些日志:
2019-10-13 20:17:29.619 DEBUG 12932 --- [ main] c.example.demoNaz.service.ThreadService : First line of thread
2019-10-13 20:17:29.619 DEBUG 12932 --- [ main] c.e.demoNaz.service.EmployeeService : Inside of getEmployeeByClient
2019-10-13 20:17:29.620 DEBUG 12932 --- [ main] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
2019-10-13 20:17:29.620 DEBUG 12932 --- [ main] o.h.q.c.internal.CriteriaQueryImpl : Rendered criteria query -> select generatedAlias0 from Employee as generatedAlias0 where generatedAlias0.client=:param0
2019-10-13 20:17:29.620 DEBUG 12932 --- [ main] org.hibernate.SQL : select employee0_.id as id1_0_, employee0_.acc as acc2_0_, employee0_.client as client3_0_ from employee employee0_ where employee0_.client=?
Hibernate: select employee0_.id as id1_0_, employee0_.acc as acc2_0_, employee0_.client as client3_0_ from employee employee0_ where employee0_.client=?
2019-10-13 20:17:29.622 DEBUG 12932 --- [ main] org.hibernate.loader.Loader : Result set row: 0
2019-10-13 20:17:29.622 DEBUG 12932 --- [ main] org.hibernate.loader.Loader : Result row: EntityKey[com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:29.622 DEBUG 12932 --- [ main] o.h.engine.internal.TwoPhaseLoad : Resolving associations for [com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:29.622 DEBUG 12932 --- [ main] o.h.engine.internal.TwoPhaseLoad : Done materializing entity [com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:29.623 DEBUG 12932 --- [ main] c.example.demoNaz.service.ThreadService : Employee Size: 1
2019-10-13 20:17:32.258 DEBUG 12932 --- [l-1 housekeeper] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)
2019-10-13 20:17:34.623 DEBUG 12932 --- [ main] c.example.demoNaz.service.ThreadService : First line of thread
2019-10-13 20:17:34.624 DEBUG 12932 --- [ main] c.e.demoNaz.service.EmployeeService : Inside of getEmployeeByClient
2019-10-13 20:17:34.625 DEBUG 12932 --- [ main] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
2019-10-13 20:17:34.625 DEBUG 12932 --- [ main] o.h.q.c.internal.CriteriaQueryImpl : Rendered criteria query -> select generatedAlias0 from Employee as generatedAlias0 where generatedAlias0.client=:param0
2019-10-13 20:17:34.627 DEBUG 12932 --- [ main] org.hibernate.SQL : select employee0_.id as id1_0_, employee0_.acc as acc2_0_, employee0_.client as client3_0_ from employee employee0_ where employee0_.client=?
Hibernate: select employee0_.id as id1_0_, employee0_.acc as acc2_0_, employee0_.client as client3_0_ from employee employee0_ where employee0_.client=?
2019-10-13 20:17:34.628 DEBUG 12932 --- [ main] org.hibernate.loader.Loader : Result set row: 0
2019-10-13 20:17:34.629 DEBUG 12932 --- [ main] org.hibernate.loader.Loader : Result row: EntityKey[com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:34.630 DEBUG 12932 --- [ main] o.h.engine.internal.TwoPhaseLoad : Resolving associations for [com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:34.630 DEBUG 12932 --- [ main] o.h.engine.internal.TwoPhaseLoad : Done materializing entity [com.example.demoNaz.entity.Employee#13002]
2019-10-13 20:17:34.631 DEBUG 12932 --- [ main] c.example.demoNaz.service.ThreadService : Employee Size: 1
2019-10-13 20:17:39.633 DEBUG 12932 --- [ main] c.example.demoNaz.service.ThreadService : First line of thread
2019-10-13 20:17:39.633 DEBUG 12932 --- [ main] c.e.demoNaz.service.EmployeeService : Inside of getEmployeeByClient
答案 0 :(得分:1)
首先,您不应该在 PostConstruct 阶段使用任何这些服务,因为不能保证此时代理拦截器已完全启动。如果需要执行某些操作,请在初始化应用程序上下文之后,尝试实现 InitializingBean 并覆盖 afterPropertiesSet ()方法,或收听诸如 ContextRefreshedEvent 的应用程序上下文事件。强>。从那里开始您的线程。这将确保所有其他bean已初始化。
现在,出现您的问题,这是因为您的缓存拦截器未初始化。解决方法是手动初始化拦截器。为此,您可以执行以下操作,
@Configuration
public class ConfigClass{
@Autowired
private CacheInterceptor cacheInterceptor;
@PostConstruct
public void init(){
cacheInterceptor.afterSingletonsInstantiated();
}
}
这将起作用。
还要在您的依赖项中添加 spring-boot-starter-cache https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache