Indeed, enabling or disabling an aspect is a crosscutting concern.
You can *almost* write a general-purpose aspect that allows you to
dynamically enable or disable other aspects. It's easy to do this for
arbitrary before or after advice, but the problem arises if you'd like
to disable around advice. If you don't proceed with around advice, it
skips the original method... I've included an example aspect below that
works if your dynamic aspects don't use around advice.
We could generalize AspectJ a little bit to allow this aspect to
enable and disable around advice too: we could make proceed a closure
on JoinPoint and add some additional context to JoinPoint for advice
execution: a field advisedJoinPoint. Then we could disable around
advice with: thisJoinPoint.getAdvisedJoinPoint.getProceed().run(args)
It would also be nice if target for adviceexecution were bound to
the currently running object (this) at the advised join point. The
main question in my mind is whether there are compelling use cases to
justify the extra complexity of this idea.
/**
* This aspect automates enabling and disabling of other aspects at
runtime
* Any aspect that implements the marker interface DynamicAspect will
be
* able to be enabled or disabled dynamically at runtime.
*
* It's also easy to use this style of code to support configuring the
aspect
* on a per-instance basis: keep a set of deployed objects, and check if
* this is in the set of deployed objects...
*
*/
public aspect AspectManagement {
private boolean DynamicAspect.enabled;
public DynamicAspect.setEnabled(boolean enabled) {
this.enabled = enabled;
}
around() : adviceexecution() && within(DynamicAspect+)
{
// could check for around advice by looking at the
generated name in the signature
if (enabled) {
proceed();
}
}
// can expose DynamicAspect for JMX...
/**
* This advice makes it an error to call any method on a disabled
aspect.
*/
around() : (execution(* *(..)) || execution(* new(..)))
&& within(DynamicAspect+) {
if (enabled) {
proceed();
} else {
throw new UnsupportedOperationException("calling a
method on a disabled aspect.");
}
}
}
Ron Bodkin
Chief Technology Officer
New Aspects of Software
o: (415) 824-4690
m: (415) 509-2895
------------Original Message------------
From: Adrian Colyer <adrian_colyer@xxxxxxxxxx>
To: aspectj-users@xxxxxxxxxxx
Date: Wed, Mar-31-2004 4:20 AM
Subject: Re: [aspectj-users] Incremental and runtime weaving
support ?
Forgive the long answer, but I
think it is worth discussing some of the options here, since many
people are unaware of what AspectJ can do in this regard.
First of all, AspectJ has been
able to support *load-time* weaving since the 1.1 release, and several
folks have written weaving classloaders that exploited that fact. What
we didn't do, was make it especially easy to exploit those load-time
weaving capabilities. AspectJ 1.2 will ship with a new sample script in
the examples directory, "aj"that will launch any Java application using
load-time weaving of aspects from the ASPECTPATH environment variable
("aj" is to "ajc" as "java" is to "javac"). In addition, there is a
weaving class loader shipped in the tools jar, and an adaptor that
makes it easy to plug load-time weaving into an existing class-loader
hierarchy. You can get many of the same benefits of arbitrary run-time
weaving by combining load-time weaving with class recycling - and
indeed most middleware systems support application re-loading to pick
up changes at runtime by using custom classloaders.
Whether you weave at load-time or
before, there are also a bunch of things you can do with aspects that
give you a high degree of runtime dynamicity:
Simplest of all is the aspect that
can be turned on or off at runtime - this can be made very efficient
indeed following the pattern
public aspect
DoSomethingInteresting {
private static boolean isEnabled
= false;
public static void
setEnabled(boolean turnMeOn) {
this.isEnabled = turnMeOn;
}
pointcut isEnabled() :
if(isEnabled);
// regular advice goes here, e.g.
before() :
someInterestingJoinPoint() && isEnabled() {
// here we go...
}
}
You can then enable or disable the
aspect behavior at runtime using the following snippet:
DoSomethingInteresting.setEnabled(true);
You can follow the same basic
pattern for aspects that are pertarget, percflow etc. by making the
isEnabled and setEnabled members non-static, and using
DoSomethingInteresting.aspectOf(x).setEnabled(true);
Using the per-clauses you can also
easily get a whole additional range of runtime behaviours, for example
the following aspect lets you decide on a pertarget basis whether or
not the aspect behaviour should be enabled (strictly, whether an aspect
instance should be created).
public aspect
DoSomethingElseInteresting pertarget(candidateTargetObject(Object)) {
private static boolean
enableBehaviourFor(Object o) {
// some runtime test
}
pointcut
candidateTargetObject(Object o) : someCalls() && target(o)
&& if(enableBehaviourFor(o));
// advice etc. goes here.
}
You could imagine a similar aspect
using percflow and deciding on an individual control flow basis whether
to create an aspect instance or not.
Frameworks like the JBoss AOP
framework only allow you to do true runtime weaving on classes that
have been pre-prepared (at load-time or before) to instrument their
join points (I can't speak for AspectWerkz and Prose off the top of my
head). If you can accept the pre-preparation step, then AspectJ can
give you an equivalent degree of runtime flexibility using a pattern
like the following:
public aspect
RuntimeAdviceChainExample {
private ICommand[] adviceChain;
public void
setAdviceChain(ICommand[] adviceChain) {
this.adviceChain =
adviceChain;
}
// could imagine other methods
that let me add, remove, reorder commands in the advice chain, omitted
for brevity
pointcut
someInterestingJoinPoints() : ..... ;
before() :
someInterestingJoinPoints() {
for (int i = 0; i <
adviceChain.length; i++) {
adviceChain[i].execute(thisJoinPoint);
}
}
}
I've shown a general form of the
aspect - if you have known context at the set of join points of
interest, and are prepared to make a custom command interface you can
write more efficient advice, e.g.
after(BankAccount acc) returning :
bankOperation(acc) {
for (int i = 0; i <
adviceChain.length; i++) {
adviceChain[i].execute(acc);
}
}
So, to summarize, you can already
do a surprising amount at runtime using the existing facilities of
AspectJ. Are there any strong use cases out there not supported by one
of the above mechanisms?
-- Adrian
Adrian_Colyer@xxxxxxxxxx
aspectj-users-admin@xxxxxxxxxxx wrote on
31/03/2004 11:59:27:
> Hi,
> you can try dynamic AOP tools, like:
> PROSE (http://prose.ethz.ch/)
> Aspectwerkz (http://aspectwerkz.codehaus.org/)
> JBoss/AOP
>
> cheers
>
> paolo
>
>
> On Wed, 31 Mar 2004 12:26:13 +0200, Enrique J. Amodeo Rubio
> <eamodeorubio@xxxxxxxxxxxxxx> wrote:
>
> > Hi everybody,
> >
> > I had a talk with my boss about the limits of AspectJ and
some
> questions appeared.
> > Is there any plans about supporting runtime (not load time)
> weaving? And for incremental weaving? I have read about
-Xreweavable
> and I wonder if this option could made feasible to support these
> features in the future. For runtime weaving I mean the ability to
> load and weave an aspect during the execution of a program in a
> similar way that you can load a class and use them. I think that
> incremental weaving is necessary in order to achieve a good
> performance. Of course some AspectJ features like introduction
could
> not support this (but I can live without them). I understand that
> JVM technology can put limitations on these topics.
> >
> > Perhaps this subject has been discussed in another mail
threads.
> If so please send me some links since I can't find them.
> >
> > Thanks,
> >
> > Enrique J. Amodeo Rubio
> > _______________________________________________
> > aspectj-users mailing list
> > aspectj-users@xxxxxxxxxxx
> > http://dev.eclipse.org/mailman/listinfo/aspectj-users
>
>
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users