使用 AspectJ 实现虫洞模式

use*_*468 5 java aop aspectj guice

我正在寻找使用 AspectJ 实现虫洞模式的示例(如果 Guice AOP 有能力实现这一点,我会感兴趣)。

虫洞本质上允许您沿调用流程传递其他参数,例如:

// say we have
class foo {
   public int m0 int a, int b) {
     return m1(a,b);
   }

   public int m1 int a, int b) {
     return m2(a,b);
   }

   public int m2 int a, int b) {
     return a+b;
   }
}
// and I wanted in a non-invasive manner to pass a third parameter of type
class context {
  String userName;
  long timeCalled;
  String path;
}
// I could use an advise to say print the context information
// to trace what was going on without mucking up my method signatures 
Run Code Online (Sandbox Code Playgroud)

我相信这位 Ramnivas Laddad 在他的 AspectJ in Action 一书中有这样一个例子。

提前致谢。

kri*_*aex 4

事实上, AspectJ in Action中有一个例子。如果您查看目录,您会发现第 12.2 章就是您要查找的内容。买这本书是个好主意。我可以热烈推荐它。因为我不确定是否可以复制并粘贴书中的部分内容,所以我将在这里引用模板:

public aspect WormholeAspect {
    pointcut callerSpace(<caller context>) :
        <caller pointcut>;

    pointcut calleeSpace(<callee context>) :
        <callee pointcut>;

    pointcut wormhole(<caller context>, <callee context>) :
        cflow(callerSpace(<caller context>)) && 
        calleeSpace(<callee context>);

    // advice to wormhole
    before(<caller context>, <callee context>) :
        wormhole(<caller context>, <callee context>)
    {
            ... advice body
    }
}
Run Code Online (Sandbox Code Playgroud)

TheServerSide.com 上有一篇Laddad 的旧文章,其中有一个更具体的示例。和书里的不太一样,但是很相似。

正如您所看到的,在 AspectJ 中这很容易做到,因为那里有切入点cflow()。我从未使用过 Guice,但它的AOP 介绍页面提到它们的实现是AOP 联盟规范的一部分。看看AOP 联盟 API,没有什么看起来像cflow()切入点,它都是围绕构造函数和方法调用以及字段访问。

那么如果你想避免在所有层中传递参数,你可以在 Spring(没有 AspectJ)或 Guice 中做什么呢?显而易见的解决方案是由ThreadLocal调用者声明和管理(即分配,但也清除)并由被调用者访问的变量。这不太好,只是一种解决方法,以免 API 变得臃肿。但它要求调用者和被调用者都对他们想要共享的内容以及如何共享有共同的理解。在某种程度上,这种实现与其说是一种模式,不如说是一种反模式。如果可以的话,使用 AspectJ 以一种干净且模块化的方式解决这个问题,将要解决的问题封装在一个模块(方面)中。