[java] Spring @Transactional 속성은 개인 메소드에서 작동합니까?

나는이있는 경우 @Transactional Spring 빈에서 개인 방법에 -annotation을, 주석이 어떤 영향이 있습니까?

@Transactional주석이 공용 메소드에있는 경우 주석이 작동하고 트랜잭션을 엽니 다.

public class Bean {
  public void doStuff() {
     doPrivateStuff();
  }
  @Transactional
  private void doPrivateStuff() {

  }
}

...

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();



답변

질문은 비공개 또는 공개가 아니며 질문은 어떻게 호출되며 어떤 AOP 구현을 사용합니까!

(기본) Spring 프록시 AOP를 사용하는 경우 Spring에서 제공하는 모든 AOP 기능 (예 🙂 @Transational은 호출이 프록시를 통과하는 경우에만 고려됩니다. -일반적으로 주석이 달린 메소드가 다른 Bean 에서 호출 된 경우 입니다.

여기에는 두 가지 의미가 있습니다.

  • 개인 메소드는 다른 Bean에서 호출되지 않아야하기 때문에 (예외는 리플렉션 임) @Transactional주석은 고려되지 않습니다.
  • 메소드가 공용이지만 동일한 Bean에서 호출 된 경우이 메소드도 고려되지 않습니다 (이 명령문은 (기본) Spring 프록시 AOP가 사용되는 경우에만 정확함).

@See Spring Reference : Chapter 9.6 9.6 프 락싱 메커니즘

IMHO 문제를 극복 할 Spring 프록시 대신 aspectJ 모드를 사용해야합니다. 그리고 AspectJ Transactional Aspects는 개인적인 방법으로도 짜여져있다 (Spring 3.0에서 확인).


답변

귀하의 질문에 대한 대답은 아니오입니다- @Transactional개인 메소드에 주석을 달 때 사용하면 효과가 없습니다. 프록시 생성기는 무시합니다.

이것은 스프링 매뉴얼 10.5.6 장에 설명되어 있습니다 .

분석법 가시성 @Transactional

프록시 @Transactional를 사용하는 경우 공개 가시성이있는 메소드에만 주석을 적용해야합니다 . 주석이있는 보호 된, 개인용 또는 패키지 표시 가능 메소드에
@Transactional주석을 달면 오류가 발생하지 않지만 주석이 달린 메소드는 구성된 트랜잭션 설정을 표시하지 않습니다. 비공개 메소드에 주석을 달아야하는 경우 AspectJ (아래 참조) 사용을 고려하십시오.


답변

기본적 @Transactional으로이 속성은 applicationContext에서 얻은 참조에 주석이 달린 메소드를 호출 할 때만 작동합니다.

public class Bean {
  public void doStuff() {
    doTransactionStuff();
  }
  @Transactional
  public void doTransactionStuff() {

  }
}

거래가 열립니다 :

Bean bean = (Bean)appContext.getBean("bean");
bean.doTransactionStuff();

이것은하지 않습니다 :

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();

스프링 레퍼런스 : @Transactional 사용

참고 : 프록시 모드 (기본값)에서는 프록시를 통해 들어오는 ‘외부’메소드 호출 만 인터셉트됩니다. 즉, ‘self-invocation’, 즉 대상 객체의 다른 메소드를 호출하는 대상 객체 내의 메소드는 호출 된 메소드에 @Transactional! 가 표시되어 있어도 런타임시 실제 트랜잭션으로 이어지지 않습니다 .

자체 호출이 트랜잭션으로 랩핑 될 것으로 예상되는 경우 AspectJ 모드 (아래 참조)의 사용을 고려하십시오. 이 경우 처음에는 프록시가 없습니다. 대신, @Transactional모든 종류의 메소드에서 런타임 동작으로 전환하기 위해 대상 클래스가 ‘위빙’됩니다 (예 : 바이트 코드가 수정 됨) .


답변

예, 개인 메소드에서 @Transactional을 사용할 수는 있지만 다른 사람들이 언급했듯이 즉시 사용할 수는 없습니다. AspectJ를 사용해야합니다. 작동 방법을 알아내는 데 시간이 걸렸습니다. 결과를 공유하겠습니다.

로드 타임 직조 대신 컴파일 타임 직조를 사용하기로 결정했습니다. 왜냐하면 그것이 전반적으로 더 나은 옵션이라고 생각하기 때문입니다. 또한 Java 8을 사용하고 있으므로 일부 매개 변수를 조정해야 할 수도 있습니다.

먼저 aspectjrt에 대한 종속성을 추가하십시오.

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.8</version>
</dependency>

그런 다음 AspectJ 플러그인을 추가하여 Maven에서 실제 바이트 코드 직조를 수행하십시오 (최소한의 예는 아님).

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.8</version>
    <configuration>
        <complianceLevel>1.8</complianceLevel>
        <source>1.8</source>
        <target>1.8</target>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

마지막으로 이것을 구성 클래스에 추가하십시오.

@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)

이제 개인 메소드에서 @Transactional을 사용할 수 있습니다.

이 접근 방식의 한 가지주의 사항 : Eclipse를 통해 앱을 실행하는 경우 작동하지 않을 수있는 경우 AspectJ를 인식하도록 IDE를 구성해야합니다. 위생 검사로 직접 Maven 빌드에 대해 테스트하십시오.


답변

트랜잭션 내부에 전용 메소드를 랩핑해야하고 aspectj를 사용하지 않으려는 경우 TransactionTemplate 을 사용할 수 있습니다 .

@Service
public class MyService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    private void process(){
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                processInTransaction();
            }
        });

    }

    private void processInTransaction(){
        //...
    }

}


답변

Spring Docs는 다음과 같이 설명합니다.

프록시 모드 (기본값)에서는 프록시를 통해 들어오는 외부 메소드 호출 만 인터셉트됩니다. 즉, 호출 된 메소드에 @Transactional이 표시되어 있어도 실제로 자체 호출은 대상 오브젝트의 다른 메소드를 호출하는 대상 오브젝트 내의 메소드가 런타임시 실제 트랜잭션으로 이어지지 않음을 의미합니다.

자체 호출도 트랜잭션으로 랩핑되도록하려면 AspectJ 모드 (아래 표의 모드 속성 참조)를 사용하십시오. 이 경우 처음에는 프록시가 없습니다. 대신 @Transactional을 모든 종류의 메소드에서 런타임 동작으로 변환하기 위해 대상 클래스가 직조됩니다 (즉, 바이트 코드가 수정 됨).

다른 방법은 사용자 BeanSelfAware입니다.


답변

내 대답은 아니오 야. Spring Reference : @Transactional 사용하기를 참조 하십시오
.

@Transactional주석은 인터페이스, 클래스 정의, 또는에, 인터페이스 정의하기 전에 방법을 배치 할 수있다 공공 클래스의 방법