Spring 使用 Ehcache 2.x 引导 3.x - @Autowired 服务在自定义 CacheEventListener 中为空

Spring Boot 2.x with Ehcache 3.x - @Autowired service is null inside custom CacheEventListener

我使用 Ehcache 作为缓冲区来为所有连接到 WebSocket 的客户端传递数据(Spring)。

CacheEventListener 实现:

public class CacheListener implements CacheEventListener<ArrayList, MeasurementPoint> {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate; //<-- This is null at runtime

    @Override
    public void onEvent(CacheEvent<? extends ArrayList, ? extends MeasurementPoint> cacheEvent) {
        simpMessagingTemplate.convertAndSend("/topic/measurementsPoints", cacheEvent.getNewValue());
    }
}

Ehcache 配置xml:

config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xsi:schemaLocation="
            http://www.ehcache.org/v3
            http://www.ehcache.org/schema/ehcache-core-3.7.xsd">
    <!-- Default cache template -->
    <cache-template name="default">
        <resources>
            <heap>1000</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache-template>

    <cache alias="measurementsCache" uses-template="default">
        <key-type>java.util.ArrayList</key-type>
        <value-type>br.com.petrobras.risersupervisory.model.MeasurementPoint</value-type>
        <listeners>
            <listener>
                <class>br.com.petrobras.risersupervisory.framework.CacheListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>UPDATED</events-to-fire-on>
            </listener>
        </listeners>
    </cache>
</config>

我尝试遵循一些教程,但所有教程都使用日志库或 System.out.println 在 CacheEventListener 实现中。

有什么方法可以在 CacheEventListener 中自动装配 @Service(Spring) 吗?这个实现是错误的吗?我找不到一个在 CacheEventListener 中使用 @Autowired 的人的例子。

Obs:不仅仅是 SimpMessagingTemplate 在运行时为 null。我也试过自动装配自定义 class 结果是一样的。

Obs2:在搜索 spring 引导日志后,我相信 CacheEventListener 在 spring 引导完成加载之前已绑定到缓存。不确定是否是这个问题。

Obs2: After searching for spring boot logs, I believe CacheEventListener is been binded to the cache before spring boot finishes loading. Not sure if this is the problem.

这暗示了您的问题,您不能将 spring bean 注入到非 spring 托管对象实例中。您可以使用一个简单的 class 来静态访问 spring 上下文来加载描述为 here.

的 bean
@Component
public class SpringContext implements ApplicationContextAware {
 
private static ApplicationContext context;
 
  public static <T extends Object> T getBean(Class<T> beanClass) {
    return context.getBean(beanClass);
  }
 
  @Override
  public void setApplicationContext(ApplicationContext context) throws BeansException 
  {
     
    // store ApplicationContext reference to access required beans later on
    SpringContext.context = context;
  }
}

SpringContext.getBean(YourBean.class);

如果您在 spring 上下文初始化之前尝试这样做,您可能仍然会遇到问题。 值得一提的是 spring-boot supports ehcache 3.x 通过 org.springframework.boot:spring-boot-starter-cache 依赖。我不知道这是否适合您的目的,但如果将 ehcache 与 spring.

集成可能会更容易