A decorator is a Java class that is annotated
javax.decorator.Decorator
and that has a corresponding decorators
element in the beans.xml
file.
A decorator bean class must also have a delegate injection point, which
is annotated javax.decorator.Delegate
. This injection point can be a
field, a constructor parameter, or an initializer method parameter of
the decorator class.
Decorators are outwardly similar to interceptors. However, they actually
perform tasks complementary to those performed by interceptors.
Interceptors perform cross-cutting tasks associated with method
invocation and with the lifecycles of beans, but cannot perform any
business logic. Decorators, on the other hand, do perform business logic
by intercepting business methods of beans. This means that instead of
being reusable for different kinds of applications, as are interceptors,
their logic is specific to a particular application.
For example, instead of using an alternative TestCoderImpl
class for
the encoder
example, you could create a decorator as follows:
@Decorator
public abstract class CoderDecorator implements Coder {
@Inject
@Delegate
@Any
Coder coder;
public String codeString(String s, int tval) {
int len = s.length();
return "\"" + s + "\" becomes " + "\"" + coder.codeString(s, tval)
+ "\", " + len + " characters in length";
}
}
This simple decorator returns more detailed output than the encoded
string returned by the CoderImpl.codeString
method. A more complex
decorator could store information in a database or perform some other
business logic.
A decorator can be declared as an abstract class so that it does not
have to implement all the business methods of the interface.
In order for a decorator to be invoked in a CDI application, it must,
like an interceptor or an alternative, be specified in the beans.xml
file. For example, the CoderDecorator
class is specified as follows:
<decorators>
<class>javaeetutorial.decorators.CoderDecorator</class>
</decorators>
If an application uses more than one decorator, the decorators are
invoked in the order in which they are specified in the beans.xml
file.
If an application has both interceptors and decorators, the interceptors
are invoked first. This means, in effect, that you cannot intercept a
decorator.
The decorators that you specify in the beans.xml
file apply only to
classes in the same archive. Use the @Priority
annotation to specify
decorators globally for an application that consists of multiple
modules, as in the following example:
@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public abstract class CoderDecorator implements Coder { ... }
Decorators with lower priority values are called first. You do not need
to specify the decorator in the beans.xml
when you use the @Priority
annotation.