[英]How to Intercept @transactional arguments if @transactional applied at class level
I want to capture the argument of @transactional if it is applied at class level.如果 @transactional 应用于类级别,我想捕获它的参数。
for eg if @transactional
applied at method level like :-例如,如果
@transactional
应用于方法级别,如:-
class A {
@transactional(readOnly= true)
public void someMethod(){
// some code...
}
}
then I am able to Intercept and capture the formal argument ie readOnly with this code like :-然后我就可以使用以下代码拦截并捕获形式参数,即 readOnly :-
@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
}
However the above code will not work if @transactional
applied at class level as :-但是,如果
@transactional
在类级别应用为:-
@transactional(readOnly= true)
class A {
public void someMethod(){
// some code...
}
}
Now in order to Intercept the @transactional
annotation which is applied at class level I have following code :-现在为了拦截在类级别应用的
@transactional
注释,我有以下代码:-
@Pointcut("@within(org.springframework.transaction.annotation.Transactional *)")
public void beanAnnotatedWithTransactional() {}
@Pointcut("execution(public * *(..))")
public void publicMethod() {}
@Pointcut("publicMethod() && beanAnnotatedWithTransactional()")
public void publicMethodInsideAClassMarkedWithATransactional() {}
My actual problem here is I am unable to check the value of readOnly flag if @transactional
is applied at class level.我的实际问题是,如果在类级别应用了
@transactional
我将无法检查 readOnly 标志的值。
For type level annotation :对于类型级别注释:
@Around("@within(transactional)")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
boolean readOnly = transactional.readOnly();
...
return pjp.proceed();
}
For method level annotation:对于方法级别的注释:
@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();
}
Another (cleaner) option for method level :方法级别的另一个(更清洁)选项:
@Around("@annotation(transactional)")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
} }
or或者
With more control over tager :更好地控制 tager :
@Around("execution(@org.springframework.transaction.annotation.Transactional public * *(..)) && @annotation("transactional")
public Object myMethod(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
}
You may use the TransactionSynchronizationManager to get reference to the transaction details.您可以使用TransactionSynchronizationManager来获取对事务详细信息的引用。
Following code provides the readonly details of the current active transaction.以下代码提供了当前活动事务的只读详细信息。
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();
}
}
}
Update:更新:
Assuming this is not a Spring Boot project , @EnableTransactionManagement is mandatory for your spring application to work with transactions.假设这不是 Spring Boot 项目, @EnableTransactionManagement对于您的 Spring 应用程序处理事务是强制性的。 Data will get persisted to database without transactions as well.
数据也将在没有事务的情况下持久保存到数据库中。
@EnableTransactionManagement annotation has to be used on @Configuration classes.
必须在 @Configuration 类上使用 @EnableTransactionManagement 注释。
Following is a sample code to enable transaction management in spring以下是在 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());
}
}
Based on the answers above I tried with the following code it is very simple.根据上面的答案,我尝试使用以下代码非常简单。
/**
* 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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.