java - AspectJ inside(is(FinalType)) 丢失

标签 java spring aop aspectj spring-aop

我使用的是aspectJ 1.8.10。 在我的代码中,我有一个带有 ScheduledExecutorService 的 bean:

@Bean
public 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 警告无法解析符号“is”)。 应用程序启动时没有 AOP 问题,但失败并显示

java.lang.IllegalArgumentException: No visible constructors in class java.util.concurrent.Executors$DelegatedScheduledExecutorService

我做错了什么? spectj > 1.8.4 有什么变化吗? (is(..) 语法)

最佳答案

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

@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.DelegateScheduledExecutorServiceExecutors 所在的 java.util.concurrent 中受到包保护。如果您查看源代码,您会看到:

static class DelegatedScheduledExecutorService
        extends DelegatedExecutorService
        implements ScheduledExecutorService {

    private final ScheduledExecutorService e;

    DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
        super(executor);
        e = executor;
    }

    // (...)
}

看到了吗?这里没有final类。实际问题是,由于 JVM 限制,CGLIB 无法创建子类:如果另一个包中的内容不是 public,则无法对它进行子类化。

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

关于java - AspectJ inside(is(FinalType)) 丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57150467/

相关文章:

java - Spring bean 如何检测它自己是否已包装在 AOP 代理中?

spring AoP,具有相同参数类型的重载方法的切入点表达式

java - 更新 TextView

java - 如何在Java中对齐按钮我尝试了一些方法,但在我的代码中不起作用任何线索我要做什么来解决这个问题

java - 在没有注释或 xml 配置的情况下创建主要 bean

java - 使用 Hibernate 和 Spring 批量插入

java - JVM 中的 native 堆栈和缓存代码

java - Spring Autowiring 不适用于 quartz

java - 使用错误的方法无法聚合消息?

c# - C# 中的面向方面编程