Spring @Transactional is applied both as a dynamic Jdk proxy and an aspectj aspect
I am in the process of adding Spring declarative transactions via the @Transactional annotation to an existing Java project.
When I ran into a problem (unrelated to this question), I turned on full debug logging. Curiously, I noticed the following:
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 transaction开发者_StackOverflow社区al 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
After some debugging, I found out that the first three log entries, where it says it found a thread-bound session and is using that transaction, is produced by a JdkDynamicAopProxy on my UserService class.
The last log message looks alarming though. It is invoked at a joinpoint before the method execution. When looking at the source for AnnotationTransactionAspect, it produces this message if no transaction manager has been set. In this case, because Spring never performs any dependency injection on this aspect.
It looks to me like two different "styles" of transactions are both applied: the dynamic proxy, AND the aspect. The only transaction-related configuration I have is:
<tx:annotation-driven transaction-manager="txManager" />
We are using AspectJ in the project, but there is no AnnotationTransactionAspect aspect registered in my aop.xml. We are using Spring 3.0.2.RELEASE.
Should I be alarmed by this? Does Spring register this aspect for me? Should I not use annotation-driven
when using AspectJ?
Strange, it sounds like you have this configuration:
<tx:annotation-driven
transaction-manager="transactionManager" mode="aspectj" />
(Transaction support using AspectJ, not JDK proxies)
Since your config doesn't have a mode attribute, the default should kick in (proxy mode). But AnnotationTransactionAspect is the exact aspect used by the aspectj mode.
To get aspectj transactions working with 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;
}
}
If you are using 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>
If you are using eclipse, this will ensure that the weaving is done when deploying inside eclipse:
http://www.eclipse.org/ajdt/
精彩评论