简体   繁体   English

如果@transactional 在类级别应用,如何拦截@transactional 参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM