5.5.7 AOP 스키마 예제 by sh

5.5.7. AOP 스키마 예제

이 절에서는 An AOP Example의 동시 잠금 실패 재시도 예제가 스키마 지원으로 다시 작성 될 때 어떻게 표시되는지 보여줍니다.

비즈니스 서비스의 실행은 동시성 문제 (예 : 교착 상태 실패자)로 인해 때때로 실패 할 수 있습니다. 작업이 다시 시도되면 다음 시도에서 성공할 수 있습니다. 그러한 조건 (충돌 해결을 위해 사용자에게 다시 돌아갈 필요가없는 멱등 원 (itempotent) 작업)에서 다시 시도하는 것이 적합한 비즈니스 서비스의 경우 클라이언트가 PessimisticLockingFailureException을 보지 않도록 작업을 투명하게 다시 시도해야 합니다. 이는 서비스 계층의 여러 서비스를 명확히 차단하는 요구 사항이므로 aspect 통한 구현에 이상적입니다.

proceed를 여러 번 호출 할 수 있도록 around advice을 사용해야합니다. 다음 목록은 기본 aspect 구현 (스키마 지원을 사용하는 일반적인 Java 클래스)을 보여줍니다.

public class ConcurrentOperationExecutor implements Ordered {

    private static final int DEFAULT_MAX_RETRIES = 2;

    private int maxRetries = DEFAULT_MAX_RETRIES;
    private int order = 1;

    public void setMaxRetries(int maxRetries) {
        this.maxRetries = maxRetries;
    }

    public int getOrder() {
        return this.order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
        int numAttempts = 0;
        PessimisticLockingFailureException lockFailureException;
        do {
            numAttempts++;
            try {
                return pjp.proceed();
            }
            catch(PessimisticLockingFailureException ex) {
                lockFailureException = ex;
            }
        } while(numAttempts <= this.maxRetries);
        throw lockFailureException;
    }

}

aspect는 Ordered인터페이스를 구현하여 aspect의 우선 순위를 트랜잭션 advice 보다 높게 설정할 수 있습니다 (우리는 재 시도 할 때마다 새로운 트랜잭션을 원합니다). maxRetriesorder속성은 모두 스프링에 의해 구성됩니다. 주요 동작은 doConcurrentOperationaround advice 메소드에서 발생합니다. 우리는 계속 하려고합니다. PessimisticLockingFailureException으로 실패하면 재 시도를 모두 마쳤으면 다시 시도합니다.

이 클래스는 @AspectJ 예제에서 사용 된 것과 동일하지만 Annotation이 제거 된 클래스입니다.

해당 스프링 설정은 다음과 같습니다.

<aop:config>

    <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">

        <aop:pointcut id="idempotentOperation"
            expression="execution(* com.xyz.myapp.service.*.*(..))"/>

        <aop:around
            pointcut-ref="idempotentOperation"
            method="doConcurrentOperation"/>

    </aop:aspect>

</aop:config>

<bean id="concurrentOperationExecutor"
    class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
        <property name="maxRetries" value="3"/>
        <property name="order" value="100"/>
</bean>

당분간은 모든 비즈니스 서비스가 멱등수라고 가정합니다. 그렇지 않은 경우 다음 예처럼 Idempotent주석을 도입하고 주석을 사용하여 서비스 작업 구현에 주석을 추가하여 진정으로 멱등 원 작업만 재 시도하도록 aspect를 조정할 수 있습니다.

@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
    // marker annotation
}

aspect에 대한 멱등 원 작업만을 재 시도하는 것은 다음과 같이 @Idempotent 연산 만 일치하도록 pointcut 표현식을 수정하는 작업을 포함합니다.

<aop:pointcut id="idempotentOperation"
        expression="execution(* com.xyz.myapp.service.*.*(..)) and
        @annotation(com.xyz.myapp.service.Idempotent)"/>

Last updated