|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html> <head>
- <title>AspectJ Reference - Porting Notes</title>
- </head>
- <body>
-
- <div align=right><small>
- © Copyright 1998-2002 Palo Alto Research Center Incorporated,
- 2003-2004 Contributors.
- All rights reserved.
- </small></div>
-
- <h1>AspectJ Porting Notes</h1>
-
- <ul>
- <li><a href="#pre-1.2">Pre-1.2 code</a></li>
- <li><a href="#pre-1.1">Pre-1.1 code</a></li>
- <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.2">Porting pre-1.2 code to AspectJ 1.2</a></h2>
- <a href="README-12.html">README-12.html</a> contains a discussion
- of the changes between 1.1 and 1.2. The key points are:
-
- <p><b>The default AspectJ compiler compliance level is now 1.4</b> (whereas in
- previous releases the default compliance level was 1.3). This has a number
- of implications:
- </p>
- <ul>
- <li> class files generated by the compiler are now JRE v1.2 and upwards
- compatible. (At compliance level 1.3, AspectJ generated class files that
- were compatible with JRE 1.1 also).</li>
- <li> <code>call</code> pointcuts may match more join points than in the same
- program compiled at compliance level 1.3.</li>
- </ul>
- <p>
- The AspectJ compiler can be restored to 1.3 compliance settings by specifying the
- "-1.3" option on the command-line.
- </p>
- <p>The following example program illustrates the differences in join point matching
- with the <code>call</code> pointcut designator between 1.4 and 1.3 compliance levels.
- </p>
- <pre>
- <code>
- 01 class A {
- 02 public void doIt() {...};
- 03 }
- 04
- 05 class B extends A {
- 06 public void doThisToo() {...};
- 07 }
- 08
- 09
- 10 public class CallsAandB {
- 11
- 12 public static void main(String[] args) {
- 13 B b = new B();
- 14 A bInDisguise = new B();
- 15
- 16 b.doIt(); // AspectJ 1.2 matches here
- 17 bInDisguise.doIt(); // this is never matched
- 18 }
- 19
- 20 }
- 21
- 22 aspect CallPCDMatchingExample {
- 23
- 24 before() : call(* B.doIt(..)) {
- 25 System.out.println("About to call B.doIt(...)");
- 26 }
- 27
- 28 }
- </code>
- </pre>
- <p>
- When this program is compiled with AspectJ 1.2 using the default compiler options,
- it will produce one line of output when it is executed:
- </p>
- <p><code>About to call B.doIt(...)</code></p>
- <p>The same program compiled under AspectJ 1.1 (or using AspectJ 1.2 with the -1.3 flag specified)
- does not produce any output when it is run.
- </p>
-
- <p>
- The reason for the additional call pcd match is that prior to compliance level 1.4,
- Java compilers produced bytecodes that call A.doIt() (the defining type of the method),
- rather than B.doIt() (the declared type in the program text). The generated call to
- A.doIt() is not matched by the call pcd used in the before advice. At
- compliance level 1.4, the bytecodes retain the declared type of the receiver in the
- program source, generating a call to B.doIt(), which <i>is</i> matched by the call pcd.
- </p>
-
- <p>This is a good example of why the recommended style is to use <code>call(* doIt(..)) && target(B)</code>,
- which always matches based on the actual type of the receiver.
- </p>
-
- <p><b>New warnings emitted by the compiler for unmatched call pcds.</b> Because users have found
- the static type matching used for a type pattern specified in a <code>call</code> pcd confusing
- (as evidenced by the example above), AspectJ 1.2 has a new Xlint warning which is enable by default.
- The compiler will now produce a warning whenever a call pointcut designator does not match at a
- join point, and a user may have expected it to. Compiling the above program using AspectJ 1.2
- produces the following compiler output:
- </p>
-
- <pre>
- <code>
- <font color="red">
- CallsAandB.java:24 warning does not match because declaring type is A, if match desired use target(B) [Xlint:unmatchedSuperTypeInCall]
- before() : call(* B.doIt(..)) {
- ^^^^^^^^^^^^^^^
-
- see also: CallsAandB.java:17
- </font>
- <font color="blue">
- 1 warning
- </font>
- </code>
- </pre>
-
- The warning is telling us that the call pointcut associated with the before advice on line 24 of the source file
- does not match at a join point where the user may have expected it to. The source location
- corresponding to the unmatched join point is indicated by the "see also" line - in this case line 17 of the
- source file. At line 17 we find a call to <code>bInDisguise.doIt()</code>. Since the static type of
- <code>bInDisguise</code> is <code>A</code>, this call will never be matched. The warning also tells us
- a possible solution if we intended the pointcut to match at this join point: use
- <code>call(* doIt(..) && target(B)</code>.
-
- <p>If you find warnings of this kind coming out when you use the AspectJ 1.2 compiler, the recommended fix is to
- switch to using the <code>target</code> designator in place of a type pattern in the <code>call</code> pointcut
- expression. Note that there is no loss of runtime efficiency here - runtime tests are only added in the cases
- where it cannot be determined at compile time whether the type of the receiver will match the type specified in
- the <code>target</code> expression. Note that <code>target</code> cannot be used in <code>declare</code> statements.
- </p>
-
- <p><b>Use of non-statically determinable pointcut expressions in declare statements</b> has always been forbidden,
- but prior to 1.2 the AspectJ compiler did not raise an error if they were used. The AspectJ Language
- Semantics appendix states that <code>cflow, cflowbelow, this, target, args</code> and <code>if</code> pointcut
- designators cannot be used directly or indirectly (through a user-defined pointcut) inside of a <code>declare</code>
- statment. When moving code from 1.1 to 1.2, additional errors may be raised due to the stricter policing of this
- rule. The solution is to recode the declare statement avoiding pointcut expressions that may require a run-time test.
- </p>
-
- <p><b>Interface constructors no longer supported</b>.
- Declaring a constructor on an interface is now (correctly) prohibited,
- and there will no longer be a constructor-execution join point for the interface.
- To initialize a field declared on an interface, use initialization, e.g.,
- </p>
- <pre>int I.i;
- after(I i) returning: initialization(I) && this(i) { i.i = 2; }</pre>
- <p>To pick out the constructor-execution for any implementation of I, try
- </p>
- <pre>execution(I+.new(..))</pre>
-
- <p>For more information, see bug
- <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=49295">49295</a>.
- </p>
-
- <p><b>Declaring a static method on an interface</b> is now (correctly) prohibited.
- One workaround is to define a static method on the aspect instead.
- For more information, see bug
- <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=47754">47754</a>.
- </p>
-
- <p><b>Watch for problems due to incompatible BCEL versions.</b>
- AspectJ 1.2 includes a different version of BCEL than AspectJ 1.1. If you have the older
- version of BCEL available earlier on your classpath than the version included in the
- 1.2 aspectjtools.jar then you will see errors like:
-
- <pre>
- C:\work\test\TestAspect.aj error Internal compiler error
- java.lang.NoSuchMethodError: org.apache.bcel.generic.InstructionFactory.
- createNewArray(Lorg/apache/bcel/generic/Type;S)Lorg/apache/bcel/generic/Instruction;
- </pre>
-
- This typically happens because the old version of BCEL has been included as a standard
- extension in your JVM configuration. Ensure you have removed it from jre/lib/ext
- under your JDK installation.
-
- <p>For more information, see bugs including
- <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=60389">60389</a>,
- <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59921">59921</a>.
- </p>
-
-
- <h2><a name="pre-1.1">Porting pre-1.1 code to AspectJ 1.1</a></h2>
- <a href="README-11.html">README-11.html</a> contains a discussion
- of the language changes from 1.0 to 1.1. The high points:
-
- <p>
- The <code>call(..)</code> pointcut designator is now implemented
- only at the call site; by contrast, the AspectJ 1.0 compiler could
- also implement it on the callee side. So in 1.0 if you
- compiled a pointcut using <code>call(..)</code> but only passed
- the compiler the code for the target of the call, the pointcut
- could be implemented. This is not true for 1.1. To fix this,
- use <code>execution(..)</code> in place of <code>call(..)</code>,
- or include all calling clients in the compile.
- (<a href="README-11.html#NO_CALLEE_SIDE_CALL">more info</a>)
-
- <p>
- Type-patterns are no longer permitted for the defining
- type of inter-type declarations. Replace the pattern with a
- type.
- In many cases, you can declare members on an interface type,
- and then declare that the types picked out by the type-pattern
- implement have the interface as their parent.
- (<a href="README-11.html#SINGLE_INTERCLASS_TARGET">more info</a>)
- <!-- todo code -->
-
- <p>
- Type-patterns are no longer permitted when specifying
- <code>declare soft</code>.
- Replace the pattern with a literal type.
- <!-- todo code -->
-
- <p>
- Wildcards patterns (<code>foo..*</code>) are no longer
- permitted for
- <code>this()</code>,
- <code>target()</code>, or
- <code>args()</code>.
- Replace the pattern with a literal type or
- with a subtype wildcard (<code>Type+</code>).
- (<a href="README-11.html#INSTANCEOF_ON_WILD">more info</a>)
- <!-- todo code -->
- <p>
- Conflicts will be reported for no-argument constructors
- generated by compilers when no constructor is defined
- for a class. That means the following code will compile
- in 1.0 but not in 1.1:
- <pre>
- class C {}
- aspect A {
- C.new() {} // permitted in 1.0; conflict in 1.1
- }
- </pre>
- One fix is to declare a non-conflicting constructor
- by adding arguments (or defining a constructor in the
- target class); a better fix might be to do the work of the
- declared constructor in advice on the initialization
- join point for the object.
- (<a href="README-11.html#DEFAULT_CONSTRUCTOR_CONFLICT">more info</a>)
-
- <p>
- The pointcut designators
- <code>within()</code> and <code>withincode()</code>
- will not pick out
- code within the lexical extent of method-local
- and anonymous inner types (because these are not
- represented as such in bytecode form). Because
- <code>within</code> forms specify staticly-determinable pointcuts,
- they might be used in declare error or declare warning
- statements, which might produce different results.
- (<a href="README-11.html#WITHIN_MEMBER_TYPES">more info</a>)
-
- <p>
- The compiler will report an error that
- the form <code>aspect {name} dominates {list}...</code>
- is no longer supported. It has
- been replaced by a new declare statement:
- <pre>
- declare precedence : {name} {list}...
- </pre>
- (<a href="README-11.html#ASPECT_PRECEDENCE">more info</a>)
-
- <p>
- The field set join point now has a return type of <code>void</code>.
- Compiling programs using around advice on these join points might
- cause errors unless the return type of the around advice
- and the result of any proceed() call is
- <code>Object</code> or <code>void</code>.
- (<a href="README-11.html#VOID_FIELD_SET">more info</a>)
- <p>
-
- The compiler cannot implement after or around advice for
- the handler PCD because the end of exception handlers is
- ambiguous in bytecode. Try to use before advice.
- (<a href="README-11.html#AFTER_HANDLER">more info</a>)
- <p>
-
- <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>
|