UserServiceTx 를 다이내믹 프록시 방식으로 변경해보자.

현재 상태에서 고쳐야 할 점

다이내믹 프록시와 연동해서 트랜잭션 기능을 부가하도록 InvocationHandler 를 구현하자

트랜잭션 InvocationHandler

다이내믹 프록시를 위한 트랜잭션 부가기능을 갖는 객체를 구현하자.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public class TransactionHandler implements InvocationHandler {

  private Object target;

  private PlatformTransactionManager transactionManager;
  private String pattern;
  
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if(method.getName().startsWith(pattern)){
      return invokeInTransaction(method, args);
    }else return method.invoke(target, args);
  }
  
  private Object invokeInTransaction(Method method, Object[] args) throws Throwable{
    TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
    try{
      Object ret = method.invoke(target, args);
      this.transactionManager.commit(status);
      return ret;
    } catch(InvocationTargetException e){
      this.transactionManager.rollback(status);
      throw e.getTargetException();
    }
  }

  public void setTarget(Object target) {
    this.target = target;
  }

  public void setTransactionManager(
      PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
  }

  public void setPattern(String pattern) {
    this.pattern = pattern;
  }
}

InvocationHandler 의 invoke() 메서드

UserServiceTx 와 다이내믹 프록시에서 비교

Method.invoke()