diff options
Diffstat (limited to 'docs/dist/doc/porting.html')
-rw-r--r-- | docs/dist/doc/porting.html | 1785 |
1 files changed, 1785 insertions, 0 deletions
diff --git a/docs/dist/doc/porting.html b/docs/dist/doc/porting.html new file mode 100644 index 000000000..0a4d558a3 --- /dev/null +++ b/docs/dist/doc/porting.html @@ -0,0 +1,1785 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + +<head> +<LINK rel="STYLESHEET" href="../style.css" type="text/css"> +<title>AspectJ 1.0.6 Reference - Porting Notes</title> +</head> + +<body> + +<DIV ALIGN=right CLASS=copyrightNotice> +© Copyright 1998-2002 Palo Alto Research Center Incorporated. All rights reserved. +</DIV> + +<h1>Porting Notes</h1> + +<ul> + <li><a href="#pre-1.0.4">Pre-1.0.4 code</a></li> + <li><a href="#pre-1.0rc1">Pre-1.0rc1 code</a></li> + <li><a href="#pre-1.0beta1">Pre-1.0beta1 code</a></li> + <li><a href="#pre-1.0alpha1">Pre-1.0alpha1 code</a> + </li> + <li><a href="#pre08b3">Pre-0.8beta3 code</a></li> + + <li><a href="#pre08b1">Pre-0.8beta1 code</a></li> + + <li><a href="#pre07b11">Pre-0.7beta11 code</a></li> + + <li><a href="#pre07b10">Pre-0.7beta10 code</a></li> +</ul> + +<h2><a name="pre-1.0.4">Porting pre-1.0.4 code</a></h2> + +<p>In versions of AspectJ prior to 1.0.4, the compiler was not +correctly implementing the AspectJ-1.0 language design for some uses +of after returning advice. +</p> + +<p> The main change that was made was of after returning advice for +constructor execution join points. Previously, this advice was legal: +</p> + +<PRE> +after() returning (Foo f): execution(Foo.new(..)) { ... } +</PRE> + +<p> However, it has always been a part of the 1.0 language design (and +of Java's language design) that constructors themselves (as opposed to +constructor calls) do not return the value of the new object. Rather, +<code>this</code> is bound to the new object, and the constructor +behaves like a void method. With that in mind, any code like the +above should be conveted to the form. </p> + +<PRE> +after(Foo f) returning: this(f) && execution(Foo.new(..)) { ... } +</PRE> + +<p> In compilers prior to 1.0.4, the following advice could pick out +join points +</p> + +<PRE> +after() returning (String s): call(void foo()) { ... } +</PRE> + +<p> This is no longer picked out. This pattern was most commonly used +in highly polymorphic contexts, such as +</p> + +<PRE> +after() returning (String s): call(* foo()) { ... } +</PRE> + +<p> If you want to capture all calls, binding null objects for those +that would otherwise have no value, you must use the +<code>Object</code> type. +</p> + +<PRE> +after() returning (Object o): call(* foo()) { ... } +</PRE> + +<p> Uses of both of these forms are highleted with compiler warnings +in the 1.0.4 compiler. +</p> + + +<hr /> + +<h2><a name="pre-1.0rc1">Porting pre-1.0rc1 code</a></h2> + +<p> Aspects can no longer be declared to implement the +<code>Serializable</code> or <code>Cloneable</code> interfaces. If +you previously used serializable or cloneable aspects, you should +refactor your code to keep the state you need to serialize or clone in +objects associated with the aspects. +</p> + +<hr /> + +<h2><a name="pre-1.0beta1">Porting pre-1.0beta1 code</a></h2> + +<p> The <code>static</code> modifier is no longer allowed on pointcut +declarations anywhere. Porting is simple; just remove the static +declarations when you find them. +</p> + +<p> Also, though the <code>returns</code> modifier on pointcuts has +not been part of the language since 1.0alpha1, the compiler still +accepted them until now. If you used this feature, now is the right +time to remove the <code>returns</code> modifier when the compiler +complains about it. +</p> + +<hr /> + +<h2><a name="pre-1.0alpha1">Porting pre-1.0alpha1 code </a></h2> + + +<p> The release of AspectJ 1.0alpha1 involved sweeping cleanups of the +language to bring it to 1.0 status. </p> + + <ul> + <li><a href="#1.0a1-pointcuts">Pointcuts</a></li> + <li><a href="#1.0a1-type-patterns">Type patterns</a></li> + <li><a href="#1.0a1-advice">Advice</a></li> + <li><a href="#1.0a1-introduction-and-static">Introduction and + static crosscutting</a></li> + <li><a href="#1.0a1-aspects">Aspects</a></li> + </ul> + +<h3><a name="1.0a1-pointcuts">Pointcuts</a></h3> + +<h4><a name="1.0a1-plural-to-singular">Removing the "s" from pointcuts</a></h4> + +<p> One of the most pervasive changes in porting code written before +1.0alpha1 is the change in some of the pointcut names from plural to +singular, that is, they lose an "s". In one sense, making this change +in your programs is easy: just go through and whever you see uses of +the pointcuts +</p> + +<blockquote>calls executions gets sets handlers initializations +staticinitializations</blockquote> + +<p> Just take off the final "s", to make one of +</p> + +<blockquote>call execution get set handler initialization +staticinitialization</blockquote> + +<p> Often, there will be other changes you should make for each of +these pointcuts, but as for the name, just take off the "s". </p> + +<p> One risk you will have when doing this is creating name conflicts. +If, for example, you named a parameter of a pointcut "set", you should +(for your own sanity -- the compiler doesn't require it) rename it in +the rewritten pointcut. </p> + +<PRE> +pointcut sort(Collection set): calls(void addAll(set)); +==> +pointcut sort(Collection mySet): call(void addAll(mySet)); +</PRE> + +<p> While converting to use singular nouns for the primitive +pointcuts, you may also want to remove the "s" from your user-defined +pointcuts. </p> + +<PRE> +pointcut publicCalls(): calls(public * *(..)); +==> +pointcut publicCall(): call(public * *(..)); +</PRE> + +<p> Of course, your naming conventions are your own, but throughout +these porting notes we will be making these changes in our example +ports. </p> + + +<h4><a name="1.0a1-remove-receptions">Removing the receptions pointcut</a></h4> + +<p> Perhaps the largest semantic change in the 1.0 language is the +removal of receptions join points. They have been merged with call +join points in AspectJ 1.0, so now a call join point doesn't represent +the "caller-side" of a call, but the call itself, both caller and +receiver. </p> + +<p> Changing code that used the <code>receptions</code> pointcut should be +fairly straightforward, depending on whether the pointcut exposed state or +not. </p> + +<h5>Not exposing state</h5> + +<p> Receptions pointcuts that did not expose state can simply be +replaced by the new <code>call</code> and <code>target</code> pointcuts:</p> + +<PRE> +receptions(void Foo.m()) +==> +target(Foo) && call(void m()) +</PRE> + +<h5>Exposing state</h5> + +<p> Some receptions pointcuts exposed the receiving object by +replacing the receiving type with a pointcut formal. These PCDs +should be rewritten to use the new <code>target</code> pointcut to expose +the receiving object. </p> + +<PRE> +pointcut fooCallees(Foo f): receptions(void f.m()); +==> +pointcut fooCallee(Foo f): target(f) && call(void m()); +</PRE> + +<p> Like <a href="#1.0a1-fixing-state-access">other pointcuts</a>, +receptions pointcuts that exposed one or more arguments should be +rewritten to use the <code>args</code> pointcut: </p> + +<PRE> +pointcut intPassers(int i, int j): receptions(void Foo.m(i, j)); +==> +pointcut intPasser(int i, int j): + args(i, j) && target(Foo) && call(void m(int, int)); +</PRE> + +<h5>Constructor receptions</h5> + +<p> There are two issues with constructor receptions in +particular. </p> + +<p>Like <a href="#1.0a1-constructor-calls">constructor calls</a>, +constructor receptions pointcuts had a dynamic character, in that +<code>receptions(C.new())</code> would capture constructions of not +only C classes, but also of classes that extended C. </p> + +<p> If you want this behaviour, then you need to use the new subtypes +operator, +, on the type name in question. So, +</p> + +<PRE> +receptions(C.new()) +==> +call(C+.new()) +</PRE> + +<p>Also like <a href="#1.0a1-constructor-calls">constructor calls</a>, +constructor receptions allowed access to the constructed object in the +same way as any other object. Since the only advice possible on +constructor receptions join points was <code>after returning</code> +advice, the object was always guaranteed to be there. But since +constructor call join points allow all kinds of advice it may be that +the object isn't constructed yet (say, in before or around advice). +This is a benefit, in that it allows caching constructed objects </p> + +<PRE> +aspect Singleton { + private C theC = null; + + C around(): call(C.new(..)) { + if (c == null) theC = proceed(); + return theC; + } +} +</PRE> + +<p> but it does require some rewriting. The new object can be +accessed as the return value in after returning advice. So, </p> + +<PRE> +after(Point p) returning (): receptions(p.new(int, int)) { ... } +==> +after() returning (Point p): call(Point+.new(int, int)) { ... } +</PRE> + +<h4><a name="1.0a1-fixing-state-access">Fixing state access</a></h4> + +<p> In previous versions of AspectJ, state such as the currently +executing object or a particular argument of a method call could be +accessed from the signatures of many pointcuts, leading to +difficult-to-read forms. In AspectJ 1.0, all state accesses now use +only three pointcuts </p> + +<blockquote>args this target</blockquote> + +<p> which pick out argument values, the currently executing object, +and the target object of a method call or field operation, +respectively. </p> + +<h5>Using args</h5> + +<p> Any time you have a pointcut that has a signature where one of the +arguments was a pointcut or advice formal, just replace that formal +with its type and add an <code>args</code> pointcut. +</p> + +<PRE> +pointcut intPassers(int i, int j): calls(void Foo.m(i, j)); +==> +pointcut intPasser(int i, int j): args(i, j) && call(void Foo.m(int, int)); +</PRE> + +<PRE> +pointcut stringPassers(String s): receptions(void Foo.m(s, ..)); +==> +pointcut stringPasser(String s): args(s, ..) && call(void Foo.m(String, ..)); +</PRE> + +<h5>Rewriting calls</h5> + +<p> If a calls pointcut exposed the the receiving object, such as </p> + +<PRE> +pointcut fooCallees(Foo f): calls(void f.m()); +</PRE> + +<p> then the new version should use the <code>target</code> pointcut +to get at that object +</p> + +<PRE> +pointcut fooCallee(Foo f): target(f) && call(void Foo.m()); +</PRE> + +<p> AspectJ's calls pointcut previously allowed the new object to be +exposed, even though it may not have been constructed yet. AspectJ +1.0 no longer allows this; you can access the new instance only in +after returning advice, when it is guaranteed that the object was +successfully constructed. So instead of using the <code>target</code> +pointcut to expose the value, you should use the normal <code>after +returning</code> mechanism: +</p> + +<PRE> +after(Point p) returning (): calls(p.new(int, int)) { ... } +==> +after() returning (Point p): call(Point+.new(int, int)) { ... } +</PRE> + + +<h5>Rewriting gets and sets</h5> + +<p> Exposing the target object of a <code>gets</code> or +<code>sets</code> pointcut should be done the same way it was for +<code>calls</code> pointcuts, with the new <code>target</code> +pointcut. </p> + +<PRE> +before(Frame f): gets(Color f.color) { ... } +==> +before(Frame f): target(f) && get(Color Frame.color) { ... } +</PRE> + +<PRE> +before(Frame f): sets(Color f.color) { ... } +==> +before(Frame f): target(f) && set(Color Frame.color) { ... } +</PRE> + +<p> In addition, the clumsy syntax for getting the old value of the +field has been eliminated. For before advice, the port is simple; +just access the field yourself in the body. Depending on the rest of +your system, you may need to restrict the advice from the aspect body +to eliminiate the circularity. </p> + +<PRE> +aspect A { + before(Frame f, Color c): gets(Color f.color)[c] { ... } +} +==> +aspect A { + before(Frame f): + target(f) && get(Color Frame.color) && !within(A) { + Color c = f.color; + ... + } +} +</PRE> + +<p> The same can be done for <code>around</code> advice. However, the +only way to port after advice that needs the old value is to convert +it to around advice. +</p> + +<PRE> +aspect A { + after(Frame f, Color c) returning (): gets(Color f.color)[c] { ... } +} +==> +aspect A { + void around(Frame f): + target(f) && get(Color Frame.color) && !within(A) { + Color c = f.color; + proceed(f); + ... + } +} +</PRE> + +<p> When porting <code>sets</code> pointcuts, the new value of a field +is still available, but not the way it was previously. Instead of +using the square bracket syntax, we use an <code>args</code> pointcut. +All set join points are assumed to have exactly one argument, which +holds the new value. So, </p> + +<PRE> +after(Color newColor): sets(Color Frame.color)[][newColor] { ... } +==> +after(Color newColor): args(newColor) && set(Color Frame.color) { ... } +</PRE> + +<p> Also, if the field was declared private, in order to get at its +old value the aspect must be declared <code>privileged</code>. +</p> + +<h5>Rewriting handlers</h5> + +<p> The value of the exception at an exception handler join point is +now accessed through the <code>args</code> pointcut; all exception +handler join points are treated as having exactly one argument, the +exception value. So, +</p> + +<PRE> +before(NotFoundException e): handlers(e) { ... } +==> +before(NotFoundException e): args(e) && handler(NotFoundException) { ... } +</PRE> + +<h5>Rewriting within</h5> + +<p> The <code>within</code> pointcut was not typically used to export +context. Though it was accidentally possible to do so in versions of +AspectJ before 1.0, it often didn't do what users expected it to. +This loophole has now been closed, and within can only take type +patterns, not pointcut or advice formals. A use of the +<code>this</code> pointcut will capture what previous implementations +did: </p> + +<PRE> +pointcut usesFoo(Foo f): within(f); +==> +pointcut usesFoo(Foo f): this(f) && within(Foo); +</PRE> + +<h4><a name="1.0a1-no-subs-in-sigs">Understanding signatures</a></h4> + +<p> Now that we have <code>this</code>, <code>target</code>, and +<code>args</code> pointcuts, all of our signatures are composed of +just types, names, and wildcards; there are no more parameters. +</p> + +<p> Also, now that we have the <code>+</code> wildcard to pick out +<a href="#1.0a1-subtypes-to-plus">subtypes</a>, we can make signature +matching much more uniform.</p> + +<p> Previously, some signatures matched based on subtypes, some based +on instanceof, and some exactly. Now, we have made all signatures +match exactly. +</p> + +<p> What does this mean for your program? Well, it means that you +may have to add <code>+</code> to some of your signatures, depending +on what you meant them to match. +</p> + +<p> For example, the pointcut +</p> + +<pre> +calls(void m(Object)) +</pre> + +<p> previously picked out all method calls to a method named m that +took one argument, which was a subtype of Object. Now, however, it +will only pick out method calls to methods that are defined to take +exactly the type Object, which may be a lot fewer join points. If you +want the old behaviour, simply convert to </p> + +<pre> +call(void m(Object+)) +</pre> + +<h4><a name="1.0a1-fixing-instanceof">Removing the instanceof pointcut</a></h4> + +<p> The intanceof pointcut has been split into two different +pointcuts, <code>this</code> and <code>target</code>. </p> + +<p> Typically, the instanceof pointcut would only exist in a compound +pointcut, composed (with <CODE>&&</CODE>) with another +pointcut. If the other pointcut was a <code>receptions</code> +pointcut, then <code>instanceof</code> should be converted to +<code>target</code> (and <code>receptions</code> converted to +<code>call</code>). So, </p> + +<PRE> +pointcut stateChanges(Subject s): + instanceof(s) && receptions(void Button.click()); +==> +pointcut stateChange(Subject s): + target(s) && call(void Button.click()); +</PRE> + +<p> In all other cases, <code>instanceof</code> referred to the +currently executing object, and so should be converted into +<code>this</code></p> + +<PRE> +before(Point p): instanceof(p) && executions(* makePolar(..)) { ... } +==> +before(Point p): this(p) && execution(* makePolar(..)) { ... } +</PRE> + +<PRE> +pointcut setup(Client c): instanceof(c) && calls(Remote Naming.lookup(String)); +==> +pointcut setup(Client c): this(c) && calls(Remote Naming.lookup(String)); +</PRE> + +<h4><a name="1.0a1-initializations">Rewriting the initializations pointcut</a></h4> + +<p> Object initialization join points are now more complicated, and +more true to Java's execution model. Now they bracket all of the +initialization that a class can do, after the return of its super +constructor call (before which no initialization can happen). Previous +versions of AspectJ had object initialization join points that only +included initialization that was made in dynamic initializers and +fields. </p> + +<p> The old behaviour can be recovered with a simple rewrite. +</p> + +<PRE> +initializations(A) +==> +initialization(A.new(..)) && !execution(A.new(..)) +</PRE> + +<h4><a name="1.0a1-constructor-calls">Understanding constructor calls</a></h4> + +<p> Previously, constructor call join points were matched by subtypes, +so <code>calls(Foo.new())</code> would match both calls to create new +<code>Foo</code> objects, and new <code>SubFoo</code> objects. The +new <code>call</code> pointcut designator matches types exactly, so if +you want the old behaviour, you should write +<code>call(Foo+.new())</code>. </p> + +<p> Similarly, constructor execution join points were matched by +subtypes. So the old <code>executions(Foo.new())</code> is now +represented by <code>execution(Foo+.new())</code>. +</p> + +<p> In both of these cases, think before using the + operator; it may +be that you didn't intend subtype matching in the first place. </p> + +<h4><a name="1.0a1-hasaspect">Removing the hasaspect pointcut</a></h4> + +<p> The <code>hasaspect</code> pointcut is no longer defined, but you +can get the same behaviour using the new <code>if</code> pointcut. +</p> + +<p> If the aspect whose presense you are checking for was defined +<code>of eachcflow</code>, <code>of eachcflowbelow</code>, or, more +unlikely, <code>of eachJVM()</code>, then the conversion is simple: +</p> + +<PRE> +hasaspect(A) +==> +if(A.hasAspect()) +</PRE> + +<p> If the aspect was defined <code>of eachobject</code>, then you +will have to expose the current object in your pointcut or advice +parameters: </p> + +<PRE> +pointcut cut(): hasaspect(A) ... ; +==> +pointcut cut(Object o): this(o) && if(A.hasAspect(o)) ... ; +or +pointcut cut(Object o): target(o) && if(A.hasAspect(o)) ... ; +</PRE> + +<p> If you were using the <code>hasaspect</code> pointcut to expose +the state of the aspect, then you can get the same state by using +<code>A.aspectOf()</code> in the body of the advice. For example, if +the aspect A were defined <code>of eachcflow</code>, then +</p> + +<PRE> +before(A myA): hasaspect(myA) { + myA.checkStatus(); +} +==> +before(): if(A.hasAspect()) { + A myA = A.aspectOf(); + myA.checkStatus(); +} +</PRE> + +<h4><a name="1.0a1-withinall">Removing the withinall pointcut</a></h4> + +<p> The withinall poinctut is no longer defined. You can use a +combination of within and the <a href="#1.0a1-subtypes-to-plus">new +subtypes operator</a>, +, instead. You'll save two characters and be +using a simpler and more orthogonal language. </p> + +<PRE> +withinall(Foo) +==> +within(Foo+) +</PRE> + +<h4><a name="1.0a1-user-defined-returns">Removing returns modifier from pointcuts</a></h4> + +<p>The returns keyword is no longer necessary for user-defined +pointcuts. Simply remove it when you find it. </p> + +<PRE> +pointcut publicIntCalls() returns int: calls(public int *(..)); +==> +pointcut publicIntCall(): call(public int *(..)); +</PRE> + +<h4><a name="1.0a1-static-pointcuts">Making some pointcuts static</a></h4> + +<p> In Java, only static members may be accessed by their declaring +type name, like the static method <code>Math.max()</code> can be +accessed. </p> + +<p> Pointcuts now have that property too. Pointcuts may be declared +to be static, in which case they can be accessed like +<code>MyAspect.move()</code>, or they can be left non-static, in which +case they can be overridden by a subaspect. </p> + +<p> In addition, while pointcuts can still be defined in classes, only +<code>static</code> pointcuts can be defined in classes. </p> + +<p> Porting should be straightforward; just make all your pointcuts in +classes <code>static</code>, and make any pointcut with a qualified +reference static. +</p> + +<h3><a name="1.0a1-type-patterns">Type patterns</a></h3> + +<h4><a name="1.0a1-new-wildcards">Understanding * and .. in type patterns</a></h4> + +<p> Previous versions of AspectJ treated * and .. too cleverly in type +patterns, placing restrictions based on what is a package and what is +a type, and basing their meanings on the definition of a package +hierarchy. </p> + +<p> In AspectJ 1.0, both of these wildcards are defined simply, and +textually: +</p> + +<ul> + <li> The * wildcard alone matches all types. </li> + + <li> The * wildcard in a pattern matches zero or more characters, + but will not match "." </li> + + <li> The .. wildcard matches any sequence of characters that begins + and ends with "." </li> +</ul> + +<p> That's it. +</p> + +<p> This change won't affect most programs, but it will make +understanding programs easier. There is one ugly idiom, however, that +this change disposes of. If your program includes the type pattern +<code>*..*</code>, which used to match all types, you can replace it with the +much simpler *. </p> + +<PRE> +pointcut unaryVoidMethods(): call(void *(*..*)); +==> +pointcut unaryVoidMethod(): call(void *(*)); +</PRE> + +<h4><a name="1.0a1-subtypes-to-plus">Fixing subtypes in introduction</a></h4> + +<p> The new + operator is used to normalize the many places you want +to use subtypes of some types. +</p> + +<p> In introduction forms, you will need to replace +<code>subtypes(<var>TypePattern</var>)</code> type patterns with the +new subtype operator, +. In the case where you wrote +<code>subtypes(Foo)</code>, i.e., the subtypes of a single type, +simply replace this with <code>Foo+</code>. Otherwise, use the ++ operator as appropriate in <var>TypePattern</var>. </p> + +<PRE> +public void (subtypes(Target0 || Target1)).accept(Visitor v) { + v.visit(this); +} +==> +public void (Target0+ || Target1+).accept(Visitor v) { + v.visit(this); +} +</PRE> + +<h3><a name="1.0a1-advice">Advice</a></h3> + +<h4><a name="1.0a1-around-returns">Moving the return type of around</a></h4> + +<p> The returns keyword is no longer used for around advice. Instead, +the return type is declared as it is for methods. So, </p> + +<PRE> +around(Point p) returns void: setters(p) { ... } +==> +void around(Point p): setter(p) { ... } +</PRE> + +<h4><a name="1.0a1-around-throws">Adding a throws clause to around</a></h4> + +<p> Around advice must now declare the checked exceptions it throws +with a <code>throws</code> clause, much like a method. +</p> + +<PRE> +char around(char c) throws java.io.CharConversionException: converter(c) { + char result; + try { result = proceed(); } + catch (Exception e) { + throw new java.io.CharConversionException(); + } + if (result == 0) throw new java.io.CharConversionException(); + return result; +} +</PRE> + +<h4><a name="1.0a1-advice-precedence">Understanding advice precedence</a></h4> + +<p> In previous versions of AspectJ, advice precedence within an +aspect was simple: if a piece of advice appeared before another piece, +it was more precedent. This made perfect sense for +<code>before</code> and <code>around</code> advice, but was the cause +of confusion (even among the AspectJ designers, more than once) for +<code>after</code> advice, as it seemed backward. </p> + +<p> In addition, advice was ordered by kind, in that around advice +always surrounded before and after advice. +</p> + +<p> AspectJ 1.0 has changed this; precedence for <code>after</code> +advice is inverted, and advice is no longer ordered by kind. +</p> + +<p>This won't matter to you unless you write pieces of advice in the +same aspect that apply to the same join point. </p> + +<p>If you do, here's what to think about: If you're looking at two +pieces of advice and want to know which has precedence, if either is +<code>after</code> advice, then the second one has precedence. +Otherwise, the first does. </p> + +<p> This allows interesting advice interaction. In the following +advice, for example, the <code>after throwing</code> advice will catch +the exception thrown by the <code>before</code> advice </p> + +<PRE> +aspect A { + before(): call(void main(..)) { + throw new RuntimeException(); + } + after() throwing(RuntimeException e): call(void main(..)) { + System.err.println("caught you!"); + } +} +</PRE> + +<p> But reversing the order will give the <code>before</code> advice +more precedence, making its exception uncatchable by the <code>after +throwing</code> advice +</p> + +<PRE> +aspect A { + after() throwing(RuntimeException e): call(void main(..)) { + System.err.println("missed you!"); + } + before(): call(void main(..)) { + throw new RuntimeException(); + } +} +</PRE> + +<p> Advice in <em>different</em> aspects is ordered by the normal aspect +precedence rules of subtyping and the <code>dominates</code> modifier. +</p> + +<h4><a name="1.0a1-after-returning">Fixing after returning</a></h4> + +<p> If you use after returning advice and do not need to expose the +return value, you no longer need to write an empty set of parentheses +to indicate that fact. So, </p> + +<pre> +after(<var>Formals</var>) returning (): <var>Pointcut</var> { ... } +==> +after(<var>Formals</var>) returning: <var>Pointcut</var> { ... } +</pre> + +<p> The same syntax is now available for after throwing advice, in +case you do not care what <code>Throwable</code> is thrown. +</p> + +<pre> +after(<var>Formals</var>) throwing: <var>Pointcut</var> { ... } +</pre> + +<h4><a name="1.0a1-this-static-join-point">Renaming thisStaticJoinPoint</a></h4> + +<p> <code>thisStaticJoinPoint</code> has been renamed +<code>thisJoinPointStaticPart</code>, to reflect that it is now +exactly the static part of <code>thisJoinPoint</code>: It will return +the same object as <code>thisJoinPoint.getStaticPart()</code>. </p> + +<h4><a name="1.0a1-this-join-point">Converting access to thisJoinPoint</a></h4> + +<p> The <code>JoinPoint</code> object hierarchy has been folded into a +single class, <code>org.aspectj.lang.JoinPoint</code>. A common +pattern in logging, for example, was </p> + +<pre> +before() executions(* myMethod()) { + ExecutionJoinPoint jp = (ExecutionJoinPoint)thisJoinPoint; + CodeSignature jp = (CodeSignature)jp.getSignature(); + System.err.println(jp.getParameters()); + System.err.println(jp.getParameterNames()); +} +</pre> + +<p> While there is still a rich hierarchy for signatures, there is +only one <code>JoinPoint</code> type, so this can be rewritten as: +</p> + +<pre> +before() executions(* myMethod()) { + JoinPoint jp = thisJoinPoint; + CodeSignature jp = (CodeSignature)jp.getSignature(); + System.err.println(jp.getArgs()); + System.err.println(jp.getParameterNames()); +} +</pre> + +<p> Some of the method names of <code>JoinPoint</code> have been +reorganized, as well. </p> + +<h3><a name="1.0a1-introduction-and-static">Introduction and static crosscutting</a></h3> + +<h4><a name="1.0a1-plus-implements-extends">Removing +implements and +extends</a></h4> + +<p> The keywords <code>+implements</code> and <code>+extends</code> no +longer exist. Instead, AspectJ uses the <code>declare</code> +form for exactly the same functionality. </p> + +<PRE> +Point +implements Serializable; +=> +declare parents: Point implements Serializable; +</PRE> + +<PRE> +MyButton +extends ButtonAdaptor; +=> +declare parents: MyButton extends ButtonAdaptor; +</PRE> + +<h4><a name="1.0a1-now-use-soft">Using declare soft</a></h4> + +<p> Around advice advice no longer effects the static exception +checking of Java. This means that the following code previously +compiled: </p> + +<PRE> +class C { + void noExceptionDeclared() { + exceptionDeclared(); + } + void exceptionDeclared() throws IOException {} +} +aspect A { + around(): call(void C.exceptionDeclared()) { + try { proceed(); } + catch (IOException e) {} + } +} +</PRE> + +<p> even though the class C is not compilable on its own (because +noExceptionDeclared actually throws an Exception). +</p> + +<p> AspectJ now firmly places everything that affects the type system +of Java, including the declared-exception checking system, into the +space of introduction and declare. So, in order to state that the +call to exceptionDeclared() will not, actually, throw an exception, we +now "soften" that exception, that is, take it out of the space of +declared exceptions. </p> + +<pre> +declare soft: <var>ExceptionType</var>: <var>Pointcut</var>; +</pre> + +<p> The pointcuts allowed here are limited; you cannot use pointcuts +that would require runtime information. But picking out method calls +is just fine. So in order to make the above example work, one new +declaration is needed: +</p> + +<PRE> +declare soft: IOException: + call(void C.exceptionDeclared()) && + withincode(void noExceptionDeclared()); +</PRE> + +<h3><a name="1.0a1-aspects">Aspects</a></h3> + +<p> The syntax of "of each" modifiers has changed. For <code>of +eachcflow</code> and <code>of eachcflowbelow</code>, you can simply +replace "of each" with "per". So, </p> + +<PRE> +aspect A of eachcflow(...) { ... } +==> +aspect A percflow(...) { ... } +</PRE> + +<p> If you have any aspects defined <code>of eachJVM()</code>, then +you should either remove that declaration entirely (because this is +the default behaviour), or replace the <code>of eachJVM()</code> +declaration with an <code>issingleton</code> declaration. +</p> + +<PRE> +aspect of eachJVM() { ... } +==> +aspect A { ... } +or +aspect A issingleton { ... } +</PRE> + +<p> The <code>of eachobject(<var>Pointcut</var>)</code> modifier has +been split into two different forms, <code>of +perthis(<var>Pointcut</var>)</code> and <code>of +pertarget(<var>Pointcut</var>)</code>. Which one you replace with +depends on the <var>Pointcut</var> you use. +</p> + +<p> If you use a pointcut that picked out reception join points, then +use <code>pertarget</code>, and rewrite the pointcut to pick out call +join points. So +</p> + +<PRE> +aspect Shadow + of eachobject(receptions(void Point.setX(int)) || + receptions(void Point.setY(int))) { + ... +} +==> +aspect Shadow pertarget(call(void Point.setX(int)) || + call(void Point.setY(int))) { + ... +} +</PRE> + +<p> Otherwise, in most cases, use <code>perthis</code>. When you +convert, remember the meaning of each of these modifiers. +<code>perthis(<var>Pointcut</var>)</code> indicates that an instance +of the aspect should be associated with every object that is +<code>this</code> at each of the join points picked out by +<var>Pointcut</var>, while <code>pertarget(<var>Pointcut</var>)</code> +associates with every object that is the target object at such join +points. </p> + +<!-- ==================================== --> +<!-- ==================================== --> +<!-- ==================================== --> + +<hr /> + +<h2><a name="pre08b3">Porting pre-0.8beta3 code</a></h2> + +<ul> + <li><a href="#cflowTerminology">Changing cflow terminology</a></li> + <li><a href="#abstractPointcuts">Overriding abstract pointcuts</a></li> + <li><a href="#recursiveAdvice">Limiting recursive advice</a></li> +</ul> + + +<p>The following changes are only required when porting code written +prior to the 0.8beta3 release of AspectJ.</p> + +<h3><a name="cflowTerminology">Changing cflow terminology</a></h3> + +<p> Changing pre-0.8beta3 code that uses AspectJ's control-flow-based +features only requires rewriting occurrences of +<code>eachcflowroot</code>, <code>cflow</code>, and +<code>cflowtop</code>. No editing of other aspect code is +necessary.</p> + +<h4>eachcflowroot</h4> + +<p> The aspect modifier "<code>of +eachcflowroot(<var>Pointcut</var>)</code>" should now be written more +as "<code>percflow(<var>Pointcut</var>)</code>". </p> + +<h4>cflow</h4> + +<p> In previous versions of AspectJ, the pointcut +<code>cflow(<var>Pointcut</var>)</code> picked out all join points in +the cflow below the join points of <var>Pointcut</var>. That is, it +did not include the join points of <var>Pointcut</var>, only the join +points in their control flow. +</p> + +<p> As of version 0.8beta3, +<code>cflowbelow(<var>Pointcut</var>)</code> has that behavior. +<code>cflow(<var>Pointcut</var>)</code> includes the join points of +<var>Pointcut</var>. </p> + +<p> In many cases, you may not care whether the points of +<var>Pointcut</var> are included or not, and so can safely leave +<code>cflow(<var>Pointcut</var>)</code> pointcut designators alone. +However, if you use the idiom +</p> + +<pre class="codeindent"> +<var>Pointcut</var> && ! cflow(<var>Pointcut</var>) +</pre> + +<p> to capture the non-recursive entries to a particular pointcut, you +will definitely want to rewrite that as +</p> + +<pre class="codeindent"> +<var>Pointcut</var> && ! cflowbelow(<var>Pointcut</var>) +</pre> + +<h4>cflowtop</h4> + +<p> The primitive pointcut designator +<code>cflowtop(<var>Pointcut</var>)</code> has been removed from the +language, as it is expressible with <code>cflow</code> or +<code>cflowbelow</code>. All uses of +<code>cflowtop(<var>Pointcut</var>)</code> can be rewritten as: +</p> + +<pre class="codeindent"> +cflowbelow(<var>Pointcut</var> && ! cflowbelow(<var>Pointcut</var>)) +</pre> + +<p> Though in most cases the following is sufficient +</p> + +<pre class="codeindent"> +cflow(<var>Pointcut</var> && ! cflowbelow(<var>Pointcut</var>)) +</pre> + +<h3><a name="abstractPointcuts">Overriding abstract pointcuts</a></h3> + +<p> In previous versions of AspectJ, a concrete aspect would +implicitly override all of its abstract pointcuts with an empty +pointcut. AspectJ 0.8beta3 enforces the restriction that a concrete +aspect may not have any abstract pointcuts. Thus the following +extension:</p> + +<pre class="codeindent"> +abstract aspect A { + abstract pointcut pc(); +} + +aspect B {} +</pre> + +<p> will no longer compile. +</p> + +<p> Adding the new empty pointcut designator +</p> + +<pre class="codeindent"> +pointcut <var>Id</var>(); +</pre> + +<p> in the declaration of the concrete aspect fixes this problem. +</p> + +<pre class="codeindent"> +abstract aspect A { + abstract pointcut pc(); +} + +aspect B { + pointcut pc(); +} +</pre> + +<h3><a name="recursiveAdvice">Limiting recursive advice</a></h3> + +<p> Previously, the compiler silently refrained from applying a piece +of advice to join points within its own advice body. So, for example, +in </p> + +<pre class="codeindent"> +class C { + static int i; +} + +aspect A { + before(): gets(int C.i) { + System.err.println("C.i was " + C.i) + } +} +</pre> + +<p> The advice would trace all references of the static field +<code>C.i</code> except those in the body of the before. </p> + +<p> The compiler has now removed this special case, and so running the +above example will now cause a <code>StackOverflowException</code> to +be thrown. </p> + +<p> Most cases of this error can be fixed by correctly specifying the +desired pointcut: In the above example, the intention is clearly not +to trace <em>all</em> references of <code>C.i</code>, just those +outside the aspect. +</p> + +<pre class="codeindent"> +class C { + static int i; +} + +aspect A { + before(): get(int C.i) && ! within(A) { + System.err.println("C.i was " + C.i) + } +} +</pre> + +<p> In a very few cases, you may want the advice to be applicable to +other code in the aspect, but not in the particular piece of advice. +In such cases, you can pull the body of the advice into a method and +restrict away from that method (and away from calls to that method): +</p> + +<pre class="codeindent"> +class C { + static int i; +} + +aspect A { + public static int getCi() { + return C.i; // will be traced + } + + before(): get(int C.i) && + ! withincode(void A.traceCi()) + ! call(void A.traceCi()) { + traceCi(); + } + private void traceCi() { + System.err.println("C.i was " + C.i) // will not be traced + } +} +</pre> + + +<!-- ============================== --> + +<hr /> +<h2><a name="pre08b1">Porting pre-0.8beta1 code</a></h2> + +<ul> + <li><a href="#introSyntax">Rewriting introductions</a></li> + <li><a href="#staticAdvice">Removing static advice</a></li> + <li><a href="#aspect-aspect">Fixing aspect-aspect inheritance</a></li> + <li><a href="#usingPrivateIntroduction">Using private introduction</a></li> +</ul> + +<p>The following changes are only required when porting code written +prior to the 0.8beta1 release of AspectJ.</p> + +<h3><a name="introSyntax">Rewriting introductions</a></h3> + +<h4>Syntax</h4> + +<p> The syntax of introduction has changed. Porting most programs +should require some simple editing. Anywhere you have an introduction +block</p> + +<pre class="codeindent"> +introduction <var>GTN</var> { + ... +} +</pre> + +<p> simply move the <var>GTN</var> down into the introduction +declarations and remove the block.</p> + +<p>For method introduction, place the <var>GTN</var> in front of the +method name, For field introduction, place the <var>GTN</var> in front +of the field name, and for constructor introduction, place the +<var>GTN</var> in front of the <code>new</code> identifier. </p> + +<pre class="codeindent"> +introduction Foo { + public void doStuff() { this.doStuffLater(); } + public int calorieCount = 3; + public new(int x) { super(); calorieCount = x; } +} + +==> + +public void Foo.doStuff() { this.doStuffLater(); } +public int Foo.calorieCount= 3; +public Foo.new(int x) { super(); calorieCount = x; } +</pre> + +<p> For implements and extends introduction, move the <var>GTN</var> +in front of the new identifiers <code>implements</code> or +<code>extends</code>, and place that in a <code>declare parents</code> +form. +</p> + +<pre class="codeindent"> +introduction Foo { + implements Comparable; + extends Goo; +} + +==> + +declare parents: Foo implements Comparable; +declare parents: Foo extends Goo; +</pre> + +<p> In all cases, if the <var>GTN</var> is just a type name, it can be +moved down on its own. However, if the <var>GTN</var> uses any of +<CODE>&&</CODE>, <code>||</code>, and <code>!</code>, it must +be parenthesized. </p> + +<pre class="codeindent"> +introduction subtypes(Foo) && !Goo { + int x; +} + +==> + +int (Foo+ && !Goo).x; +</pre> + + +<h4>Access</h4> + +<p>If you had an introduction that was referring to private or +protected members of the target class, this will no longer work. You +will either need to modify your code to avoid this accessibility +issue, or you will need to use the <code>privileged</code> modifier on +the aspect that contains the introduction.</p> + +<pre class="codeindent"> +class Counter { + private int count = 2; +} + +aspect ExposeCountersPrivates { + introduction Counter { + public int getCount() { return count; } + } +} + +==> +// in 0.8, only privileged aspects can expose a class's privates +privileged aspect ExposeCountersPrivates { + public int Counter.getCount() { return count; } +} +</pre> + + +<p> If you have introduced private or package-protected members, you +will probably have to re-write some code. Most previous uses of +introducing privates can be improved by using private introduction +instead.</p> + +<pre class="codeindent"> +class C { +} + +aspect AddCounter { + introduction C { + private int count; + public int getCount() { return count; } + } +} + +==> +aspect AddCounter { + private int Counter.count; + public int Counter.getCount() { return count; } +} +</pre> + +<p> There is one case that we know of where the inability to perform +the introduction of private members makes 0.7 code difficult to +port to 0.8. If you were using the introduction of a <code>private +void writeObject(..)</code> or a <code>private void +readObject(..)</code> method to interact with Java's serialization +API, you will need to come up with an alternative design. Using some +combination of <code>Externalizable</code>, +<code>writeReplace(..)</code> and/or <code>readResolve(..)</code> +methods should allow you to port your code. If you find this isn't +the case, we'd like to hear about it. + + +<p> If you were introducing either a protected member or a +package-private member onto a class in order to override a protected +member that was inherited from a superclass, you will have to make +this introduction public. <p> + + +<h3><a name="staticAdvice">Removing static advice</a></h3> + +<p> Static advice has been removed from the language. Now, every +piece of advice is non-static, meaning that it will run in the context +of an aspect instance. +</p> + +<p> If you have an aspect that only contains static advice, has no +"of" clause or is declared "of eachJVM()", and is not extended by +another aspect, simply remove the keyword "static" from all pieces of +advice, and make sure the aspect is not defined with the "abstract" +modifier. </p> + +<pre class="codeindent"> +aspect Tracing { + static before(): executions(* *(..)) { + System.out.println("Got Here! " + thisJoinPoint); + } +} + +==> + +aspect Tracing { + before(): execution(* *(..)) { + System.out.println("Got Here! " + thisJoinPoint); + } +} +</pre> + +<p> Otherwise, if you have an aspect contains both static and +non-static advice, is extended, or is "of eachObject(...)" or "of +eachcflowroot(...)", you should group your static advice together and +put it in a new aspect, possibly even an inner aspect. </p> + +<pre class="codeindent"> +aspect ComplexTracing of eachobject(cflow(executions(void Main.main(..)))) { + static before(): executions(* *(..)) { + System.out.println("Got Here! " + thisJoinPoint); + } + static after(): executions(* *(..)) { + System.out.println("Returned! " + thisJoinPoint); + } + + // some other dynamic advice, fields, etc +} + +==> + +aspect ComplexTracing of eachobject(cflow(executions(void Main.main(..)))) { + static aspect AlwaysTracing { + before(): execution(* *(..)) { + System.out.println("Got Here! " + thisJoinPoint); + } + after(): execution(* *(..)) { + System.out.println("Returned! " + thisJoinPoint); + } + } + + // some other dynamic advice, fields, etc +} +</pre> + +<h3><a name="aspect-aspect">Fixing aspect-aspect inheritance</a></h3> + +<p> Aspects can now only extend abstract aspects. This restriction +may cause some redesign of aspect hierarchies. You will probably find +that for the majority of your code the most serious change this +requires is to add an explicit <code>abstract</code> modifier to a +super-aspect that was already implicitly abstract.</p> + +<pre class="codeindent"> +aspect BaseTracing { + abstract pointcut traced(); + before(): traced() { + System.out.println("Got Here! " + thisJoinPoint); + } +} + +==> + +// make this abstract aspect explicitly abstract +abstract aspect BaseTracing { + ... +} +</pre> + + +<p> This change has also affected the <code>getAspect</code> static +method. Now, <code>getAspect</code> is only defined on non-abstract +aspects. Previously, you could call <code>getAspect</code> on an +abstract superaspect and (sometimes) get an instance of a subaspect +back. </p> + +<p>This pattern was used in the Spacewar example in the AspectJ +distribution. We had the class hierarchy </p> + +<pre> + SpaceObject (abstract) + |- Ship + |- Bullet + |- EnergyPellet +</pre> + +<p> And the aspect hierarchy +</p> + +<pre> + SpaceObjectDA (abstract) + |- ShipDA of eachobject(instanceof(Ship)) + |- BulletDA of eachobject(instanceof(Ship)) + |- EnergyPacketDA of eachobject(instanceof(Ship)) +</pre> + +<p> And we would call <code>SpaceObjectDA.getAspect(SpaceObject)</code> to access +the aspect associated with a ship, bullet, or energy pellet. This +pattern depended on the <code>SpaceObjectDA</code> aspect hierarchy +exactly mirroring the <code>SpaceObject</code> hierarchy, and being +maintained that way. </p> + +<p> A better way to implement this kind of design aspect is to use +private introduction, a new feature of AspectJ. +</p> + +<h3><a name="usingPrivateIntroduction">Using private introduction</a></h3> + +<p> A common pattern for AspectJ programs that need to associate some +state with every object of a particular type has been to use aspects +that are defined <code>of eachobject(instanceof(...))</code>. A prime +example of this was the <code>BoundPoint</code> aspect of the bean +example: which needed to associate each point with a +<code>PropertyChangeSupport</code> object. </p> + +<pre class="codeindent"> +aspect BoundPoint of eachobject(instanceof(Point)) { + + java.beans.PropertyChangeSupport support = null; + + after() returning(Point p): receptions(p.new(..)){ + support = new PropertyChangeSupport(myPoint); + } + + around(Point p) returns void: receptions(void p.set*(*)) { + // code that uses support + } +} +</pre> + +<p> In the new version of AspectJ, a better way of accomplishing many +of these state association is to use privately introduced fields. +Instead of creating an aspect instance for every <code>Point</code> +object, store the <code>PropertyChagneSupport</code> object in the +<code>Point</code> objects themselves. +</p> + +<pre class="codeindent"> +aspect BoundPoint { + private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); + + void around(Point p): setters(p) { + // code that uses p.support + } +} +</pre> + +<p> Just as in the past, the PropertyChangeSupport object is not +accessable to anyone but the aspect, but now less mechanism is needed. +</p> + +<p> There are times when changing aspects that are defined <code>of +eachobject(instanceof(...))</code> may not be reasonable. If the +aspect instance is stored or passed to other methods, then having a +real <code>of eachobject(instanceof(...))</code>, now written +<code>perthis(this(...))</code>, association may capture the +crosscutting concern best. </p> + +<!-- ============================== --> + +<hr /> +<h2><a name="pre07b11">Porting pre-0.7beta11 code</a></h2> + +<ul> + <li><a href="#twoArgumentCalls">Removing two-argument calls</a></li> + <li><a href="#adviceInClasses">Removing advice from Class declarations</a></li> +</ul> + +<p>The following changes are only required when porting code written +prior to the 0.7beta11 release of AspectJ.</p> + +<h3><a name="twoArgumentCalls">Removing two-argument calls</a></h3> + +<p> In AspectJ 0.7beta11, the two-argument <code>calls</code> +primitive pointcut designator was deprecated. Removing these +designators will require different cases depending on what the +original pointcut did. </p> + +<h4>Calls to static methods</h4> + +<p> For pointcuts denoting calls to particular static methods, such as +</p> + +<blockquote><pre> +calls(String, static String valueOf(int)) // deprecated +</pre></blockquote> + +<p> the transformation is easy. Simply make the desired signature +explicit. Instead of catching all calls to any static method that +happens to have the signature <code>String valueOf(int)</code>, catch +calls to that exact method defined in the String class. </p> + +<blockquote><pre> +call(static String String.valueOf(int)) +</pre></blockquote> + +<p> Pointcuts denoting calls to classes of static methods can also be +rewritten with these rules. For example, </p> + +<blockquote><pre> +calls(my.package.*, static * get*(..)) // deprecated +</pre></blockquote> + +<p> should now be written </p> + +<blockquote><pre> +call(static * my.package.*.get*(..)) +</pre></blockquote> + +<h4>Calls to non-static methods</h4> + +<p> Many pointcuts denoting calls to non-static methods can be +fixed the same way that those pointcuts denoting calls to static +methods are fixed. So, +</p> + +<blockquote><pre> +calls(Thread, int getPriority()) // deprecated +</pre></blockquote> + +<p> which denotes all calls to nullary int methods named <code>getPriority</code> +when the called object is an instance of the <code>Thread</code> type, +can almost always be rewritten </p> + +<blockquote><pre> +call(int Thread.getPriority()) +</pre></blockquote> + +<p> which denotes all calls to the nullary int <code>Thread.getPriority()</code> +method. +</p> + +<p> Expanding the signature picks out slightly different join points +than the original two-argument form. This won't matter for most +programs, but in some cases the differences may be noticable. In +particular, the expanded-signature form only picks out those calls +where the called object is statically typed to <code>Thread</code> +when its <code>int getPriority()</code> method is called. If you want +to capture calls to the <code>int Thread.getPriority()</code> method, +regardless of how the called object is statically typed, you shoud use +the different translation: </p> + +<blockquote><PRE> +call(int getPriority()) && target(Thread) +</PRE></blockquote> + +<p> This will capture all call join points of methods with signature +<code>int Thread.getPriority()</code>. </p> + +<p> It will also denote any join points if the Thread type does not +define (possibly abstractly) some <code>int getPriority()</code> +method, though. </p> + + +<h3><a name="adviceInClasses">Removing advice from Class declarations</a></h3> + +<p> The simplest way to remove an advice declaration from a class is +to simply define the advice declaration in an inner aspect. So, +instead of </p> + +<blockquote><pre> +class C { + static before(): executions(C.new()) { ... } // deprecated +} +</pre></blockquote> + +<p> write </p> + +<blockquote><pre> +class C { + static aspect ConstructionProtocol { + static before(): executions(C.new()) { ... } + } +} +</pre></blockquote> + +<p> If your advice doesn't refer to any inner classes or interfaces of +C, you can move the inner aspect out of the class entirely. </p> + +<blockquote><pre> +class C { ... } + +aspect ConstructionProtocol { + static before(): execution(C.new()) { ... } +} +</pre></blockquote> + +<p> Your code will be clearer if you consider the purpose of each +piece of advice when you make this change. It may be that some of the +advice naturally belongs to another aspect, perhaps already existing. +Or it may be that some pieces of advice in a class are associated to +one concern and some to another; in which case more than aspect would +be appropriate. </p> + +<!-- ============================== --> +<hr /> +<h2><a name="pre07b10">Porting pre-0.7beta10 code</a></h2> + +<ul> + <li><a href="#joinPoints">Changing access to thisJoinPoint</a></li> +</ul> + +<p>The following changes are only required when porting code written +prior to the 0.7beta10 release of AspectJ.</p> + + +<h3><a name="joinPoints">Changing access to thisJoinPoint</a></h3> + +<p> In AspectJ 0.7beta10, access to the reflective object +<code>thisJoinPoint</code> substantially changed. The two parts of +this change were the elimination of the <code>runNext()</code> static +method, and the use of an interface hierarchy represent the join point +object. </p> + +<h4><a name="proceed"><code>thisJoinPoint.runNext()</code> to +<code>proceed()</code></a></h4> + +<p> The elimination of the <code>runNext()</code> static method +requires almost no porting work. An automatic replacement of the +string +</p> + +<blockquote><code>thisJoinPoint.runNext</code></blockquote> + +<p> with the string +</p> + +<blockquote><code>proceed</code></blockquote> + +<p> will do the job. However, if any around advice used the +identifier "<code>proceed</code>" as a formal parameter or local +variable, it must be renamed, and if any aspect used it as a field, +then references to the field in around advice should be made explicit +(prefixing the reference with the aspect name or "<code>this</code>", +depending on whether the field is static or not). </p> + +<h4><a name="thisJoinPoint">Using <code>thisJoinPoint</code></a></h4> + +<p> While access to reflective information through +<code>thisJoinPoint</code> is more powerful and regular through its +interface hierarchy, the previous uses must be rewritten. Changing +your code will likely require manual editing, but in doing so your +code should get simpler and cleaner. </p> + +<!-- --> + +<p> Many existing uses of the fields on join points can be re-written +to use one of: +</p> + +<ul> + <li><code>thisJoinPoint.toString()</code></li> + <li><code>thisJoinPoint.toShortString()</code></li> + <li><code>thisJoinPoint.toLongString()</code></li> + <li><code>thisJoinPoint.getSignature().toString()</code></li> + <li><code>thisJoinPoint.getSignature().toShortString()</code></li> + <li><code>thisJoinPoint.getSignature().toLongString()</code></li> +</ul> + +<p>For example: +</p> + +<blockquote><pre> +System.out.println(thisJoinPoint.className + "." + + thisJoinPoint.methodName) +</pre></blockquote> + +<p> can be replaced with +</p> + +<blockquote><code>System.out.println(thisJoinPoint)</code></blockquote> + +<p> or +</p> + +<blockquote><code>System.out.println(thisJoinPoint.getSignature().toShortString())</code></blockquote> + +<p> with comparable behavior. +</p> + +<!-- --> + +<p> Accesses to the parameters field of join points should be changed +as follows. A field access like: +</p> + + +<blockquote><code>thisJoinPoint.parameters</code></blockquote> + +<p> must be changed to: +</p> +<ul> + <li><code>thisJoinPoint.getArgs()</code></li> +</ul> + +<!-- --> + +<p> Accesses to the methodName and className fields of join points +that are not suitable for replacement with a toString method, +should be changed as follows. Field accesses like: +</p> + +<ul> + <li><code>thisJoinPoint.className</code></li> + <li><code>thisJoinPoint.methodName</code></li> +</ul> + +<p> must be changed to: +</p> + +<ul> + <li><code>thisJoinPoint.getSignature().getDeclaringType().getName()</code></li> + <li><code>thisJoinPoint.getSignature().getName()</code></li> +</ul> + +<!-- --> + +<p> Accessses to the parameterNames and parameterTypes fields of +join points, that are not suitable for conversion to one of the +toString() methods should be changed as follows. Field access +like: +</p> + +<ul> + <li><code>thisJoinPoint.parameterNames</code></li> + <li><code>thisJoinPoint.parameterTypes</code></li> +</ul> + +<p> must be changed to: +</p> + +<ul> + <li><code>((CodeSignature)thisJoinPoint.getSignature()).getParameterNames()</code></li> + <li><code>((CodeSignature)thisJoinPoint.getSignature()).getParameterTypes()</code></li> +</ul> + +</body> +</html> |