Or in an OSGi environment
the bundles can be dynamically refreshed (meaning unloaded then
reloaded, but possibly woven with a different set of aspects on
reload). Or you can manage classloaders yourself and discard that
which has loaded the code so far and create a new one that will reload
with a potentially different set of aspects that include more
pointcuts/advice. But basically reloading has to happen for
*load*time weaving to do something different.
When you say:
All of the points are not known at deploy time.
Can it really be *any* join point? or is it more like 'execution of
any public method' - so execution(public * *(..)) or something like
that? Since I typically see this usually done by weaving all places
that might ever want interception and writing highly optimal advice
that can do very fast checks for whether there is 'nothing to do' at
the various locations. Something like these two levels of check:
pointcut interceptionLocation(): executionOfSomethingInteresting() &&
if(InterceptorFramework.anythingSwitchedOnAnywhere);
Object around(): interceptionLocation() {
if (!InterceptorFramework.anythingToDoHere(thisJoinPointStaticPart)) {
return proceed();
}
// do stuff
}
The if() guard in the pointcut will prevent construction of the
thisJoinPoint object (which can be expensive) if the advice is not
actually going to be called.
Ordering of advice is usually achieved using 'declare precedence:' to
specify a partial ordering amongst aspects that may apply at a
particular join point - since between different aspects it is
deliberately undefined unless you say otherwise. Within an aspect the
order of application of advice is well defined so you can usually get
what you want by arranging your before/after/around advice as
appropriate. If you attempt an arrangement that confuses AspectJ, it
will tell you.
Andy.
2008/12/3 Jason Weinstein <Jason.Weinstein@xxxxxxx>:
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
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users