Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Design Question Dynamic Interceptors

2008/12/4 Jason Weinstein <Jason.Weinstein@xxxxxxx>:
> Can you point me to any resources which discuss this in more detail?
>
> I guess i am most interested in how the aspectweaver/classloader is loading
> the pointcuts/advice. Also is there some internal api which can be called to
> say add pointcut/advice via api?

It comes up on the list now and again - you could try searching the
archives.  The most 'dynamic' we get out of the box is that you can
write the aop.xml file out to disk just before loading the classes,
the creation of the classloader that loads the classes is what will
trigger creation of a weaver attached to that classloader, and that
will lookup the aop.xml files in order to learn what aspects are
defined.  (aspectjweaver.jar includes a basic javaagent that the JVM
recognizes and knows wants to be involved in classloading).

To remove the aop.xml files from the mix, you could write your own
implementation of IWeavingContext (or subclass the
DefaultWeavingContext) in order to supply definitions directly that
the DefaultWeavingContext will have discovered by parsing the XML.
However, this still has the same restrictions as aop.xml - you can't
define advice dynamically, you can merely fill in pointcuts for
abstract aspects.  So you need some abstract pointcuts and generic
advice defined in some aspect library that you 'activate' by defining
concrete sub-aspects via the weavingcontext.

The documentation on doing your own WeavingContext is hopeless I'm
afraid - but I know some people have gone down this route, and I know
others have done a bit of class reloading (since I've had bugs in
related to it).  Hopefully they can provide more info on the approach.

Andy.

>
> Thanks
>
> Andy Clement wrote:
>
> We do support some degree of hotswap class replacement (similar to
> what happens if you change a class and update it in the VM 'live'
> during debugging for example) - but we don't manage that for you, you
> would have to drive the class replacement.
>
> What about if i am using aop.xml and not Annotations. Is there any
> difference??
>
>   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
>
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>


Back to the top