[SPRING] Spring의 @Transactional이 보호 된 메소드에서 작동하지 않는 이유는 무엇입니까?
SPRINGSpring의 @Transactional이 보호 된 메소드에서 작동하지 않는 이유는 무엇입니까?
Spring @Transactional 속성은 개인 메소드에서 작동합니까?
개인 및 패키지 개인 메서드를 제외 해야하는 이유를 생각할 수 있지만 보호 된 메서드가 트랜잭션 방식으로 작동하지 않는 이유는 무엇입니까? 다음 스택 추적은 공용 메소드에 대한 올바른 동작을 표시합니다 (인터페이스 프록시를 통해 호출 됨).
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at com.sun.proxy.$Proxy145.improveType(Unknown Source) ~[na:na]
비 인터페이스 CGLIB 프록시를 통해 "동일한"보호 된 메소드를 호출하면 다음과 같은 결과가 나타납니다.
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at my.company.webservices.facade.EntityFacade$$EnhancerBySpringCGLIB$$fd77735b.findEntity(<generated>) ~[spring-core-4.2.1.RELEASE.jar:na]
이것은 분명히 디자인 결정 (왜?)이지만, 개발자 오류 일 때 자동으로 실패한다고 의심합니다.
편집하다 이것은 인터페이스를 사용할 때 분명히 문제가되지 않지만 (인터페이스의 공용 메소드 만) Spring은 CGLIB를 통해 객체를 프록시하는 인터페이스가 반드시 필요하지 않으므로 protected @Transactional 메소드를 호출하면 공용 메소드처럼 작동합니다 (예 : 의도적으로 트랜잭션을 무시한다는 점을 제외하고는 프록시를 통해).
해결법
-
==============================
1.이것 때문에:
이것 때문에:
이:
Spring 사람들은 아마도 JDK 프록시와 일관성을 유지하기를 원할 것입니다. JDK와 CGLIB를 기반으로 다른 프록시 구성과 다른 결과를 원치 않을 것입니다.
-
==============================
2.다른 답변에 대한 추가 정보.
다른 답변에 대한 추가 정보.
다음은 Spring 블로그의 예제 사진입니다.
보시다시피 프록시는 구현 클래스 (여기서는 AccountServiceImpl)를 감싸고 프록시 자체는 AccountService 인터페이스의 메소드 만 구현합니다. 인터페이스는 공용 메소드 (공용 계약) 만 제공하므로 프록시는 보호 된 메소드를 랩핑 할 수 없으며 공용 메소드에서 제공하는 트랜잭션 동작을 제공 할 수 없습니다.
AspectJ를 사용하는 경우 동일한 서비스에서 메소드를 호출하는 것이 가능하지만 지금까지 사용하지 않았기 때문에 이것이 보호 된 메소드에도 해당되는지 확실하지 않습니다.
-
==============================
3.보호 된 방법은 공개 계약의 일부가 아닙니다. 이것이 프록시되지 않은 이유입니다. 대부분의 경우 소비자에게 보이지 않습니다.
보호 된 방법은 공개 계약의 일부가 아닙니다. 이것이 프록시되지 않은 이유입니다. 대부분의 경우 소비자에게 보이지 않습니다.
a) IF로 연결하고 구체적인 구현으로 캐스팅 (나쁜) 또는 b) 구체적인 구현으로 연결하고 소비자가 동일한 패키지에있는 경우 보호 된 메소드를 호출 할 수 있습니다. b) 만 이해하는 것처럼 Spring이 왜 보호 된 메소드를 프록시하지 않는지 알 수 있습니다. 드문 경우이며 JDK 프록시가 아닌 CGLIB에서만 작동합니다.
빈을 확장하고 super.myProtectedMethod ()를 호출하는 유스 케이스에 대해 궁금 할 수도 있습니다. 이러한 호출은 액세스 수준에 관계없이 전혀 프록시되지 않습니다.
from https://stackoverflow.com/questions/34197964/why-doesnt-springs-transactional-work-on-protected-methods by cc-by-sa and MIT license