提问者:小点点

如果@transactional应用于类级别,如何截取@transactional参数


如果@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标志的值。


共3个答案

匿名用户

对于类型级别注释:

@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
    }
}