我有一个新的Jakarta EE(Qurakus)应用程序和一些旧代码,其中包含注册事件侦听器的方法.我已经为事件注册表制作了一个包装器.现在我需要一些方法来有效地注册许多事件监听器.它看起来像这样:

@ApplicationScoped
public class EventRegistry {
    private Set<Listener<?>> listeners = Collections.synchronizedSet(new HashSet<>());

    public void register(Listener l) {
    }
    public void unregister(Listener l) {
    }
}
@ApplicationScoped
public class Listener1 implements Listener<MyEvent> {
    @Override
    public void onEvent(MyEvent e) {
    }
}

所以基本上我需要一种让听众注册的方法.我考虑使用我在注册表的PostConstruct中触发的Jakarta EE事件,并在每个侦听器中侦听它,然后侦听器再注册它自己.这是一种省钱的方法吗?或者,如果不通过注入使用侦听器Bean,它会被销毁吗?此外,通常还有一种更好的方法来为特定的Bean执行操作(我将所有侦听器都放在一个包中).

推荐答案

一个简单的方法来做你想做的事情是:

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

@ApplicationScoped
public class EventRegistry {
    private final Set<Listener<?>> listeners = Collections.synchronizedSet(new HashSet<>());

    @Inject
    void init(Instance<Listener<?>> listenerInstance) {
        // check out the comments; for Quarkus you can inject all listeners as:
        // @Inject @All List<Listener<?>> listeners
        listenerInstance.forEach(listeners::add);
    }

    public void register(Listener l) { // maybe not even needed anymore
        listeners.add(l);
    }
}

您可以要求CDI进行方法注入;您也可以向它请求一个类型的Instance(在本例中是您的Listener),并通过Instance检索所有实现,如上所示.在实例上发生注入时,在任何@PostConstruct个方法之前调用用@Inject注释的方法.您可以进行属性注入(即@Inject private Instance<Listener<?>> listenerInstance),但您只需要在EventRegistry的初始化期间使用此对象.没有理由再把它留在一处房产里了.

由于您使用的是CDI,并且CDI支持观察者模式,因此您可以考虑更改实现以使用该工具,如另一个答案中所建议的那样.

Java相关问答推荐

如何计算内循环的时间复杂度?

具有默认分支的JUnit代码覆盖率切换声明

Cosmos Change Feed Process Lag远远超过收集中的记录数量

最小拓Flutter 排序的时间复杂度是多少?

方法没有用正确的值填充数组—而是将数组保留为null,'

为什么我的ArrayList索引的索引总是返回-1?

对于几乎不涉及逻辑的请求,您是否应该使用命令模式?

Spring Boot 3.2.2中的@Inject和@Resource Remove

使用传递的参数构造异常的Mockito-doThrow(或thenThrow)

返回响应时,CamelCase命名约定不起作用

类型集合的Jackson JsonNode:类型引用的对象读取器应该是Singleton吗?

Kotlin Val是否提供了与Java最终版相同的可见性保证?

Lombok@Nonnull是否也对供应商有影响?

Java泛型类方法的静态返回类型是否被类型擦除?

无法播放音频:从资源加载库GStreamer-Lite失败

删除打印语句会影响功能...腐败在起作用?

本机方法(JNI)总是编译的吗?

Java HashMap保留所有时间复杂性

如何修复Spring Boot应用程序中的RestDocumentationGenerationException:java.io.FileNotFoundException:/curl-request.adoc(只读文件系统)?

如何正确使用java.time类?