2014-04-29 3 views
0

다음 코드의 newPrint 메서드는 새 트랜잭션을 만들어야하지만 분명히 oldPrint 메서드에서 사용 된 것과 동일한 트랜잭션 상태 개체를 출력합니다. oldPrint를 다른 클래스에서 호출하려고합니다. newPrint가 this을 사용하여 호출 되었기 때문입니까? 그렇다면 새로운 거래가 언제 만들어 집니까? @Transactional이 클래스 수준에서 사용되기 때문에 다른 클래스의 두 메서드를 모두 호출하면 별도의 두 트랜잭션이 만들어집니다.스프링 전파 .REQUIRES_NEW

@Transactional 
public class Unsubcriber { 


    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
    public void newPrint() { 
     System.out.println(TransactionAspectSupport.currentTransactionStatus()); 
    } 

    public void oldPrint() { 

     System.out.println(TransactionAspectSupport.currentTransactionStatus()); 
     newPrint(); 
    } 

출력 : Propagation.REQUIRES_NEW이 작동 할 때

o[email protected]3bacd0e7 
o[email protected]3bacd0e7 

어떤 시나리오가 될 것이다?

+0

내부 oldPrint, 당신은'newPrint()'대신()'인쇄'의 의미합니까? – geoand

+0

@geoand 내 나쁜, 그냥 내 질문을 편집했습니다. 감사! – Abidi

+0

내 대답을 확인하십시오 :) – geoand

답변

0

당신이보고있는 것은 Spring AOP에 대한 클래스 오해입니다.

동일한 클래스의 메서드에서 newPrint()이 호출되기 때문에 조언이 트리거되지 않으므로 트랜잭션 처리가 수행되지 않습니다.

newPrint() 메서드를 클래스 외부에서 호출했다면 호출자가 이미 트랜잭션에 참여했는지 여부에 관계없이 새 트랜잭션이 생성됩니다.

클래스에 @Transactional을 사용 했으므로 모든 메소드가 기본 설정 인 @Transactional을 가져 오므로 실제로 트랜잭션이 발생합니다.

Spring에서 AOP가 작동하는 방식에 대한 자세한 내용은 Spring 참조 문서의 this 섹션을 참조하십시오.

((Unsubcriber) AopContext.currentProxy()).newPrint(); 

이 솔루션은 그 중 this SO 게시물입니다 다양한 장소에서 언급 한 : 다음 될 것으로 예상처럼

총 해킹 코드가 작동하세요.

+0

나는 그것을 얻었습니다. 어떻게 전파를 사용할 수 있습니까? REQUIRES_NEW? – Abidi

+0

업데이트 된 답변 확인 – geoand

0

클래스 내에서 (this을 사용하여) 메소드를 호출하면 해당 클래스가 Spring의 프록시 객체에 포함 된 트랜잭션 초기화를 거치지 않는다는 것을 의미합니다. this 키워드는 트랜잭션을 인식하고 향상된 Spring 객체가 아니라 원래 객체의 인스턴스에 대한 포인터이기 때문입니다. 같은 시나리오에서 예상대로

주석은가 작동합니다 geoand의 편집 설명이 참 가정

object1.oldPrint(); 
object1.newPrint(); 
1

, 질문에 대한 대답은 봄이 거래 제한을 적용 AOP 프록시를 사용합니다. 따라서 외부에서 가입자가 들어오는 호출이 들어 오면이를 차단하여 트랜잭션 경계를 적용 할 수 있습니다. 당신이 'this'를 사용하여 말했듯이 클래스 내에서 호출하는 경우, 수행 할 수있는 프록시가 없으므로 @Transactional이 작동하지 않습니다. 여기

1

는 public 메소드 작업 트랜잭션 주석 @

1. 언급 할 가치가 @Transactional의 몇 가지 규칙이 있습니다. 이 주석을 사용하여 개인 또는 보호 된 메소드가있는 경우 Spring AOP에 주석을 표시하는 방법은 없습니다 (쉬운) 입니다. 을 찾으려고 미친 것은 아니므로 주석이 달린 모든 메소드가 공개되어 있는지 확인하십시오.

2. 트랜잭션 경계는 올바르게 주석 된 (위 참조) 메소드가 Spring 프록시를 통해 호출 될 때만 작성됩니다. 즉, @Autowired bean을 통해 주석이 달린 메소드를 직접 호출해야합니다. 그렇지 않으면 트랜잭션이 시작되지 않습니다. 주석이없는 @Autowired bean의 메소드를 호출하는 경우 그 주석 자체는 public 메서드를 호출합니다. 주석이 달린 사용자의 주석은 무시됩니다. 스프링 AOP가 처음 @ @ Autowired 코드를 입력했을 때만 주석을 확인하기 때문입니다.

소스 - http://blog.timmattison.com/archives/2012/04/19/tips-for-debugging-springs-transactional-annotation/