SeamFramework.orgCommunity Documentation
Interceptores são um meio poderoso para capturar e separar preocupações ortogonais para o tipo de sistema. Qualquer interceptador é capaz de interceptar invocações de qualquer tipo Java. Isto torna-os ideais para resolver questões técnicas, tais como gerenciamento de transação e segurança. No entanto, por natureza, interceptores desconhecem a real semântica dos eventos que interceptam. Assim, interceptores não são um instrumentos adequados para a separação de questões relacionadas à negócios.
O contrário é verdadeiro decoradores. O decorator intercepta invocações apenas para uma determinada interface Java e, portanto, é ciente de toda a semântica que acompanha a interface. Isto torna os decoradores uma ferramenta perfeita para modelar alguns tipos de questões de negócios. Significa também que um decorador não tem a generalidade de um interceptador. Decoradores não são capazes de resolver questões técnicas que atravessam muitos tipos diferentes.
Suponha que temos uma interface que representa contas:
public interface Account {
public BigDecimal getBalance();
public User getOwner();
public void withdraw(BigDecimal amount);
public void deposit(BigDecimal amount);
}
Vários Web Beans em nosso sistema implementam a interface Account. No entanto, temos uma obrigação legal que, para qualquer tipo de conta, as grandes transações devem ser registadas pelo sistema, em um registro especial (log). Este é um trabalho perfeito para um decorador.
Um decorador é um Web Bean simples que implementa o tipo que decora e é anotado com @Decorator.
@Decorator
public abstract class LargeTransactionDecorator
implements Account {
@Decorates Account account;
@PersistenceContext EntityManager em;
public void withdraw(BigDecimal amount) {
account.withdraw(amount);
if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
em.persist( new LoggedWithdrawl(amount) );
}
}
public void deposit(BigDecimal amount);
account.deposit(amount);
if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
em.persist( new LoggedDeposit(amount) );
}
}
}
Ao contrário de outros Web Beans simples, um decorador pode ser uma classe abstrata. Se não há nada de especial que o decorador precisa fazer para um determinado método da interface decorada, você não precisa implementar esse método.
Todos os decoradores têm um atributo delegado. O tipo e os tipos de binding do atributo delegado determinam qual o Web Beans que o decorador está vinculado. O tipo do atributo delegado deve implementar ou estender todas as interfaces implementadas pelo decorador.
Este atributo delegado especifica que o decorador está vinculado a todos os Web Beans que implementam Account:
@Decorates Account account;
Um atributo delegado pode especificar uma anotação de binding. Então, o decorador só será vinculado ao Web Beans com o mesmo vínculo.
@Decorates @Foreign Account account;
Um decorador é vinculado a qualquer Web Bean que:
tem o tipo do atributo delegado como um tipo da API, e
tem todos os tipos de vínculo que são declarados pelo atributo delegado.
O decorador pode invocar o atributo delegado, que tem praticamente o mesmo efeito que chamar InvocationContext.proceed() a partir de um interceptador
Nós precisamos habilitar nosso decorador no web-beans.xml.
<Decorators>
<myapp:LargeTransactionDecorator/>
</Decorators
>
Essa declaração tem o mesmo propósito para decoradores que a <Interceptors> tem para os interceptadores:
isso possibilita-nos determinar a ordem total para todos os decoradores em nosso sistema, assegurando um comportamento determinístico
isso permite habilitarmos ou desabilitarmos as classes decoradas em tempo de implantação.
Interceptadores para o método são chamados antes dos decoradores que se aplicam a esse método.