我正在尝试使用@around advice将用于跟踪的上下文注入到新创建的可调用对象中:
@Aspect
@Configurable
public class TracingAspect {
@Around("execution(java.util.concurrent.Callable+.new(..))")
public Callable wrapExecutor(ProceedingJoinPoint pjp) throws Throwable {
Context context = Context.current();
return context.wrap((Callable) pjp.proceed());
}
}
当weaver遇到预期的连接点时,如以下示例中的匿名可调用实现:
public class Foo {
private ExecutorService threadpool = Executors.newFixedThreadPool(10);
public Future<String> doStuffAsync() throws InterruptedException {
return threadpool.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println(42);
return 42;
}
});
}
}
我从aspectj weaver收到以下错误消息: error at foo/bar/tracing/aspect/TracingAspect.java::0 incompatible return type applying to constructor-execution(void foo.bar.Foo$1.<init>(foo.bar.Foo))
我做错什么了?
1条答案
按热度按时间klr1opcd1#
首先,不能替换构造函数中返回的对象
execution()
,因为构造函数不是一个普通的方法,例如可以将父类型或接口作为返回类型。构造函数总是准确地返回所定义类型的对象,而不是其他类型。这甚至不是aspectj限制,而是jvm限制。使用诸如asm之类的字节码工程库,您将有相同的限制。因此,在aspectj中,最好的方法是替换构造函数中返回的对象
call()
,但对象也必须与预期类型匹配。不幸的是,opentelemetry返回一个lambda示例,该示例不能转换为完全匿名的Callable
代码中的子类型。这意味着,在这种代码结构下,您无法执行任何操作。作为一种解决方法,您可以拦截对方法的调用
Callable
示例,例如ExecutorService.submit(Callable)
. 你只需要确保捕捉到所有相关的。例如:当然,如果您能够准确地确定那些属性(例如,从哪个类、哪个包中进行调用等),那么您也可以对拦截的调用进行筛选,以获得具有某些属性的可调用项。