Arthur's Blog
Spring AOP Proxy의 동작방식과 이슈 본문
아래 글에서 "실제 서비스"는 개발자가 직접 작성한 서비스의 코드이고, "Proxy객체"는 Spring이 CGLIB 또는 JDK Proxy를 통해 실제 서비스를 감싼 객체이다.
Service를 작성하게 되면 실행될 때 Proxy객체가 만들어지며 DI받은 Bean의 method를 실행시키면 Proxy객체를 통해서 실제 Service가 호출된다.
public class ProxyUserService {
private final UserService userService;
private final EntityManager em;
public void doTransaction() {
EntityTransaction tx = em.getTransaction()
try {
tx.begin();
userService.doTransaction();
tx.commit();
} catch(Exception e) {
tx.rollback();
}
}
}
public class UserService {
@Transactional
public void doTransaction() {
//doSomething
}
}
하지만, 실제 서비스의 doSomething 메소드에서 같은 서비스 내 @Transactional이 붙어있는 다른 함수를 호출하면 어떻게 될까?
기대 | 실제 |
Proxy객체의 doSomething() 호출 실제 서비스의 doSomething() 호출 tx.begin() 실제 서비스의 doTransaciton() 호출 tx.commit() 반환 |
Proxy객체의 doSomething() 호출 실제 서비스의 doSomething() 호출 실제 서비스의 doTransaction() 호출 반환 |
위 표와 같다. 잘 이해가 되지 않는다면 아래 코드를 보자.
Controller에서 ProxyUserService를 주입받았고, Proxy객체의 doSomething을 호출한다. 하지만, doSomething을 호출하면 실제 서비스 내에서 다른 메소드를 호출하기 때문에 doTransaction은 Transaction이 없이 실행되게 된다.
public class ProxyUserService {
private final UserService userService;
private final EntityManager em;
public void doSomething() {
userService.doSomething();
}
public void doTransaction() {
EntityTransaction tx = em.getTransaction()
try {
tx.begin();
userService.doTransaction();
tx.commit();
} catch(Exception e) {
tx.rollback();
}
}
}
public class UserService {
public void doSomething() {
//doSomething
doTransaction();
}
@Transactional
public void doTransaction() {
//doSomething
}
}
'Backend > Spring Boot' 카테고리의 다른 글
Spotless란? (0) | 2023.07.04 |
---|---|
IoC 컨테이너 (0) | 2023.07.01 |
Spring Bean은 상태를 가져도 되는가? (0) | 2023.07.01 |
List안의 값을 Validation 하는 법 (0) | 2023.07.01 |
Service 구현체를 추상화 하는것에 대해.. (0) | 2023.07.01 |