SeamFramework.orgCommunity Documentation

8장. 데코레이터

8.1. 위임 속성
8.2. 데코레이터 활성화

인터셉터는 유형 시스템에 직교 되어 있는 문제를 분리하고 캡쳐하는 강력한 방법입니다. 인터셉터는 모든 Java 유형 호출을 차단할 수 있습니다. 이는 트랜젝션 관리 및 보안과 같은 기술적 문제를 해결하는데 유용합니다. 하지만, 본래 인터셉터는 차단한 이벤트의 실제적 시멘틱을 인식하지 않습니다. 따라서, 인터셉터는 비지니스 관련 문제를 분리하기 위한 도구로는 적합하지 않습니다.

역으로 기능하는 것이 데코레이터입니다. 데코레이터는 특정 Java 인터페이스에 대해서만 호출을 차단하며, 인터페이스에 부착된 모든 시멘틱을 인식합니다. 이는 일부 비지니스 문제를 모델화하기 위해 데코레이터를 완벽한 도구로 만듭니다. 또한 데코레이터는 인터셉터의 일반적 기능을 갖지 않습니다. 데코레이터는 여러 이질적 유형을 초월하는 기술적 문제를 해결할 수 없습니다.

어카운트를 나타내는 인터페이스가 있다고 가정합니다:

public interface Account {

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

시스템에서 여러 다른 Web Beans는 Account 인터페이스를 구현합니다. 하지만, 일반적인 법적 요구조건이 있으며, 모든 종류의 어카운트의 경우, 대용량 트랜젝션은 특정 로그로 시스템에 의해 기록되어야 합니다. 이는 데코레이터의 뛰어난 작업 기능입니다.

데코레이터는 심플 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 Beans와 다르게, 데코레이터는 추상클래스일 수 도 있습니다. 데코레이터된 인터페이스의 특정 방식에 대해 데코레이터가 특별히 해야할 것이 없을 경우, 이 방식을 구현하실 필요가 없습니다.

모든 데코레이터는 위임 속성 기능을 갖습니다. 위임 속성의 유형 및 바인딩 유형은 어떤 Web Beans에 데코레이터를 바운딩할 지를 결정합니다. 위임 속성 유형은 데코레이터에 의해 구현된 모든 인터페이스를 구현 또는 확장해야 합니다.

이러한 위임 속성은 Account를 구현하는 모든 Web Beans로 바인딩하는 데코레이터를 지정합니다.

@Decorates Account account;

위임 속성은 바인딩 어노테이션을 지정할 수 도 있습니다. 그 후 데코레이터는 동일한 바인딩을 사용하여 Web Beans로 바운딩되게 됩니다.

@Decorates @Foreign Account account;

데코레이터는 다음과 같은 사항이 있는 Web Bean으로 바인딩됩니다:

데코레이터는 위임 속성을 호출할 수 있으며, 인터셉터에서 InvocationContext.proceed()를 호출하는 것과 동일한 영향을 미칩니다.

web-beans.xml에서 데코레이터를 활성화해야 합니다.


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

이러한 명시 사항은 데코레이터에 대해 <Interceptors> 명시가 인터셉터에 대해 실행하는 것과 동일한 목적을 실행합니다:

데코레이터를 적용하기 전 해당 방식의 인터셉터를 호출합니다.