(loop (print (eval (read))))

;;닭집을 차리기 위한 여정

트랜잭션과 aspectj

유일하게 쓸만한..

그동안 쭉 cglib 프록시를 썼었다. 아무래도 cglib의 프록시 방식이 substance를 만드는 방식이다보니,
내부 메서드 호출에 대해서도 잘 감싸주겠지 생각했었는데 알아보고 실험해보니 jdk프록시와 다를바없이 동작하더라는..

예를들어 간단히 이런 코드를 돌려보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Service
public class FooService {
@Inject
PostMapper postMapper;
@Inject
UserMapper userMapper;
@Transactional(propagation = Propagation.REQUIRED)
public void insertFoo(User user, Post post) {
userMapper.insert(user);
insertBar(post);
throw new RuntimeException("fucking fucked!!");
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertBar(Post post) {
postMapper.insert(post);
}
}

예상과는 다르게 postMapper.insert(post) 마저 롤백되어 버린다.
실제로 브레이크 포인트를 걸어가며 디버깅해보면 프록시를 통하지 않고 다이렉트로 직접 호출하고 있다.
substance인데 왜 ㅅㅂ 존나 노이해..

결국 유일하게 쓸만한 솔루션은 그냥 닥치고 AspectJ 라는 거다. AspectJ 를 쓰면 아무런 문제가 생기지 않는다.
(혹은 cglib을 고쳐서 쓰거나…)

이렇게 동작하는것만 보장되면 구차하게 계속 서비스를 안 쪼개도 되고 템플릿 패턴을 쓸 수 있게된다.
생각해보면 컨트롤러와 서비스의 계층을 확실하게 나누는데도 도움이 된다. 예를들어 일반적인 처리는 컨트롤러에서, 특정 프로세스가 2회 이상 반복되는 경우에 템플릿 서비스로 계층화를 시키는게 가능하다. 이러면 소스를 줄이는데도 크게 도움이되고, 서비스== 템플릿 이므로 어떤 서비스가 어디서 호출되는지 고민할 필요도 없어진다.