为什么我的CDI启动类被调用了两次?

时间:2017-10-12 08:15:02

标签: java-ee cdi startup payara

在Payara上部署.war之后,我正在使用以下类进行一些初始化。我可以看到init()方法实际上在应用程序启动期间被调用了两次。

package mypackage;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
import javax.inject.Inject;

import lombok.extern.log4j.Log4j2;

@Log4j2
@ApplicationScoped
public class StartupService {

    @Inject LogConfig logConfig;

    void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
        log.debug("### STARTUP SERVICE CALLED ###");

        logConfig.startup();
    }
}

有人可以向我解释为什么这两次被召唤以及我如何避免它?

我的意思是,我当然可以实现一个静态布尔标志来识别我之前已经调用过一次,但是我更愿意修复根本原因并且只从头开始调用一次。

1 个答案:

答案 0 :(得分:1)

好的,我会尝试对此进行总结,但可能并非如此,我可以尝试深入挖掘。但这是我认为正在进行的......

您可以获得两次事件,每次都有不同的有效负载。 这可能有多种原因,但最有可能的一个原因是Paraya在整合方面存在微小缺陷。 Weld建议集成商通过SPI定义其运行环境。如果他们不这样做,Weld可以处理它,但需要做一些假设和猜测,以满足规范要求。

在这种情况下,我怀疑Paraya错误地定义Environment并且Weld不确定要触发哪些事件 - 对于Web模块,需要使用ServletContext有效负载触发事件,而其余部分模块具有普通Object作为有效载荷。

可悲的是,除了抢先获取有关环境的信息之外,没有简单的方法可以防止这两个事件被解雇。原因是Weld需要在Web模块有任何挂钩活动之前很久就决定Object有效负载事件。

您案例中的解决方案可能是将Object指定为更具体的类型 - 因此只能观察到一个事件。根据您的示例,我假设ServletContext有效负载将是您要查找的有效负载。