Skip to main content

[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




Back to the top