假设我有以下内容:
配置
设置 guava EventBus bean。
@Configuration
public class AppConfig {
@Bean
public EventBus eventBus() {
return new EventBus(); // guava event bus
}
}
事件监听器
监听并处理放在事件总线上的部分/所有事件。 可能有几个与此类似的不同类来订阅应用程序中的事件。
@Component
public class EventListener {
@Autowired
public EventListener(EventBus eventBus) {
eventBus.register(this); // register this instance with the event bus so it receives any events
}
@Subscribe
public void onTestEvent(TestEvent e) {
System.out.println("Caught event");
}
}
事件调度器
将事件放在事件总线上的东西。
@Component
public class EventDispatcher {
@Autowired
public EventDispatcher(EventBus eventBus) {
eventBus.post(new TestEvent());
}
}
主应用入口点
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
我如何确保所有监听事件的类都在发布它们的类之前被实例化?也就是说,目前事件派发器类可能会在监听器被实例化之前被实例化并发布事件,这意味着监听器可能会错过事件。
我在想也许可以创建另一个注解,比如@EventListener,然后让 spring 以某种方式对所有带有这个注解的类进行优先级排序,但不确定如何实现这个或者这是否真的是个好主意。
谢谢。
最佳答案
我决定扩展 Guava EventBus
类创建 BufferedEventBus
。
这只是缓冲发送给它的任何事件对象,直到应用程序上下文完成加载。当发生这种情况时,它会发布任何缓冲的事件。任何 future 事件都会立即发布,不会被缓冲。
BufferedEventBus
package tjenkinson.events;
import java.util.ArrayList;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import com.google.common.eventbus.EventBus;
/**
* A guava event bus that holds back any events that are posted to it until the application
* context has finished loading meaning all eager-loaded beans will have been constructed.
*
* This means any eager-loaded beans that want to listen to events on this event bus will be able
* to and not miss any events that were posted from other beans before they had a chance to listen.
*/
@Service
public class BufferedEventBus extends EventBus implements ApplicationListener<ContextRefreshedEvent> {
private boolean applicationContextLoaded = false;
private final ArrayList<Object> bufferedEvents = new ArrayList<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
synchronized(bufferedEvents) {
if (applicationContextLoaded) {
// context already loaded. maybe it's been refreshed.
return;
}
postBufferedEvents();
applicationContextLoaded = true;
}
}
@Override
public void post(Object event) {
synchronized(bufferedEvents) {
if (applicationContextLoaded) {
super.post(event);
}
else {
bufferedEvents.add(event);
}
}
}
private void postBufferedEvents() {
synchronized(bufferedEvents) {
for (Object event : bufferedEvents) {
super.post(event);
}
bufferedEvents.clear();
}
}
}
我现在只是在整个应用程序中使用它而不是标准的 EventBus
。
关于java - 在 spring 中,确保在调度事件之前实例化 Guava Event Bus 监听器 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28246529/