使用AspectJ实现虫洞模式

我正在寻找使用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 

我相信这个Ramnivas Laddad在他的着作“AspectJ in Action”中有这样一个例子。

提前致谢。

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

 public aspect WormholeAspect { pointcut callerSpace() : ; pointcut calleeSpace() : ; pointcut wormhole(, ) : cflow(callerSpace()) && calleeSpace(); // advice to wormhole before(, ) : wormhole(, ) { ... advice body } } 

Laddad在TheServerSide.com上发表了一篇旧文章,其中有一个更具体的例子。 它与书中的不同,但相似。

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

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

一个简单的例子。 想象一下,你有提供function的上下文目标对象 ,它们在某种程度上取决于上下文的状态:

 class T { public void foo() { System.out.println("T.foo()"); } } class Context { public boolean isValid = true; public void doStuff() { T t = new T(); t.foo(); } } public class Main { public static void main(String[] args) { Context c = new Context(); c.doStuff(); } } 

只有当成员isValid设置为true ,才能确保Context实例可以在T实例上调用foo()方面可以采用以下方式:

 public aspect ContextStateValidation { pointcut MyContext(Context c) : execution(* Context.*()) && this(c); pointcut FooCalls(T t) : call(* T.foo()) && target(t); pointcut FooCallsInMyContext(Context c, T t) : cflow(MyContext(c)) && FooCalls(t); void around(Context c, T t) : FooCallsInMyContext(c, t) { if (c.isValid) proceed(c, t); } } 

不要使用虫洞图案……事实上,只有在你确定需要的时候才使用AOP,否则就离开它。

虫洞模式的缺点是你跳过很多层……你真正想要的是什么? 🙂

Grtz,

克里斯托夫