0

我从 GenericServlet 派生并使用 @Tx 注释该派生类。我想在 servlet 启动期间使用 GenericServlet.init() 方法调用通过 aop 在 servlet 外部触发一些初始化。前两行根本不匹配,第三行显然匹配所有 servlet,第四行匹配所有 servlet,尽管使用注释指定目标。

@Before("@this(com.github.jjYBdx4IL.aop.tx.Tx)
    && execution(* javax.servlet.GenericServlet+.init()) && this(foo)")
@Before("@target(com.github.jjYBdx4IL.aop.tx.Tx)
    && execution(* javax.servlet.GenericServlet+.init()) && this(foo)")

@Before("execution(* javax.servlet.GenericServlet+.init()) && this(foo)")
@Before("target(@com.github.jjYBdx4IL.aop.tx.Tx Object)
    && execution(* javax.servlet.GenericServlet+.init()) && this(foo)")

如果我将 GenericServlet+.init() 替换为 GenericServlet.init(..)

@Before("@this(com.github.jjYBdx4IL.aop.tx.Tx) 
    && execution(* javax.servlet.GenericServlet.init(..)) && this(foo)")

这很奇怪,因为使用调试器,GenericServlet.init() 肯定会从 GenericServlet.init(ServletConfig) 调用...

有人可以澄清一下,这里发生了什么吗?我希望第一行应该可以解决问题,但事实并非如此。

我最好的猜测是它与 Jetty 实例本身使用的类加载器和 webapp 的类加载器的分离有关......我设法使以下至少编织 init() 方法(根据 maspectj 的调试输出) :

@After("@this(com.github.jjYBdx4IL.aop.tx.Tx
    && target(javax.servlet.GenericServlet+)
    && execution(* init()) && this(foo)")

但它不会触发。

更新

我将问题追溯到这个:URLClassLoader loading Annotation as com.sun.$Proxy$27

基本上, foo.getClass().isAnnotationPresent(Tx.class) 总是返回 false。现在的问题是:这是什么废话?我怎样才能禁用它?

4

1 回答 1

0

当父类加载器已经定义了相同的类/注释时,类加载器正在使用这些 com.sun.proxy.$Proxy 实例。因为我想编织像 javax.servlet.GenericServlet 这样的系统类,所以我需要使用父类加载器加载我的注释/方面,即使用 Jetty 本身。将我的 webapp 的包含注释的依赖项设置为“提供”的 maven 范围解决了这个问题。

“已解决”的意思是:注解的代理仍然存在,但对“isAnnotationPresent”的调用实际上现在返回 true 而不是 false,这就是 AspectJ 在运行时无法识别注解切入点的原因。

于 2017-06-07T17:58:40.263 回答