ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring Transaction aop 의 동작 원리
    카테고리 없음 2023. 4. 20. 09:53
    이번 포스팅은 spring Transaction aop의 동작 원리를 간단하게 한번 살펴 보겠다. 깊게 들어가면 나도 어렵고 보는사람도 어렵고 다시 보는 나도 또 어렵다. 그러니 간단하게 동작 원리만 살펴 보겠다. 일단 @Transactional 어노테이션은 보통 일반적으로 Service 계층에 넣는다. 그리고 Controller에서 Service를 호출한다. facade 계층이 있으면 facade 에서 호출하겠지만 보통은 Controller에서 호출하는게 대부분이다. 그럼 Controller에서 Service를 Autowired받으면 Service 객체에 프록시 객체가 주입된다. (물론 AOP 어노테이션이 있으면) AOP 프록시 객체가 주입되었으면 AOP가 동작한다는 의미다. 필자는 jpa트랜잭션 기준으로 설명한다. org.springframework.transaction.interceptor.TransactionInterceptor 이 spring에서 구현한 AOP 인터셉터다. org.aopalliance.intercept.MethodInterceptor를 구현하고 있다. 더 들어가면 복잡해지니 여기까지만 알아도 될 것같다. 그리고 TransactionInterceptor의 부모 클래스는 TransactionAspectSupport 클래스로 실질적으로 트랜잭션을 담당하기 위한 클래스이다.
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
    
    위의 메서드는 TransactionAspectSupport에 있는 메서드로 트랜잭션 처리를 위한 메스드 시그네쳐이다. 최초 Controller에서 Service로 호출되기 전에 위의 메서드를 호출한다. 여기서 트랜잭션을 시작하고 서비스 계층도 호출하며 트랜잭션도 끝낸다. 또한 JPA 기준으로 JpaTransactionManager(extends AbstractPlatformTransactionManager) 클래스도 호출한다.
    public final TransactionStatus getTransaction(TransactionDefinition definition)
    
    AOP이후 최초(최초라기보다 트랜잭션을 생성할때 최초?) 호출되는 메서드는 위의 메서드로 AbstractPlatformTransactionManager 클래스에 있다. TransactionStatus를 생성해주는 메서드이다, 그럼 어떻게 동작하는지 보자
    retVal = invocation.proceedWithInvocation();
    
    위의 메서드는 실제 메서드를 호출하는 아이다. 저게 호출되면 Service를 호출하게 된다. 그러고 나서 Service계층에서 save, update, delete등 메서드를 호출하게 되면 다시 메서드(invokeWithinTransaction) 를 호출한다. 그럼 처음에 호출 됐던 invokeWithinTransaction이 메서드는 스택에 쌓이게 된다.(재귀호출한다는 것이 맞을듯하다.) 물론 트랜잭션을 시작할때 transactionManager를 캐싱해둔다.
    this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
    
    그래서 있으면 있던 트랜잭션을 사용한다. 말이 쉽지 복잡하다.
    PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier);
    
    그리고 나서 커밋 메서드는 호출은 하지만 실질적인 디비에는 커밋을 날리지 않는다. Service메서드가 끝날 때 첫 번째 호출된 메서드가 스택에서 꺼내진 후에 커밋을 날린다.
    else if (status.isNewTransaction()) {
      if (status.isDebug()) {
        logger.debug("Initiating transaction commit");
      }
      doCommit(status);
    }
    
    AbstractPlatformTransactionManager 클래스의 일부분이다. 처음에는 isNewTransaction이 true 일때 왜 커밋을 할까? 생각했는데 처음에 들어온 함수가 마지막에 나가다보니 그런거 같았다. 위에 보이는 doCommit() 메서드가 실직적으로 커밋을 날리는 메서드이며 추상 메서드이다. Jpa는 JpaTransactionManager 클래스가 구현 되어져 있다.
    EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction();
    tx.commit();
    
    JpaTransactionManager 클래스의 doCommit() 메서드 일부분이다. 많은 부분을 띄엄띄엄 설명을 하긴 했는데 그럴수밖에 없던 이유가 너무 복잡하다. 시간이 되면 조금더 살펴본 후에 간단하게 만들수 있다면 한번 트랜잭션을 만들어 봐야겠다. 워낙 복잡해갖고... 할 수 있을 런지.. 그래도 아주 간단하게 Spring aop transaction이 어떻게 동작 하는지는 알아봤다.

    댓글

Designed by Tistory.