복붙노트

[SPRING] Spring @Transactional은 동적 인 Jdk 프록시와 aspectj aspect로 적용된다.

SPRING

Spring @Transactional은 동적 인 Jdk 프록시와 aspectj aspect로 적용된다.

@Transactional 어노테이션을 통해 Spring 선언적 트랜잭션을 기존 Java 프로젝트에 추가하는 과정에있다.

문제 (이 질문과 관련이 없음)를 만났을 때 나는 전체 디버그 로깅을 켰습니다. 흥미롭게도 다음과 같은 사실을 알았습니다.

17:47:27,834 DEBUG HibernateTransactionManager:437 - Found thread-bound Session [org.hibernate.impl.SessionImpl@10ed8a8e] for Hibernate transaction
17:47:27,845 DEBUG HibernateTransactionManager:470 - Participating in existing transaction
17:47:27,865 DEBUG AnnotationTransactionAttributeSource:106 - Adding transactional method 'updateUserProfile' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
17:47:27,875 DEBUG AnnotationTransactionAspect:321 - Skipping transactional joinpoint [se.myservice.UserService.updateUserProfile] because no transaction manager has been configured

일부 디버깅 후, 처음 세 개의 로그 항목 (thread-bound 세션을 발견하고 해당 트랜잭션을 사용하고 있음)이 UserService 클래스의 JdkDynamicAopProxy에 의해 생성된다는 것을 알았습니다.

마지막 로그 메시지가 놀랍게 보입니다. 메서드 실행 전에 joinpoint에서 호출됩니다. AnnotationTransactionAspect의 소스를 보면 트랜잭션 관리자가 설정되지 않은 경우이 메시지가 표시됩니다. 이 경우 Spring은이 측면에 의존성 주입을 수행하지 않기 때문에.

두 가지 다른 "스타일"의 트랜잭션이 적용되는 것처럼 보입니다 : 동적 프록시와 aspect. 내가 가진 유일한 트랜잭션 관련 구성은 다음과 같습니다.

<tx:annotation-driven transaction-manager="txManager" />

우리는 프로젝트에서 AspectJ를 사용하고 있지만, aop.xml에 AnnotationTransactionAspect aspect가 등록되어 있지 않다. 우리는 Spring 3.0.2.RELEASE를 사용하고 있습니다.

나는 이것에 놀랄 것인가? Spring은이 부분을 저에게 등록합니까? AspectJ를 사용할 때 annotation-driven을 사용하지 않을까요?

해결법

  1. ==============================

    1.이상하게도,이 구성이있는 것 같습니다.

    이상하게도,이 구성이있는 것 같습니다.

    <tx:annotation-driven
        transaction-manager="transactionManager" mode="aspectj" />
    

    (JDK 프록시가 아닌 AspectJ를 사용한 트랜잭션 지원)

    config에는 모드 속성이 없으므로 기본값이 시작되어야합니다 (프록시 모드). 그러나 AnnotationTransactionAspect는 aspectj 모드에서 사용되는 정확한 aspect입니다.

  2. ==============================

    2.aspectj 트랜잭션을 java config와 함께 작동 시키려면.

    aspectj 트랜잭션을 java config와 함께 작동 시키려면.

    @EnableWebMvc
    @Configuration
    @ComponentScan("com.yourdomain")
    @EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
    public class ApplicationConfig extends WebMvcConfigurerAdapter {
    
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    
            //...
        }
    
        @Bean
        public JpaTransactionManager transactionManager() {
    
            JpaTransactionManager bean = new JpaTransactionManager(entityManagerFactory().getObject());
            return bean ;
        }
    
        @Bean
        public AnnotationTransactionAspect annotationTransactionAspect() {
    
            AnnotationTransactionAspect bean = AnnotationTransactionAspect.aspectOf();
            bean.setTransactionManager(transactionManager());
            return bean;
        }
    }
    

    당신이 maven을 사용한다면 :

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

    이클립스를 사용하고 있다면, 이렇게하면 이클립스 내부에 배포 할 때 위빙이 완료됩니다.

    http://www.eclipse.org/ajdt/

  3. from https://stackoverflow.com/questions/3573188/spring-transactional-is-applied-both-as-a-dynamic-jdk-proxy-and-an-aspectj-aspe by cc-by-sa and MIT license