Refactoring Instrumentation in AOP 2.0: Iteration 3
bill.burke Jul 6, 2005 8:36 PM* Write a fully optimized instrumentor that inlines before/after, within the
OPtimized MethodInvocation, ConstructorInvocation, etc... classes. Remember
that old generated code snippet we sent around before? I'll attach some examples.
public class Foo { private float doit(double stuff) throws TypedException { } public static abstract class Joinpoint_doit implements MethodJoinpoint { protected Foo target; protected double arg1; protected Joinpoint_doit() {} protected Joinpoint_doit(Foo target, double arg1) { this.target = target; this.arg1 = arg1; } public Object dispatch() { return new Float(target.doit(arg1)); } public Object[] getArguments() {...} public abstract float doit(Foo target, arg1); } } package org; public class Foo_Joinpoint_doit extends Foo.Joinpoint_doit { private Security before1; private TxDemarcation around1; private LatchedJoinpoint around2; private SomeAspect after1; private SomeAspect after2; Private AnotherAspect afterThrowing1; private int currentAdvice; public Foo_Joinpoint_doit(TxDemarcation around1, LatchedJoinpoint around2) { this.around1 = around1; this.around2 = around2; } public Foo_joinpoint_doit(Foo target, double arg1, TxDemarcation around1, LatchedJoinpoint around2) { super(target, arg1); } // for dynamic invoke. public Object invoke(Object target, MethodJoinpoint jp) throws Exception { Object[] args = jp.getArguments(); return new Float(doit((Foo)target, ((Double)args[0]).doubleValue())); } public float doit(Foo target, double arg1) throws TypedException { float returnValue; before1.authenticate(); try { Foo_Joinpoint around = new Foo_Joinpoint(target, arg1, around1, around2); returnValue = = (Float)(around.invokeNext()).floatValue(); // after needs detyped args so get them from the around advice args = around.getArguments(); returnValue = (Float)(after1.doAdvice(this, // static joinpoint new Float(returnValue), // return as a generic object args)).floatValue(); // needs generic args returnValue = after2.doAdvice(returnValue); // just typed returnValue needed. } catch (Throwable t) { t = afterThrowing1.execute(this, t, args); t = afterThrowing2.execute(this, t, args); if (t instanceof TypedException) throw (TypedException)t; else if (t instanceof RuntimeException) throw (RuntimeException)t; else throw new RuntimeException(t); } return returnValue; } public FooPolicy getAround3() { return (FooPolicy)target.getInstanceAdvisor().getPerInstanceAspect("FooPolicy"); } public Object invokeNext() throws Throwable { try { switch (++currentAdvice) { case 1: return around1.doTransaction(this); case 2: return around2.invoke(this); case 3: InvocationStack.push(this); try { return new Float(getAround3().doit(arg1)); } finally { InvocationStack.pop(); } default: return dispatch(); } } finally { --currentAdvice; } } }