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;
}
}
}