SeamFramework.orgCommunity Documentation

Kapitel 8. Dekoratoren

8.1. "Delegate" Attribute
8.2. Aktivierung von Dekoratoren

Interzeptoren bieten eine leistungsfähige Weise, Probleme, die orthogonal zum Typensystem sind, festzuhalten und zu trennen. Jeder Interzeptor kann Aufrufe jedes Java Typs abfangen. Dies macht ihn perfekt für die Lösung technischer Probleme wie etwa Transaktionsmanagement und Sicherheit.Jedoch sind Interzeptoren ihrem Wesen nach nicht der tatsächlichen Semantik der Ereignisse gewahr, die sie abfangen. Interzeptoren sind daher nicht die geeigneten Tools zur Separierung von unternehmensbezogenen Problemen.

Das Gegenteil gilt für Dekoratoren. Ein Dekorator fängt Aufrufe nur für ein bestimmtes Java-Interface ab und kennt daher die zu diesem Interface gehörende Semantik. Dadurch sind Dekoratoren das perfekte Tool zur Bearbeitung einige unternehmensbezogener Probleme. Es bedeutet auch, dass Dekoratoren nicht diesselbe Allgemeingültigkeit wie Interzeptoren besitzen. Dekoratoren können keine technischen Probleme lösen, die sich über viele disparate Typen verteilen.

Nehmen wir an, wir besitzen ein Konten repräsentierendes Interface:

public interface Account {

    public BigDecimal getBalance();
    public User getOwner();
    public void withdraw(BigDecimal amount);
    public void deposit(BigDecimal amount);
}

Mehrere verschiedene Web Beans in unserem System implementieren das Account-Interface. Es existiert allerdings eine gängige legale Voraussetzung die besagt, dass für jede Art von Konto, große Transaktionen vom System in einem besonderen Protokoll gespeichert werden müssen. Dies ist die perfekte Aufgabe für einen Dekorator.

Ein Dekorator ist ein einfaches Web Bean, das den Typ das es dekoriert implementiert und @Decorator annotiert ist.

@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) );
        }
    }
    
}

Anders als andere einfache Web Beans, kann ein Dekorator eine abstrakte Klasse sein. Falls es nichts besonderes ist, dass der Dekorator für eine bestimmte Methode des dekorierten Interface tun muss, so brauchen Sie diese Methode nicht zu implementieren.

Alle Dekoratoren besitzen ein "Delegate" Attribut. Typ und Binding-Typen des "Delegate" Attribut bestimmen, an welche Web Beans der Dekorator gebunden wird. Der Typ des "Delegate" Attributs muss alle vom Dekorator implementierten Interfaces implementieren oder erweitern.

Dieses "Delegate" Attribut legt fest, dass der Dekorator an alle Account implementierenden Web Beans gebunden wird:

@Decorates Account account;

Ein "Delegate" Attribut kann eine Binding-Annotation festlegen. Dann wird der Dekorator nur an Web Beans mit demselben Binding gebunden.

@Decorates @Foreign Account account;

Ein Dekorator wird an ein beliebiges Web Bean gebunden, das:

Der Dekorator kann das "Delegate" Attribut aufrufen, was eine sehr ähnliche Wirkung wie der Aufruf von InvocationContext.proceed() von einem Interzeptor hat.

Wir müssen unseren Dekorator in web-beans.xml aktivieren.


<Decorators>
    <myapp:LargeTransactionDecorator/>
</Decorators
>

Diese Deklaration dient demselben Zweck für Dekoratoren, den die<Interceptors>-Deklaration für Interzeptoren erfüllt:

Interzeptoren für eine Methode werden aufgerufen vor den Dekoratoren an dieser Methode angewendet werden.