CDI supports two mechanisms for dynamically adding or modifying the behavior of beans: interceptors and decorators.
Interceptors
Interceptors provide a mechanism for implementing functionality across multiple beans, and bean methods, that is orthogonal to the core function of those beans.
It is often used for non-business features like logging or security. For instance, in Java EE 7 the JTA specification provides the @Transactional
interceptor to control transactions for the current invocation.
Interceptor Binding Type
An interceptor binding is an annotation annotated with the @javax.interceptor.InterceptorBinding
meta-annotation.
Its goal is to bind the interceptor code to the bean or method to intercept.
defining an interceptor binding
`@Inherited`
`@Target`({TYPE, METHOD})
`@Retention`(RUNTIME)
`@InterceptorBinding`
**public** `@interface` Loggable {
}
Interceptor definition
An interceptor is a bean declared with the @javax.interceptor.Interceptor
annotation.
Its matching interceptor binding should also be added to its declaration.
Since CDI 1.1, the interceptor can be enabled with @javax.annotation.Priority
annotation--this defines its resolution order.
Method interceptors should have a method annotated @javax.interceptor.AroundInvoke
that takes the javax.interceptor.InvocationContext
as a parameter.
Defining an interceptor
`@Interceptor`
`@Loggable` **(1)**
`@Priority`(Interceptor.Priority.APPLICATION) **(2)**
**public** **class** **TransactionInterceptor** {
`@AroundInvoke` **(3)**
**public** Object logMethod(InvocationContext ctx) {
*// …*
}
}
- The interceptor binding to bind this code to this annotation
- The
@Priority
annotation to enable and prioritize the interceptor.
- The
@AroundInvoke
annotation indicates which method does the interception
Using interceptors
Thanks to interceptor binding it is very easy to apply an interceptor to bean or method.
**public** **class** **MyBean** {
`@Logabble`
**public** **void** doSomething() {
....
}
}
`@Logabble`
**public** **class** **MyOtherBean** {
**public** **void** doSomething() {
....
}
}
When applied on a bean, all the bean’s methods will be intercepted.
Activating and ordering interceptors
In Java EE 7 the easiest way to activate an interceptor in to use the @Priority
annotation.
It is also possible to do it in beans.xml file as explained in the spec.
Decorators
Decorators also dynamically extend beans but with a slightly different mechanism than interceptors. Where interceptors deliver functionality orthogonal to potentially many beans, decorators extend the functionality of a single bean-type with functionality that is specific to that type.
Decorators are an easy way to change the business operation of an existing bean.
A decorator is a bean annotated with @javax.decorator.Decorator
.
A decorator only decorates the interfaces that it implements (i.e. to be decorated a bean must implement an interface).
Example: a decorator firing an event in addition of expected code execution
`@Decorator` **(1)**
`@Priority`(Interceptor.Priority.APPLICATION) **(2)**
**public** **abstract** **class** **EventingDecorator** **implements**
MyBusiness **(3)**
{
`@Inject`
`@Delegate` **(4)**
MyBusiness business;
`@Inject`
Event evt;
**public** **void** doSomething(String message) {
business.doSomething(message);
evt.fire(message)
}
}
- The decorator is defined with the matching annotation
- Decorators are enabled and prioritized like interceptors
- As all methods don’t have to be decorated (i.e. implemented), the decorator is allowed to be an abstract class
- The decorated bean is injected with the specific
@Delegate
annotation.
A decorator must declare a single delegate injection point annotated @javax.decorator.Delegate
. The delegate injection point is the bean to be decorated. Any calls to the delegate object that correspond to a decorated type will be called on the decorator, which may in turn invoke the method directly on the delegate object. The decorator bean does not need to implement all methods of the decorated types and may be abstract.
Activating and ordering decorators
In Java EE 7 the easiest way to activate a decorator in to use the @Priority
annotation.
It is also possible to activate a decorator in beans.xml, as explained in the spec.
Decorators are always called after interceptors.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}