SeamFramework.orgCommunity Documentation
Interceptadores 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. Isso os torna ideais para resolver questões técnicas, tais como gerenciamento de transação e segurança. No entanto, por natureza, interceptadores desconhecem a real semântica dos eventos que interceptam. Assim, interceptadores não são um instrumento adequado para a separação de questões relacionadas a negócios.
O contrário é verdadeiro decoradores. O decorador intercepta invocações apenas para uma determinada interface Java e, portanto, é ciente de toda a semântica que acompanha a interface. Isso 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 represente 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). Esse é 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 a qual Web Beans 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:
tenha como tipo do atributo delegado uma API, e
tenha todos os tipos de vínculo que são declarados pelo atributo delegado.
O decorador pode invocar o atributo delegado,o que praticamente equivale a 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.