Hazelcast嵌入式实例场景下仅单次添加Local Entry Listener方案问询
问题解决思路
核心需求为避免Local Entry Listener在当前Hazelcast实例上被重复注册,下面给出2种可落地的实现方案:
方案1:校验已注册监听器列表(最贴合你给出的理想实现逻辑)
Hazelcast的IMap接口提供了getLocalEntryListeners()方法,可以直接获取当前节点该Map实例上所有已注册的本地Entry监听器,你只需要判断目标监听器是否已在列表中即可。
注意如果每次注册都new新的监听器实例,需要重写监听器类的equals()和hashCode()方法,或者将监听器注册为单例Bean复用同一实例,避免实例不同导致校验失效。
补全后的代码如下:
@Bean public HazelcastInstance instance() { HazelcastInstance instance = Hazelcast.getInstance(); IMap<String, ?> sessionsMap = instance.getMap("spring:session:sessions"); // 校验逻辑:判断当前Map的本地监听器中是否已存在自定义监听器实例 boolean hasMyListener = sessionsMap.getLocalEntryListeners().stream() .anyMatch(listener -> listener instanceof MyLocalListener); if (!hasMyListener) { sessionsMap.addLocalEntryListener(new MyLocalListener()); } return instance; }
方案2:存储监听器注册ID做校验
addLocalEntryListener()返回的UUID虽然是随机的,但仅对当前节点的本地监听器有效,你不需要分布式存储这个ID,只要存在当前应用的本地上下文即可:
// 配置类成员变量存储注册ID,配置类为Spring单例,变量全局唯一 private final AtomicReference<UUID> listenerIdRef = new AtomicReference<>(); @Bean public HazelcastInstance instance() { HazelcastInstance instance = Hazelcast.getInstance(); IMap<String, ?> sessionsMap = instance.getMap("spring:session:sessions"); // 只有ID为null时才注册 if (listenerIdRef.get() == null) { UUID listenerId = sessionsMap.addLocalEntryListener(new MyLocalListener()); listenerIdRef.compareAndSet(null, listenerId); } return instance; }
额外排查建议
正常Spring单例@Bean方法只会被调用一次,如果你出现了重复注册的情况,建议先排查以下两点:
- 你的配置类是否被多次扫描、多次加载到Spring上下文
- HazelcastInstance Bean的作用域是否被误设为非单例
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

