AspectJ within(is(FinalType)) 错过了
AspectJ within(is(FinalType)) missed
我正在使用 aspectJ 1.8.10。
在我的代码中,我有一个带有 ScheduledExecutorService 的 bean:
@Bean
public ScheduledExecutorService backgroundTaskExecutor() {
return Executors.newSingleThreadScheduledExecutor();
}
当 bean 实例化时,代理 class 抛出:
.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 classes。
像这样:
@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 有什么变化吗? (是(..)语法)
您已将 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
"No visible constructors" 并不意味着 class 是最终的,它的意思是:没有可见的构造函数。实际上,内部静态 class Executors.DelegatedScheduledExecutorService
是 Executors
所在的 java.util.concurrent
中的 package-protected。如果您查看源代码,您会看到:
static class DelegatedScheduledExecutorService
extends DelegatedExecutorService
implements ScheduledExecutorService {
private final ScheduledExecutorService e;
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
super(executor);
e = executor;
}
// (...)
}
看到了吗?这里没有final
class。实际问题是由于 JVM 限制,CGLIB 无法创建 subclass:如果不是 public
.
,您不能 subclass 另一个包中的东西
这就是为什么我告诉你让 Spring 使用 JDK 动态代理并利用这样一个事实,在这种情况下 subclassing 不是必需的,而是实现一个接口就够了。
我正在使用 aspectJ 1.8.10。 在我的代码中,我有一个带有 ScheduledExecutorService 的 bean:
@Bean
public ScheduledExecutorService backgroundTaskExecutor() {
return Executors.newSingleThreadScheduledExecutor();
}
当 bean 实例化时,代理 class 抛出:
.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 classes。 像这样:
@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 有什么变化吗? (是(..)语法)
您已将 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
"No visible constructors" 并不意味着 class 是最终的,它的意思是:没有可见的构造函数。实际上,内部静态 class Executors.DelegatedScheduledExecutorService
是 Executors
所在的 java.util.concurrent
中的 package-protected。如果您查看源代码,您会看到:
static class DelegatedScheduledExecutorService
extends DelegatedExecutorService
implements ScheduledExecutorService {
private final ScheduledExecutorService e;
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
super(executor);
e = executor;
}
// (...)
}
看到了吗?这里没有final
class。实际问题是由于 JVM 限制,CGLIB 无法创建 subclass:如果不是 public
.
这就是为什么我告诉你让 Spring 使用 JDK 动态代理并利用这样一个事实,在这种情况下 subclassing 不是必需的,而是实现一个接口就够了。