一旦缓存条目过期,我尝试使用 EntryExpiredListener 使用另一个服务执行操作,但如果它正在调用服务,并且该服务正在调用系统中的任何存储库,我无法将侦听器添加到缓存中
The dependencies of some of the beans in the application context form a cycle:
filterChainExceptionHandler (field private org.springframework.web.servlet.HandlerExceptionResolver sb.practice.configs.security.filters.FilterChainExceptionHandler.resolver)
↓
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
↓
openEntityManagerInViewInterceptorConfigurer defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]
↓
openEntityManagerInViewInterceptor defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]
┌─────┐
| cacheManager defined in class path resource [org/springframework/boot/autoconfigure/cache/HazelcastCacheConfiguration.class]
↑ ↓
| cacheService defined in file [D:\Dev\Locals\pt-spring-boot\target\classes\sb\practice\services\impl\CacheService.class]
↑ ↓
| activeUserCacheService_Hazelcast defined in file [D:\Dev\Locals\pt-spring-boot\target\classes\sb\practice\services\impl\caches\ActiveUserCacheService_Hazelcast.class]
↑ ↓
| masterRoleRepository defined in sb.practice.repositories.masters.MasterRoleRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration
↑ ↓
| (inner bean)#28f48a7c
└─────┘
这是我的缓存监听器:
@Slf4j
public class CacheListener implements EntryExpiredListener<String, String>{
public ActiveUserCacheService_Hazelcast activeUsersCache;
@Override
public void entryExpired(EntryEvent<String, String> event) {
log.info("entryEvicted. Cache: {}. Value: {}. \nEvent: {} ", event.getName(), event.getOldValue(), event);
}
}
缓存服务:
@Service
@RequiredArgsConstructor
public class CacheService {
@Value("${hazelcast.cache.cluster.nodes}")
String[] clusteringNodes;
private final ActiveUserCacheService_Hazelcast activeUserCacheService_Hazelcast;
public <T> boolean containsKey(long key, String cacheName) {
IMap<Long, T> map = hazelcastInstance().getMap(cacheName);
return map.containsKey(key);
}
private static MapConfig mapConfig(String name, Integer timeToLive) {
MapConfig mapConfig = new MapConfig(name);
mapConfig.setTimeToLiveSeconds(timeToLive);
//
// EntryListenerConfig entryListenerConfig = new EntryListenerConfig();
// entryListenerConfig.setImplementation(new CacheListener());
// mapConfig.addEntryListenerConfig(entryListenerConfig);
final EvictionConfig evictionConfig = new EvictionConfig();
evictionConfig.setEvictionPolicy(EvictionPolicy.LRU);
evictionConfig.setMaxSizePolicy(MaxSizePolicy.PER_NODE);
evictionConfig.setSize(500);
mapConfig.setEvictionConfig(evictionConfig);
return mapConfig;
}
@Bean
HazelcastInstance hazelcastInstance() {
Config config = new Config();
CacheConstants.CACHES.forEach((name, timeToLive) -> config.addMapConfig(mapConfig(name, timeToLive)));
NetworkConfig network = config.getNetworkConfig();
network.setPort(5701).setPortCount(20);
network.setPortAutoIncrement(true);
JoinConfig join = network.getJoin();
join.getMulticastConfig().setEnabled(false);
join.getTcpIpConfig().setEnabled(true);
for (String clusteringNode : clusteringNodes) {
join.getTcpIpConfig().addMember(clusteringNode);
}
return Hazelcast.newHazelcastInstance(config);
}
}
该服务仅包含对 masterRoleRepository 的注入,这导致了问题。 有没有办法使用EventListener作为组件并调用服务来做逻辑?
提前谢谢您!
如果你有这样的配置,你可以将监听器创建为bean
@Configuration
@EnableAsync
public class HazelcastInstanceConfiguration {
public static final String MAP_NAME = "myMap";
@Bean
public Config hazelcastConfig() {
Config config = new Config();
// Configure the map
MapConfig mapConfig = config.getMapConfig(MAP_NAME);
mapConfig.setTimeToLiveSeconds(30);
EntryListenerConfig entryListenerConfig = new EntryListenerConfig();
entryListenerConfig.setImplementation(cacheListener());
mapConfig.addEntryListenerConfig(entryListenerConfig);
return config;
}
@Bean
CacheListener cacheListener() {
return new CacheListener();
}
}
在监听器中使用 setter 注入服务
@Slf4j
@RequiredArgsConstructor
public class CacheListener implements EntryExpiredListener<String, String> {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
@Override
public void entryExpired(EntryEvent<String, String> event) {
log.info("entryEvicted. Cache: {}. Value: {}. \nEvent: {} ",
event.getName(), event.getOldValue(), event);
myService.deleteFromRepository(event.getKey());
}
}
使服务异步,以免阻塞 hazelcast 线程
@Service
@Slf4j
public class MyService {
@Async
public void deleteFromRepository(String key) {
log.info("deleteFromRepository is called for key : {}", key);
}
}