微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring AOP“内”不适用于方法

如何解决Spring AOP“内”不适用于方法

下面是我的自定义注释。

@Target({ ElementType.METHOD,ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Transactional(value = TransactionalCode.MANAGER,readOnly = true)
public @interface FinanceReadTx {
}

我想对“MyAnnotation”做一些事情,所以我声明了@Around 和如下所示的方法

@Aspect
@Component
public class TransactionalInterceptor implements Ordered {
    @Around("within(@org.springframework.transaction.annotation.Transactional *) || " +
            "within(@(@org.springframework.transaction.annotation.Transactional *) *)")
    public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
        try {
            setDbType(pjp);
            Object result = pjp.proceed();
            DataSourceContextHolder.clearDataSourceType();
            return result;
        } finally {
            // restore state
            DataSourceContextHolder.clearDataSourceType();
        }
    }
....
}

以下服务由其他类“自动装配”。所以我觉得不是AOP代理的问题。

@Service
public class UnconfirmedReportService {
    private static final int PREVIEW_SIZE = 8;
    @Autowired
    private UnconfirmedReportRepository unconfirmedReportRepository;
...
    @FinanceHikariReadTx
    public List<UnconfirmedExcelDownloadView> getExcelData(UnconfirmedSearchCondition condition) {
        List<UnconfirmedExcelDownloadView> excelData = newArrayList();
        excelData.addAll(newArrayList(getPurchaseReportDetailExcel(condition)));
        return excelData;
    }
...
}

下面的代码调用上面的服务

@Slf4j
@Component
public class UnconfirmedDashboardDetailExcelReader extends SellerExcelReaderTemplate<UnconfirmedExcelDownloadView,UnconfirmedSearchCondition> {
    @Autowired
    private UnconfirmedReportService unconfirmedReportservice;

    @Override public List<UnconfirmedExcelDownloadView> read(String conditionjson) {
        UnconfirmedSearchCondition condition = transformCondition(conditionjson);
        List<UnconfirmedExcelDownloadView> viewList = unconfirmedReportservice.getExcelData(condition);
        return viewList;
    }
...
}

如果@MyAnnotation 被注解到一个类,则调用proceed() 但如果一个方法像上面的代码一样带有注解,它就不起作用。我希望它只使用方法

我在几个小时内一直在努力解决这个问题,但找不到解决方案。请帮帮我。

解决方法

您目前正在执行与我在 this answer 中解释的类似的操作,即匹配类的(元)注释。

现在你想知道为什么它不匹配方法。我解释说here。基本上,@within() 匹配带注释的类中的任何内容,而 @annotation() 匹配带注释的方法。问题是,@annotation() 需要一个确切的类型名称。

但是还有另一种方法可以直接在 execution() 签名中表达带注释的方法。在这里,您还可以选择以与将元注释用于带注释的类类似的方式来指定元注释。让我们比较一下两者:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MetaAnnotationInterceptor {
  @Before(
    "execution(* *(..)) && (" +
      "within(@de.scrum_master.app.MetaAnnotation *) || " +
      "within(@(@de.scrum_master.app.MetaAnnotation *) *) || " +
      "within(@(@(@de.scrum_master.app.MetaAnnotation *) *) *)" +
    ")"
  )
  public void annotatedClasses(JoinPoint thisJoinPoint){
    System.out.println(thisJoinPoint);
  }

  @Before(
    "execution(@de.scrum_master.app.MetaAnnotation * *(..)) || " +
    "execution(@(@de.scrum_master.app.MetaAnnotation *) * *(..)) || " +
    "execution(@(@(@de.scrum_master.app.MetaAnnotation *) *) * *(..)) "
  )
  public void annotatedMethods(JoinPoint thisJoinPoint){
    System.out.println(thisJoinPoint);
  }
}

后者就是你要找的。只需将 de.scrum_master.app.MetaAnnotation 替换为 org.springframework.transaction.annotation.Transactional,它应该适用于您的用例。确保不要弄乱 ()@* 的数量和嵌套顺序,否则很快就会出现切入点语法错误。

如果你更喜欢一个或两个通知方法,你可以创建一个包含两个切入点的大杂乱字符串,或者定义两个单独的 @Pointcut 并将它们组合在通知中,用 {{1 }}。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。