Декоратор — это класс Java, аннотированный javax.decorator.Decorator
и имеющий соответствующий элемент decorators
в файле beans.xml
.
Класс бина декоратора также должен иметь точку инъецирования делегата, которая аннотирована javax.decorator.Delegate
. Эта точка инъецирования может быть полем, параметром конструктора или параметром метода инициализатора класса декоратора.
Декораторы внешне похожи на Interceptor-ы. Тем не менее, они дополняют задачи, выполняемые Interceptor-ами. Interceptor-ы выполняют сквозные задачи, связанные с вызовом метода и жизненными циклами компонентов, но не могут выполнять какую-либо бизнес-логику. Декораторы, с другой стороны, выполняют бизнес-логику, перехватывая бизнес-методы бинов. Это означает, что вместо повторного использования для различных типов приложений, как и Interceptor-ы, их логика специфична для конкретного приложения.
Например, вместо использования альтернативного класса TestCoderImpl
для примера encoder
, вы можете создать декоратор следующим образом:
@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";
}
}
Этот простой декоратор возвращает более подробный вывод, чем закодированная строка, возвращённая методом CoderImpl.codeString
. Более сложный декоратор может хранить информацию в базе данных или выполнять другую бизнес-логику.
Декоратор может быть объявлен как абстрактный класс, так что ему не нужно реализовывать все бизнес-методы интерфейса.
Чтобы декоратор вызывался в приложении CDI, он должен, как и Interceptor, или альтернатива, быть указан в файле beans.xml
. Например, класс CoderDecorator
указан следующим образом:
<decorators>
<class>javaeetutorial.decorators.CoderDecorator</class>
</decorators>
Если приложение использует более одного декоратора, декораторы вызываются в том порядке, в котором они указаны в файле beans.xml
.
Если в приложении есть как Interceptor-ы, так и декораторы, Interceptor-ы вызываются первыми. По сути, это означает, что вы не можете перехватить декоратор.
Декораторы, указанные в файле beans.xml
, применяются только к классам в одном и том же архиве. Используйте аннотацию @Priority
, чтобы глобально указывать декораторы для приложения, состоящего из нескольких модулей, как в следующем примере:
@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public abstract class CoderDecorator implements Coder { ... }
Декораторы с более низкими значениями приоритета вызываются первыми. Не обязательно указывать декоратор в beans.xml
, когда используется аннотация @Priority
.