[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[aspectj-users] Design Question Dynamic Interceptors
|
I am using LTW with use of aop.xml and a single "aj" file. However i
don't really see how AspectJ supports the addition and deletion of
Aspects at runtime. In a way i want to weave and unweave new
pointcuts/advice at runtime. In fact i'd like for a user to be able to
specify them.
I would like to be able to
1) Add and Remove interceptors at runtime. Interceptors apply at
specific points in the code (pointcut). All of the points are not known
at deploy time.
For instance i would like to be able to add and remove an around()
advice for Class/Interface A Method X at runtime
2) I would like to be able to chain the Interceptors.
For instance for method X i would like to first apply Interceptor A,
then Interceptor B, then call the original Method X (or skip it).
To accomplish this i came up with a little framework which manages an
Interceptor Table/Chains
It allows for the dynamic addition and deletion of Interceptors as well
as their chaining.
The framework code is called from the aspect "aj" file.
So largely these pointcuts are static. However the Interceptor behavior
is dynamic. (I'm being very specific and don't have a *.*(..) pointcut)
The advice in the "aj" code simple calls into my framework which is kind
of like a DI (dynamic invocation) framework.
The question is is there a way to dynamically add and remove new
pointcuts/advice at runtime, and ensure the order they are woven?.
Some example code which illustrates some ideas is shown below.
public pointcut DeliveryChannel_accept1(
DeliveryChannel object) :
execution(public MessageExchange
javax.jbi.messaging.DeliveryChannel+.accept())
&& this(object);
Object around(DeliveryChannel object,
long timeout)
throws MessagingException :
DeliveryChannel_accept1(object, timeout) {
Proceed proceed = new Proceed()
{ // This is the
actual target code. At the end of an InterceptorChain this code may be
called.
public Object invoke(Object target, Object[] args) throws
Exception {
DeliveryChannel channel = (DeliveryChannel) target;
long timeout = (Long) args[0];
return proceed(channel, timeout);
}
};
Object result = null;
try {
result =
system.invoke(JBIConstants.KEY_DELIVERYCHANNEL_ACCEPT1, // This code
calls my framework, which
thisJoinPoint, proceed);
//1. Looks up the
list of Interceptors to apply (can be empty)
} catch (MessagingException e)
{
//2. Runs each interceptor with args from JoinPoint passed in
throw
e;
//3. Calls the Proceed object which runs the actual target method
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
return result;
}
Interceptors have a simple api like
public Object invoke(IInterceptorChain chain) throws Exception;
The InterceptorChain has methods like
public String getKey();
public void setKey(String key);
public Object getTarget();
public void setTarget(Object target);
public Member getMember(); // Constructor or Method
public void setMember(Member member);
public Object[] getArgs();
public void setArgs(Object[] args);
public Object proceed() throws Exception;
Where proceed() is implemented something like
public Object proceed() throws Exception {
Object ret;
if (getIter().hasNext()) { // Iter contains list of Interceptors
ret = getIter().next().invoke(this);
} else {
wasTargetCalled = true;
ret = getProceed().invoke(target, args);
}
return ret;
}
and Proceed abject has simple api like
public Object invoke(Object target, Object[] args) throws Exception;
The table of Interceptors has methods like
addKey(key, Interceptor)
getListForKey(key)
removeInterceptor(Interceptor)
There are a variety of types of Interceptors including basic ones which
only run if Filter passes, etc