@Initialized(ApplicationScoped.class) 事件何时在 CDI 中发送?

When is the @Initialized(ApplicationScoped.class) event sent in CDI?

我试图了解在 CDI 容器抛出的事件上下文中的 @Initialized() 事件的 lifecycle/flow,这些事件在扩展中是可观察到的。

根据 WELD 2 docs, the Container lifecycle events 是:

  • BeforeBeanDiscovery
  • ProcessAnnotatedType and ProcessSyntheticAnnotatedType
  • AfterTypeDiscovery
  • ProcessInjectionTarget and ProcessProducer
  • ProcessInjectionPoint
  • ProcessBeanAttributes
  • ProcessBean, ProcessManagedBean, ProcessSessionBean, ProcessProducerMethod and ProcessProducerField
  • ProcessObserverMethod
  • AfterBeanDiscovery
  • AfterDeploymentValidation
  • BeforeShutdown

我无法找到的是,在此容器生命周期中,@Initialized event be triggered. I suspect that it is done AfterDeploymentValidation, but I cannot find any documentation to support that fact. Additionally, I can't seem to find anything in the CDI 1.1 spec 会在哪里指示 when/where 抛出 @Initalized 事件。

例如,事件是在发现的bean的所有@PostConstruct方法执行之前还是之后抛出的?事件是在 EJB @Startup 初始化之前还是之后抛出?是否有任何文档清楚地列出了 CDI 中这些事件的 order/sequence?

Q1: What I'm having trouble finding out is where during this container lifecycle would the @Initialized event be triggered. I suspect that it is done AfterDeploymentValidation, but I cannot find any documentation to support that fact.

CDI 1.1 spec, section 11.5.4. AfterDeploymentValidation event所述:

The container must fire an event after it has validated that there are no deployment problems and before creating contexts or processing requests.

A1: 因此,具有限定符 @Initialized 任何范围 的事件将被触发 AfterDeploymentValidation 事件之后。


Q2: Additionally, I can't seem to find anything in the CDI 1.1 spec which dictates when/where the @Initalized event is thrown.

A2: 部分 6.7. Context management for built-in scopes 描述了每个内置作用域的行为并提供了自定义作用域实现的建议:

Portable extensions are encouraged to fire an event with qualifier @Initialized(X.class) when a custom context is initialized ...
An event with qualifier @Initialized(RequestScoped.class) is fired when the request context is initialized ...etc.


Q3: For instance, is the event thrown before or after all the @PostConstruct methods of discovered beans is executed?

6.7. Context management for built-in scopes所述:

The request scope is active:
- ...
- during @PostConstruct callback of any bean.

The application scope is active:
- ...
- during @PostConstruct callback of any bean.
...etc

A3: 作用域要激活,首先需要对其进行初始化。因此,带有限定符 @Initialized 的事件将在 @PostConstruct 任何 bean 的回调之前触发,但仅限于必须在回调中处于活动状态的范围。


Q4: Is the event thrown before or after an EJB @Startup is initialized? Is there any documentation that clearly lists the order/sequence of these events in CDI?

A4: EJB 包含在单独的规范中 JSR 345: Enterprise JavaBeans TM ,Version 3.2 EJB Core Contracts and Requirements

根据第 4.8.1 节单例会话 Bean 初始化:

By default, the container is responsible for deciding when to initialize a singleton session bean instance. However, the Bean Provider can optionally configure the singleton session bean for eager initialization. If the Startup annotation appears on the singleton session bean class or if the singleton session bean has been designated via the deployment descriptor as requiring eager initialization, the container must initialize the singleton session bean instance during the application startup sequence. The container must initialize all such startup-time singleton session beans before any external client requests (that is, client requests originating outside of the application) are delivered to any enterprise bean components in the application.
...
In some cases, explicit initialization ordering dependencies exist between multiple singleton session bean components in an application. The DependsOn annotation is used to express these dependencies. A DependsOn dependency is used in cases where one singleton session bean must initialize before one or more other singleton session beans. The container ensures that all singleton session beans with which a singleton session bean has a DependsOn relationship have been initialized before the PostConstruct method is called.

因此,具有限定符 @Initialized 的事件也将在 EJB bean 的 @PostConstruct 回调之前触发,但仅限于必须在回调中处于活动状态的范围。