Mastering Java EE Development with WildFly
上QQ阅读APP看书,第一时间看更新

Container lifecycle events

An internal event management is inside the life cycle of the CDI container. For example, when the discovery system finds a bean, it sends a registration event. When the bean goes out of scope, an event is sent to destroy it. CDI lets us customize these processes thanks to the extensions.

The extensions are represented by classes extending the API Extension and declared as services in the folder META-INF/services of our application. An extension can override one of these events, BeforeBeanDiscovery, AfterBeanDiscovery, AfterDeploymentValidation, and BeforeShutdown.

Here's a sample of CDI extension:

import javax.enterprise.inject.spi.Extension;
class ObserverExtension implements Extension { ... }

Next, register our extension as a service provider through a file META-INF/services/javax.enterprise.inject.spi.Extension, which contains the name of our extension class:

it.vige.businesscomponents.injection.inject.spi.ObserverExtension

We have created an extension. Unlike the beans, the extensions start at deploy time but they can be injected in our beans anyway:

@Inject
private ObserverExtension observerExtension;

See now how to implement the beforeBeanDiscovery event:

import javax.enterprise.inject.spi.Extension;
class ObserverExtension implements Extension {
void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) {
...
}
<T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat) {
logger.info
("scanning type: " + pat.getAnnotatedType().getJavaClass().getName());
}
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd) {
...
}
}

Thanks to the AfterBeanDiscovery object, we can register a bean at runtime. Here is a sample:

Void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager bm) {

This example reads annotations of the class:

AnnotatedType<SecurityManager> at = bm.createAnnotatedType(SecurityManager.class);

This example creates an instance of the class and injects dependencies:

final InjectionTarget<SecurityManager> it = bm.createInjectionTarget(at);
abd.addBean(new Bean<SecurityManager>() {...}

In fact, the extension does more than just observe. An extension can modify the metamodel of the container too. Here’s a very simple sample:

import javax.enterprise.inject.spi.Extension;
class ObserverExtension implements Extension {
<T> void processAnnotatedType(@Observes @WithAnnotations({Named.class}) ProcessAnnotatedType<T> pat) {
/* tell the container to ignore the type if it is annotated
@Ignore */
if ( pat.getAnnotatedType().isAnnotationPresent(Named.class) )
pat.veto();
}
}
The @WithAnnotations annotation causes the container to deliver the events only for the types that contain the annotation specified as a parameter.

The observer method may inject a BeanManager:

<T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat, BeanManager beanManager) { ... }

An extension observer method is not allowed to inject any other object.