首页 > 解决方案 > 带有 Ehcache 3.x 的 Spring Boot 2.x - @Autowired 服务在自定义 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>

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

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

Obs:不仅 SimpMessagingTemplate 在运行时为空。我也尝试过自动装配一个自定义类,结果是一样的。

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

标签: javaspring-bootehcache

解决方案


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

这暗示了您的问题,您不能将 spring bean 注入到非 spring 托管对象实例中。您可以使用一个简单的类为您提供对 spring 上下文的静态访问,以加载此处描述的 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 支持ehcache 3.x。org.springframework.boot:spring-boot-starter-cache我不知道这是否适合您的目的,但如果 ehcache 与 spring 集成可能会更容易。


推荐阅读