문제

메소드에 주석을 달 때 실제로 무슨 일이 일어나는지 알고 싶습니다. @Transactional? 물론, 나는 봄이 트랜잭션에서 그 방법을 포장 할 것이라는 것을 알고 있습니다.

그러나 나는 다음과 같은 의심을 가지고 있습니다.

  1. 나는 봄이 a를 창조한다고 들었습니다 프록시 클래스? 누군가 이것을 더 자세히 설명 할 수 있습니까? 깊이. 그 프록시 클래스에서 실제로 무엇이 상주 하는가? 실제 수업은 어떻게됩니까? 그리고 Spring의 생성 된 프록스 클래스를 어떻게 볼 수 있습니까?
  2. 나는 또한 봄 문서에서 다음을 읽었습니다.

참고 :이 메커니즘은 프록시를 기반으로하기 때문에 프록시를 통해 들어오는 '외부'메소드 호출 만 차단됩니다.. 즉, 대상 객체의 다른 방법을 호출하는 대상 개체 내의 방법 인 'self-invocation'은 호출 된 메소드가 @Transactional!

원천: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

외부 메소드 호출만이 자체 투여 방법이 아닌 트랜잭션하에있는 이유는 무엇입니까?

도움이 되었습니까?

해결책

이것은 큰 주제입니다. Spring Reference Doc은 여러 장을 헌신합니다. 나는 그것을 읽는 것이 좋습니다 측면 지향 프로그래밍 그리고 업무, Spring의 선언적 거래 지원은 재단에서 AOP를 사용합니다.

그러나 매우 높은 수준에서 Spring은 선언하는 클래스에 대한 프록시를 만듭니다. @transactional 수업 자체 또는 회원에. 프록시는 대부분 런타임에 보이지 않습니다. 그것은 스프링이 프록시가있는 객체에 메소드 호출 전, 후 또는 주변에 동작을 주입하는 방법을 제공합니다. 거래 관리는 연결될 수있는 동작의 한 예일뿐입니다. 보안 점검은 또 다른 것입니다. 그리고 당신은 로깅과 같은 것들을 위해 자신의 것도 제공 할 수 있습니다. 따라서 메소드에 주석을 달 때 @transactional, 스프링은 주석을 달고있는 클래스와 동일한 인터페이스를 구현하는 프록시를 동적으로 생성합니다. 고객이 귀하의 객체에 전화를 걸 때, 호출은 가로 채고 프록시 메커니즘을 통해 동작이 주입됩니다.

그건 그렇고 EJB의 거래는 비슷하게 작동합니다.

당신이 관찰했듯이, 프록시 메커니즘은 호출이 외부 객체에서 들어올 때만 작동합니다. 객체 내에서 내부 호출을 할 때, 당신은 실제로 "이것"대리를 우회하는 참조. 그러나 그 문제를 해결하는 방법이 있습니다. 나는 한 가지 접근법을 설명합니다. 이 포럼 게시물 내가 사용하는 a BeanFactoryPostProcessor 프록시 인스턴스를 런타임에 "자체 참조"클래스에 주입합니다. 이 참조는 "라는 멤버 변수에 대한 저장" "". 그러면 스레드의 거래 상태를 변경 해야하는 내부 호출을 해야하는 경우 프록시를 통해 호출을 지시합니다 (예 :"me.somemethod ()".) 포럼 게시물은 더 자세히 설명합니다. BeanFactoryPostProcessor Spring 1.X TimeFrame에 다시 작성된 코드는 이제 약간 다릅니다. 그러나 바라건대 그것은 당신에게 아이디어를 제공합니다. 아마 사용할 수있는 업데이트 버전이 있습니다.

다른 팁

스프링이 Bean 정의를로드하고 @transactional 주석을 찾도록 구성되면 실제 Bean 주위에 이러한 프록시 객체를 생성합니다. 이 프록시 객체는 런타임에 자동 생성 된 클래스의 인스턴스입니다. 메소드가 호출 될 때 이러한 프록시 오브젝트의 기본 동작은 "대상"Bean (즉, Bean)에서 동일한 메소드를 호출하는 것입니다.

그러나 프록시는 인터셉터와 함께 제공 될 수 있으며,이 인터셉터는 대상 Bean의 방법을 호출하기 전에 프록시에 의해 호출됩니다. @Transactional과 주석이 달린 대상 Bean의 경우 Spring은 TransactionInterceptor를 생성하여 생성 된 프록시 객체로 전달합니다. 따라서 클라이언트 코드에서 메소드를 호출 할 때 프록시 객체의 메소드를 호출하는데, 이는 먼저 트랜잭션 interceptor (트랜잭션을 시작하는)를 호출하여 대상 Bean의 메소드를 호출합니다. 호출이 완료되면 TransactionInterceptor가 트랜잭션을 추천/롤백합니다. 클라이언트 코드에 투명합니다.

"외부 방법"에 관해서는, 콩이 자체 방법 중 하나를 호출하면 프록시를 통해 그렇게하지 않을 것입니다. 스프링은 프록시에 콩을 감싸고 콩은 알지 못합니다. "외부"에서만 전화를 걸어 대리를 통과합니다.

그게 도움이 되나요?

시각적 인 사람으로서, 나는 프록시 패턴의 시퀀스 다이어그램으로 무게를 측정하는 것을 좋아합니다. 화살표를 읽는 방법을 모른다면, 나는 다음과 같은 첫 번째 것을 읽습니다. Client 실행 Proxy.method().

  1. 클라이언트는 자신의 관점에서 대상에 대한 방법을 호출하고 대리인에 의해 조용히 가로 채 웁니다.
  2. 이전 측면이 정의되면 프록시가 실행됩니다.
  3. 그런 다음 실제 방법 (대상)이 실행됩니다.
  4. 회복 후 및 던지기 후 방법은 메소드가 반환 된 후 실행되고/또는 메소드가 예외를 던지는 경우 선택적 측면입니다.
  5. 그 후 프록시는 후 측면을 실행합니다 (정의 된 경우)
  6. 마지막으로 프록시는 호출 클라이언트로 돌아갑니다

Proxy Pattern Sequence Diagram(나는 그 기원을 언급 한 조건에서 사진을 게시 할 수있었습니다. 저자 : Noel Vaes, 웹 사이트 : www.noelvaes.eu)

가장 간단한 대답은 @Transactional을 선언하는 방법에서 트랜잭션 경계가 시작되고 메소드가 완료되면 경계가 종료됩니다.

JPA 호출을 사용하는 경우이 트랜잭션 경계에서 모든 커밋이 있습니다. Entity1, Entity2 및 Entity3을 저장한다고 가정 해 봅시다. Enitiy1과 Entity2가 동일한 트랜잭션에 들어 오므로 ENTITY1 및 ENTITY2가 ENTITY3과 함께 롤백됩니다.

트랜잭션 : (ENTITY1.SAVE, ENTITY2.SAVE, ENTITY3.SAVE). 모든 예외는 DB와의 모든 JPA 트랜잭션이 롤백됩니다. 내부적으로 JPA 트랜잭션은 Spring에서 사용됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top