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
|