ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring @Transactional aop 구현해보기
    카테고리 없음 2023. 4. 20. 09:52
    말이 거창하지 실제 Transactional 을 구현하는건 아니다. @Transactional 대충 어떻게 동작하는지 알아보기 위해 aop 를 구현하는 것이다. 실질적으로 Transactional을 구현하는건 아니다. Transaction이라는 어노테이션이 달린 메서드는 aop 를 동작한다고 해보겠다.
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Inherited
    @Documented
    public @interface Transaction {
    }
    
    그리고나서 AOP 동작을 위해 MethodInterceptor 구현해야된다. 실제 여기서 트랜잭션 시작과 끝을 구현하면된다.
    public class TransactionInterceptor implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Transaction start");
            Object proceed = invocation.proceed();
            System.out.println("Transaction end");
            return proceed;
        }
    }
    
    
    그리고나서 우리는 동적으로 포인트컷을 만들 필요가 없기 때문에 StaticMethodMatcherPointcut 를 구현하면된다.
    public class TransactionPointcut extends StaticMethodMatcherPointcut {
    
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            return method.isAnnotationPresent(Transaction.class);
        }
    }
    
    마지막으로 설정 할 것이 있는데 해당 포인트컷과 우리가 실행 시킬 메스드(TransactionInterceptor) 를 매칭 시켜야 된다. 그러기 위해서 AbstractPointcutAdvisor를 구현하자. 실질적으로 구현할 것도 없이 우리가 만든 interceptor와 pointcut 인스턴스만 넘겨주면 된다.
    public class TransactionPointcutAdvisor extends AbstractPointcutAdvisor implements Serializable {
    
        private final TransactionPointcut pointcut = new TransactionPointcut();
    
        private TransactionInterceptor interceptor;
    
        public TransactionPointcutAdvisor(TransactionInterceptor interceptor) {
            this.interceptor = interceptor;
        }
    
        @Override
        public Advice getAdvice() {
            return this.interceptor;
        }
    
        @Override
        public Pointcut getPointcut() {
            return this.pointcut;
        }
    }
    
    그리고 나서 동작시킬 Service 클래스를 두개 만들어보자
    @Service
    public class AopService {
    
        @Transaction
        public String service(){
            return "aop";
        }
    }
    
    @Service
    public class NoAopService {
    
        public String service() {
            return "noAop";
        }
    }
    
    
    한개는 AOP가 적용되야 되는 메서드이고 다른한개 클래스는 AOP 없는 메서드이다.
    @Autowired
    private AopService aopService;
    
    @Autowired
    private NoAopService noAopService;
    
    @Test
    public void test() {
        logger.info("aopService : {}", aopService.getClass());
        logger.info("noAopService : {}", noAopService.getClass());
    }
    
    실행을 해보면 다음고 같은 로그가 남을 것이다.
    2016-05-13 17:06:35.455  INFO 4504 --- [           main] me.wonwoo.SpringLogTestApplicationTests  : aopService : class me.wonwoo.service.AopService$$EnhancerBySpringCGLIB$$a322247b
    2016-05-13 17:06:35.456  INFO 4504 --- [           main] me.wonwoo.SpringLogTestApplicationTests  : noAopService : class me.wonwoo.service.NoAopService
    
    AopService는 프록시 객체가 주입되었다. 하지만 다른 한개는 일반 객체가 주입되었다. 실제로 AopService의 service를 호출하면 Transaction start 와 Transaction end가 찍히는걸 볼수 있다. 이것으로 간단하게 @Transactional aop를 구현해봤다.

    댓글

Designed by Tistory.