为了账号安全,请及时绑定邮箱和手机立即绑定

AspectJ within(is(FinalType)) 错过了

AspectJ within(is(FinalType)) 错过了

Qyouu 2023-04-13 10:48:44
我正在使用 aspectJ 1.8.10。在我的代码中,我有一个带有 ScheduledExecutorService 的 bean:@Beanpublic ScheduledExecutorService backgroundTaskExecutor() {    return Executors.newSingleThreadScheduledExecutor();}当 bean 实例化时,代理类抛出:.AopConfigException: Could not generate CGLIB subclass of class [class java.util.concurrent.Executors$DelegatedScheduledExecutorService]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class java.util.concurrent.Executors$DelegatedScheduledExecutorService我知道,ScheduledExecutorService 没有构造函数是根本原因。但是我需要配置方面的切入点以排除 FinalType 类。像这样:@Before("!within(is(FinalType)) && execution(* your_method_name(..)) ")但是,正如我提到的,aspectJ 版本 1.8.10 无法识别 is(..) 语法。(Intellij IDEA 警告 Cannot resolve symbol 'is')。应用程序启动时没有 AOP 问题,但失败了java.lang.IllegalArgumentException: No visible constructors in class java.util.concurrent.Executors$DelegatedScheduledExecutorService我做错了什么?aspectj > 1.8.4 有什么变化吗?(是(..)语法)
查看完整描述

1 回答

?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

您已将 Spring AOP 配置为强制创建 CGLIB 代理,即使对于像这样的接口类型ScheduledExecutorService,也可能通过


@EnableAspectJAutoProxy(proxyTargetClass = true)

只需删除该proxyTargetClass = true部分或设置为false,然后您的方面就会起作用。您不需要任何is(FinalType)切入点指示符,只需编写类似


@Before("execution(* schedule*(..))")

为了拦截调度程序方法。


更新:让我解释一下为什么对is(FinalType)您没有帮助以及为什么认为它不起作用是错误的:


再次阅读错误消息:


Could not generate CGLIB subclass of class

  [class java.util.concurrent.Executors$DelegatedScheduledExecutorService]:

  Common causes of this problem include using a final class or a non-visible class;

  nested exception is

    java.lang.IllegalArgumentException: No visible constructors in class

    java.util.concurrent.Executors$DelegatedScheduledExecutorService

“没有可见的构造函数”并不意味着该类是最终的,它的意思是:没有可见的构造函数。实际上,内部静态类在所在位置Executors.DelegatedScheduledExecutorService是受包保护的。如果您查看源代码,您会看到:java.util.concurrentExecutors


static class DelegatedScheduledExecutorService

        extends DelegatedExecutorService

        implements ScheduledExecutorService {


    private final ScheduledExecutorService e;


    DelegatedScheduledExecutorService(ScheduledExecutorService executor) {

        super(executor);

        e = executor;

    }


    // (...)

}

看?final这里没有课。实际问题是由于 JVM 的限制,CGLIB 无法创建子类:如果不在另一个包中,则不能将其子类化public。


这就是为什么我告诉你让 Spring 使用 JDK 动态代理并利用这样一个事实,在这种情况下子类化不是必需的,但实现一个接口就足够了。


查看完整回答
反对 回复 2023-04-13
  • 1 回答
  • 0 关注
  • 168 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信