Я использую 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());
}
}
XML-файл конфигурации Ehcache:
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.
Есть ли способ, которым я могу автоматически подключить @Service(Spring) внутри CacheEventListener? Является ли эта реализация неправильной? Я не смог найти ни одного примера использования @Autowired внутри CacheEventListener.
Obs: не только SimpMessagingTemplate имеет значение null во время выполнения. Я тоже пробовал автосвязывать пользовательский класс, и результат был таким же.
Obs2: после поиска журналов весенней загрузки я считаю, что CacheEventListener был привязан к кешу до завершения загрузки весенней загрузки. Не уверен, что это проблема.
@BenjaminCaure Я добавил @Component в класс CacheListener (тот, который реализует CacheEventListener), но, к сожалению, simpMessagingTemplate по-прежнему равен нулю.
CacheListener не контролируется Spring и поэтому не будет внедрен.
Спасибо за разъяснение @M.Deinum, я этого не знал. Я следовал руководству, указанному Hopey One, и это решило проблему.
Любая дополнительная информация, потому что у меня такая же проблема.




Obs2: после поиска журналов весенней загрузки я считаю, что CacheEventListener был привязан к кешу до завершения загрузки весенней загрузки. Не уверен, что это проблема.
Это намекает на вашу проблему: вы не можете внедрять bean-компоненты Spring в экземпляры управляемых объектов без 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.
Это было именно то, что мне было нужно! Спасибо за помощь, @Hopey One!
Можете ли вы попытаться аннотировать свой CacheListener с помощью аннотации @Component? это позволило бы внедрять зависимости с помощью Autowired