如果@transactional应用于类级别,我想捕捉它的参数。
例如,如果@transactional
应用于方法级别,例如:-
class A {
@transactional(readOnly= true)
public void someMethod(){
// some code...
}
}
然后我能够拦截并捕获正式参数,即仅使用此代码读取,例如:-
@Aspect
@Component
@Order(0)
public class ReadOnlyRouteInterceptor {
private static final Logger logger = LoggerFactory.getLogger(ReadOnlyRouteInterceptor.class);
@Around("@annotation(transactional)")
public Object proceed(ProceedingJoinPoint proceedingJoinPoint, Transactional transactional) {
if (transactional.readOnly())
//do something
}
但是,如果@事务性
在类级别应用,则上述代码将不起作用:-
@transactional(readOnly= true)
class A {
public void someMethod(){
// some code...
}
}
现在为了拦截应用于类级别的@transactional
注释,我有以下代码:-
@Pointcut("@within(org.springframework.transaction.annotation.Transactional *)")
public void beanAnnotatedWithTransactional() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithTransactional()")
public void publicMethodInsideAClassMarkedWithATransactional() {}
我这里的实际问题是,如果在类级别应用@transactional
,我无法检查readOnly标志的值。
对于类型级别注释:
@Around("@within(transactional)")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
boolean readOnly = transactional.readOnly();
...
return pjp.proceed();
}
对于方法级注释:
@Around("execution(public * *(..)) && @annotation(org.springframework.transaction.annotation.Transactional)")
public Object myMethod(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
Transactional annotation = method.getAnnotation(org.springframework.transaction.annotation.Transactional.class);
boolean value = annotation. readOnly();
...
return pjp.proceed();
}
方法级别的另一个(更干净)选项:
@Around("@annotation(transactional)")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
}
或者
对tager有更多的控制:
@Around("execution(@org.springframework.transaction.annotation.Transactional public * *(..)) && @annotation("transactional")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
}
您可以使用TransactionSynchronizationManager获取对事务详细信息的引用。
以下代码提供了当前活动事务的只读细节。
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Component
@Aspect
public class TestTransactionalAspect {
@Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
public void beanAnnotatedWithTransactional() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Around("publicMethod() && beanAnnotatedWithTransactional()")
public void publicMethodInsideAClassMarkedWithATransactional(ProceedingJoinPoint pjp) {
try {
System.out.println("Intercepted "+pjp.toShortString());
if (TransactionSynchronizationManager.isActualTransactionActive()) {
System.out.println("Is transaction readonly : "+TransactionSynchronizationManager.isCurrentTransactionReadOnly());
}
pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
}
}
更新:
假设这不是一个Spring Boot项目,@EnableTransactionManagement是您的Spring应用程序处理事务所必需的。数据也将在没有事务的情况下持久化到数据库中。
@EnableTransactionManagement注释必须在@Configuration类上使用。
以下是在Spring中启用事务管理的示例代码
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public FooRepository fooRepository() {
// configure and return a class having @Transactional methods
return new JdbcFooRepository(dataSource());
}
@Bean
public DataSource dataSource() {
// configure and return the necessary JDBC DataSource
}
@Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
}
根据上面的答案,我尝试了以下代码,它非常简单。
/**
* This Aspect advice will be called only if transactional applied at method level
*/
@Around("@annotation(transactional)")
public Object proceedWithMethodLevelAnnotation(ProceedingJoinPoint proceedingJoinPoint,
Transactional transactional) {
if( transactional.readOnly() ) {
//do something
}
/**
* This Aspect advice will be called only if transactional annotation applied at class level
*/
@Around("@within(transactional)")
public Object proceedWithClassLevelAnnotation(ProceedingJoinPoint proceedingJoinPoint,
Transactional transactional)
if( transactional.readOnly() ) {
//do something
}
}