# 5.5.7 AOP 스키마 예제 by sh

### **5.5.7. AOP 스키마 예제**

이 절에서는 [An AOP Example](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-ataspectj-example)의 동시 잠금 실패 재시도 예제가 스키마 지원으로 다시 작성 될 때 어떻게 표시되는지 보여줍니다.&#x20;

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

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

```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 보다 높게 설정할 수 있습니다 (우리는 재 시도 할 때마다 새로운 트랜잭션을 원합니다). `maxRetries`및 `order`속성은 모두 스프링에 의해 구성됩니다. 주요 동작은 `doConcurrentOperation`around advice 메소드에서 발생합니다. 우리는 계속 하려고합니다. `PessimisticLockingFailureException`으로 실패하면 재 시도를 모두 마쳤으면 다시 시도합니다.&#x20;

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

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

```markup
<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를 조정할 수 있습니다.&#x20;

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

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wannaqueen.gitbook.io/spring5/spring-5.0/5-spring-aspect/5.5/5.5.7-by-sh.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
