스프링/6. 스프링 DB-2

43. 트랜잭션 AOP 주의사항 2 -프록시 내부호출

sdafdq 2023. 10. 15. 12:36

스프링 트랜잭션 AOP기능은 public 메소드만 적용 됨.

 

그리고 이건 실무에서도 쓰는 방법중 하나인데, @Transactional 없는 메소드 -> @Transactional 있는 메소드 이런 식 일시,

@Slf4j
@SpringBootTest
public class InternalCallV2Test {

    @Autowired
    CallService callService;

    @Test
    void printProxy(){
        log.info("callService class={}", callService.getClass());
    }

    @Test
    void externalCallV2(){
        callService.external();
    }

    @TestConfiguration
    static class InternalCallV1TestConfig{
        @Bean
        CallService callService(){
            return new CallService(internalService());
        }

        @Bean
        InternalService internalService(){return new InternalService();}
    }

    static class InternalService{
        @Transactional
        public void internal(){
            log.info("call internal");
            printTxInfo();
        }

        private void printTxInfo(){
            boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("tx active = {}", txActive);
            boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
            log.info("tx readOnly={}", readOnly);
        }
    }

    @RequiredArgsConstructor
    static class CallService{
        private final InternalService internalService;
        public void external(){
            log.info("call external");
            internalService.internal();
        }

        @Transactional
        public void internal(){
            log.info("call internal");
            printTxInfo();
        }

        private void printTxInfo(){
            boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
            log.info("tx active = {}", txActive);
            boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
            log.info("tx readOnly={}", readOnly);
        }
    }
}

아예 이렇게 클래스를 나눠 놓기도 함.

 

왜 프록시가 외부에서 호출 들어온 상태로 프록시에 대한 명령?(@Transactional 등)이 있으면 그 상태로 쭈욱 가니까

아예 프록시 새로 만들어서 그러니까 프록시용? 프록시용들만 따로 모아놓은?

그런 클래스 아예 따로 만들어서 그런 식으로 호출하게끔.

 

예를 들면 뭐 TxService 이런 걸 추가로 만드는 거임.

주는 Service이고.

 

static class InternalService{
    @Transactional
    public void internal(){
        log.info("call internal");
        printTxInfo();
    }

    private void printTxInfo(){
        boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
        log.info("tx active = {}", txActive);
        boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
        log.info("tx readOnly={}", readOnly);
    }
}

이렇게. printTxInfo는 private니 그냥 넘어가고,

여기다 TxService 등으로 이름 붙여 @Transactional인거 모아 두든지, 아니면 @Transaction 없는 거 -> @Transactional 있는 거 이런 형태의 @Transactional 붙는 거만 따로 모아서 클래스를 만들 든.