SeamFramework.orgCommunity Documentation
呼叫攔截器(Interceptors)是個用來擷取和區分與型別系統垂直的相關問題的強大方式。任何攔截器皆可攔截任何 Java 類型的調用(invocation)。這使它們適用於解決涉及技術上的問題,例如交易管理和安全性。不過,就一般來講,攔截器並不會知道它們所攔截的事件之實際 語。因此,攔截器並不適合作為一個區分涉及商業問題的工具。意
裝飾器(decorators)則是相反的。裝飾器只會針對於特定 java 介面來攔截調用,因此它知道該介面的所有語意。這使得裝飾器適用於模擬涉及商業上的問題。同時這也代表裝飾器並沒有攔截器的普遍性。裝飾器無法解決涉及多種不同類型的技術問題。
假設我們有個顯示帳號的介面:
public interface Account {
public BigDecimal getBalance();
public User getOwner();
public void withdraw(BigDecimal amount);
public void deposit(BigDecimal amount);
}
我們的系統中會有幾個不同的 Web Bean 實做 Account
介面。不過,我們有個法律上的統一規定需求,那就是不管是任何哪種類型的帳號,大型的交易都必須被系統記錄於一個特殊的日誌中。這是一項適合裝飾器的工作。
裝飾器(decorator)是個單純的 Web Bean,它可實做它所裝飾的類型並且會被標記為 @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) );
}
}
}
和其它單純的 Web Bean 不同的是,裝飾器可能會是個抽象類別(abstract class)。若裝飾器無須為被裝飾之介面的特定 method 進行任何特殊動作的話,您便無須實做該 method。
所有的裝飾器都有個 delegate 屬性。delegate 屬性的類型以及綁定類型可斷定裝飾器應綁定至哪些 Web Bean。delegate 屬性類型必須實做或是延伸裝飾器所實做的所有介面。
下列 delegate 屬性指出裝飾器已綁定至所有實做 Account
的 Web Bean:
@Decorates Account account;
Delegate 屬性可指定一個 binding annotation(綁定註解)。如此一來裝飾器便只會綁定至含有相同 binding 的 Web Bean。
@Decorates @Foreign Account account;
一個裝飾器會綁定至任何符合以下條件的 Web Bean:
擁有一個 API 類型的 delegate 屬性類型,以及
擁有 delegate 屬性所宣告的所有綁定類型。
裝飾器能夠引動 delegate 屬性,這和透過一個攔截器調用 InvocationContext.proceed()
的效果大致相同。