123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- <html> <head>
- <title>AspectJ 1.6.9 Readme</title>
- <style type="text/css">
- <!--
- P { margin-left: 20px; }
- PRE { margin-left: 20px; }
- LI { margin-left: 20px; }
- H4 { margin-left: 20px; }
- H3 { margin-left: 10px; }
- -->
- </style>
- </head>
-
- <body>
- <div align="right"><small>
- © Copyright 2010 Contributors.
- All rights reserved.
- </small></div>
-
- <h1>AspectJ 1.6.9 Readme</h1>
-
- <p>The full list of resolved issues in 1.6.9 is available <a href="https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced;bug_status=RESOLVED;bug_status=VERIFIED;bug_status=CLOSED;product=AspectJ;target_milestone=1.6.9;target_milestone=1.6.9M1;target_milestone=1.6.9M2;target_milestone=1.6.9RC1">here</a></h2>
-
- <h2>Features</h2>
-
- <h3>declare annotation supports compound signature patterns: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=287613">287613</a></h3>
- <p>Until now it wasn't possible to express a compound pattern in any of the declare annotation constructs that
- take a member signature. For example, if you wanted to attach an annotation to all your getter like methods, you needed
- two constructs</p>
- <pre><code>
- declare @method: * is*(): @FooBar;
- declare @method: * get*(): @FooBar;
- </code></pre>
- <p>Now AspectJ allows compound patterns for declare @method/@constructor/@field.</p>
- <pre><code>
- declare @method: (* is*()) || (* get*()): @FooBar;
- </code></pre>
-
- <h3>Intertype declaration of member types</h3>
-
- <p>It is now possible to ITD member types. The syntax is as would be expected. This example introduces a new member type called
- Inner into type Foo:</p>
- <pre><code>public class Foo {
- public static void main(String[] args) {
- new Inner().run();
- }
- }
-
- aspect Magic {
- public static class Foo.Inner {
- public void run() {
- System.out.println("Inner.run() executing");
- }
- }
- }</code></pre>
- <p>Only static member types are supported.</p>
-
- <h3>'Optional' aspects: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=310506">310506</a></h3>
-
- <p>It is not uncommon to ship a library aspect separately to a jar upon which it depends. In the case of Spring there is
- an aspect library containing a multitude of aspects that attach different technologies (transactions/persistence/etc) to your
- application. Normally an aspect will fail with a "can't find type" style message if a weaver is told to use it and yet it
- references some missing dependency. This can be annoying and require you to include jars on your classpath (or in your maven
- configuration) that you don't actually use, they are *only* there to avoid problems with the aspect. In 1.6.9 you can add
- a setting to these aspects in the aop.xml that makes them optional. The setting mentions a type and if that type cannot be found
- the aspect immediately shuts itself down. This basically means that the aspect is only going to do its job if the type being
- mentioned in the setting is around. This enables the aspect library to be on the aspect path but any aspects within it to
- switch-off if there is nothing for them to do.
- </p>
- <p>Here is an example, 'AspectA' will switch itself off if the type 'a.b.c.Anno' cannot be found:</p>
- <code><pre>
- <aspect name="AspectA" requires="a.b.c.Anno"/>
- </pre></code>
-
- <h3>Reduction in class file sizes: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=312839">312839</a></h3>
-
- <p>More details here: <a href="http://andrewclement.blogspot.com/2010/05/aspectj-size-is-important.html">http://andrewclement.blogspot.com/2010/05/aspectj-size-is-important.html</a>
- but basically some work has been done to improve the serialized form of aspects. As an example, a compiled Roo petclinic sample (which
- uses lots of aspects and ITDs) is down from 1Meg (AspectJ 1.6.9m2) to 630k (AspectJ 1.6.9rc1).</p>
-
- <h3>Transparent weaving: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=309743">309743</a></h3>
- <p>In a further step towards transparent weaving, support for the AjType reflection system is now being made optional.
- This means if intending to use the AjTypeSystem to reflect on woven code, then the code must be built with the
- option -makeAjReflectable. This change is being made because the reflection supporting metadata that
- enables the AjTypeSystem to work can break other tools that are just using regular reflection on the classes. These
- days many more users are processing classes using standard reflection than are using AjTypeSystem. The related bugzilla
- discussing this issue is <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=309743">309743</a>.</p>
-
- <h3>Overweaving: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=293450">293450</a></h3>
-
- <p>Preliminary support for overweaving was added in AspectJ 1.6.7, but now in AspectJ 1.6.9m2 it is much more reliable.
- Basically it is an alternative to reweaving when needing to weave a class multiple times. Overweaving can cope with
- 'other tools' modifying the bytecode in between AspectJ weaves, whereas reweaving cannot. More details are in the related
- bugzilla <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=293450">293450</a> and in this
- <a href="http://andrewclement.blogspot.com/2010/05/aspectj-overweaving.html">blog article</a>. A weaver is switched
- into overweaving mode by the option -Xset:overWeaving=true - which can be specified on the command line or in the weaver
- options section of aop.xml. There is still more work to be done on this feature - any feedback is welcome.</p>
-
- <h3>AOP Scoping: <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=124460">124460</a></h3>
-
- <p>Another feature that had preliminary support a while ago is aspect scoping in aop.xml. This has also been improved in
- AspectJ1.6.9m2. For those not aware of it, it is the ability to specify a scope against aspects defined in your loadtime
- weaving aop.xml file. A scope effectively enables the user to limit the applicability of your aspect to some subset of all those
- types included by the weaver include section. Why is it needed? It can be useful when taking an aspect that did not
- originally scope itself properly (using a within clause) and needing to limit its effect in a load time weaving context.
- Think of it as a within
- pattern that you can put into the aop.xml that augments all the pointcuts defined in the original aspect.</p>
-
- <p>Here is an example:</p>
- <code><pre>
- <aspectj>
- <aspects>
- <aspect name="X"/>
- <aspect name="Y" scope="com.foo..*"/>
- </aspects>
- <weaver>
- <include within="com..*"/>
- </weaver>
- </aspectj>
- </pre></code>
- <p>In this example the weaver include section specifies all the types in com..* should be woven and the
- aspects to be used are X and Y. The new 'scope' setting on aspect Y's definition allows finer control, and specifies that
- Y should in fact only be applied to com.foo..* types.</p>
-
- <h3>Message inserts for declare warning/error messages</h3>
-
- <p>It is now possible to use joinpoint context in the messages attached to declare warning and declare error constructs. Some
- examples:</p>
-
- <code><pre>
- declare warning: execution(* A.m(..)): "joinpoint is {joinpoint}";
- declare warning: execution(* A.m(..)): "joinpoint kind is '{joinpoint.kind}'";
- declare warning: get(int *) && within(A): "joinpoint signature is {joinpoint.signature}";
- declare warning: execution(* A.m(..)): "joinpoint declaring type is {joinpoint.signature.declaringType}";
- declare warning: execution(* A.m(..)): "signature name for method is {joinpoint.signature.name}";
- declare warning: execution(* A.m(..)): "joinpoint location is {joinpoint.sourcelocation.sourcefile}:{joinpoint.sourcelocation.line}";
- declare warning: execution(* A.m(..)): "joinpoint line is '{joinpoint.sourcelocation.line}'";
-
- declare warning: get(int *): "warning is from aspect {advice.aspecttype}";
- declare warning: execution(* A.m(..)): "warning sourcelocation is {advice.sourcelocation.sourcefile}:{advice.sourcelocation.line}";
- </pre></code>
-
- <p>The syntax is to enclose the relevant key within curly brackets within the message. Please raise an enhancement request
- if you need other keys - the set supported so far are all those shown in the example above.</p>
-
-
- <h3>declare warning/error for type patterns</h3>
-
- <p>It is now possible to use a type pattern with declare warning and declare error. For example:</p>
-
- <code><pre>
- declare warning: I+ && !hasfield(int i): "Implementations of I are expected to have a int field called i";
- </pre></code>
-
- <h3>Type category type patterns</h3>
-
- <p>This is the ability to narrow the types of interest so that interfaces can be ignored, or inner
- types, or classes or aspects. There is now a new is() construct that enables this:</p>
-
- <code><pre>
- execution(* (!is(InnerType)).m(..)) {}
- !within(* && is(InnerType)) {}
- </pre></code>
-
- <p>Options for use in is() are: ClassType, AspectType, InterfaceType, InnerType, AnonymousType, EnumType, AnonymousType.</p>
- <p>Note: It is important to understand that "!within(is(InnerType))" and "within(!is(InnerType))" are not the same. The latter one is
- unlikely to be what you want to use. For example here:
- <code><pre>
- class Boo {
- void foo() {}
- class Bar {
- void foo() {}
- }
- }
- </pre></code>
- <p>Bar.foo() will match within(!is(InnerType)) because within considers all surrounding types (so although Bar doesn't match the
- pattern, the surrounding Boo will match it). Bar.foo() will not match !within(is(InnerType)) because Bar will match the pattern
- and then the result of that match will be negated.</p>
-
- <h3>Intertype fields preserve visibility and name</h3>
-
- <p>Some users always expect this:</p>
-
- <code><pre>
- class C {
- }
-
- aspect X {
- private int C.someField;
- }
- </pre></code>
-
- <p>To cause a private field called 'someField' to be added to C. This is conceptually what happens during compilation but if any
- user then later attempts to access someField via reflection or runs a javap against the class file, they will see that isn't
- what happens in practice. A public member is added with a mangled name. For code attempting to access someField built with ajc,
- the visibility of the declaration will, of course, be respected. But for frameworks accessing the code later (typically through
- reflection), it can cause confusion. With AspectJ 1.6.9 the name and visibility are now preserved. Compile time semantics
- remain the same, it is only the weaving process that has changed to produce slightly different output.</p>
- <p>Here is the output of javap when that is built with 1.6.8:</p>
- <code><pre>
- class C extends java.lang.Object{
- public int ajc$interField$X$someField;
- C();
- }
- </pre></code>
- <p>Here is the output of javap when that is built with 1.6.9:</p>
- <code><pre>
- class C extends java.lang.Object{
- private int someField;
- C();
- public static int ajc$get$someField(C);
- public static void ajc$set$someField(C, int);
- }
- </pre></code>
- <p>The name 'someField' is preserved. The visibility is also preserved but because of that we also need to generate some accessors
- to get at the field.</p>
-
- <h3>AspectJ snapshots in a maven repo</h3>
-
- <p>To ease how AspectJ development builds can be consumed, they are now placed into a maven repo. When a new version of AspectJ
- is put into AJDT it is also put into the maven.springframework.org repo.
- The maven compatible repo is <code>maven.springframework.org/snapshot/org/aspectj</code> - and if you browse to it you will
- see it currently contains 1.6.9 dev builds under the name 1.6.9.BUILD-SNAPSHOT.
-
- The repo is added with this magic:</p>
-
- <code><pre>
- <repository>
- <id>maven.springframework.org</id>
- <name>SpringSource snapshots</name>
- <url>http://maven.springframework.org/snapshot</url>
- </repository>
- </pre></code>
- <p>
- and then the version to depend upon is:
-
- 1.6.9.BUILD-SNAPSHOT</p>
-
- <hr>
-
- <h4>
- <!-- ============================== -->
- </body>
- </html>
|