Spring Boot 中的 Hazelcast 和 JCache 创建了两个实例

Hazelcast and JCache in Spring Boot creates two instances

看起来默认 Spring 启动自动配置将在使用 JCache 并启用缓存时创建两个 hazelcast 实例 (@EnableCaching)

完整示例位于:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache

TLDR; Is there a way to get Spring boot's autoconfiguration to only create one Hazelcast instance when enabling caching through JCache?

我通过添加以下依赖项创建了一个演示 Spring 引导项目:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>

    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
    </dependency>

    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
    </dependency>

    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-spring</artifactId>
        <version>${hazelcast.version}</version>
    </dependency>

并将 @EnableCaching 添加到应用程序 class,Spring 将自动配置 Hazelcast 但会启动两个 hazelcast 实例,它们加入了一个集群,如日志所示:

Members [2] {
    Member [192.168.1.157]:5701 - 3eabbe90-6815-49ff-8d93-9e4b12e67810
    Member [192.168.1.157]:5702 - e9c93366-2408-4726-965a-b21dcf897113 this
}

缓存有效,但我不想要两个 Hazelcast 实例。

破解

我通过提供自己的缓存管理器设法让它工作:

@Bean
public CacheManager springHzProvider(HazelcastInstance instance) {
    return SpringHazelcastCachingProvider.getCacheManager(instance, null, new Properties());
}

并删除 hazelcasthazelcast-spring 依赖项并添加 hazelcast-all:

    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast-all</artifactId>
        <version>${hazelcast.version}</version>
    </dependency>

但问题是是否有更好的 'proper' 方法来实现这一点?理想情况下无需定义自定义缓存管理器并添加 hazelcast-all

@dvanrensburg 根据评论,作为临时解决方案,从 auto-configuration 中排除 HazelcastAutoConfiguration class。我已经记录了 Spring Boot https://github.com/spring-projects/spring-boot/issues/8275 的问题,因为我认为这是根本原因,如果 @EnableCaching 触发了第一个实例的创建,则不应创建第二个实例。

我在上面使用了 Neil 的解决方案,但是 运行 我无法自动装配由 JCache 配置创建的 Hazelcast 实例。看起来该实例是在 Spring 之外创建的,并已在应用程序上下文中注册。

在配置中为实例命名

<instance-name>test</instance-name>

然后添加一个显式挂钩以将实例引入上下文

@Bean
public HazelcastInstance getInstance() {
    return Hazelcast.getHazelcastInstanceByName("test");
}

效果很好。 HazelcastAutoconfiguration 不会 运行 因为它的条件是实例不存在。

我唯一担心的是,这在很大程度上依赖于以下事实:对于 Spring 版本 1.5.1 Boot,JCache 配置会创建此实例 在 HazelcastAutoconfiguration 启动之前。

更新 在优秀 Spring 引导社区的@snicoll 的帮助下,我找到了更好的解决方案。

只需明确告诉 Spring 引导使用哪个 hazelcast 配置并命名 Hazelcast 实例。将以下内容放入 application.properties spring.hazelcast.config=hazelcast.xml

示例见:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache/tree/fixed