aboutsummaryrefslogtreecommitdiffstats
path: root/docs/release/README-1.6.9.adoc
blob: a7923cf01cb5ec30a8db4d13acdbb98374fab8f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
= AspectJ 1.6.9

_© Copyright 2010 Contributors. All rights reserved._

The full list of resolved issues in 1.6.9 is available
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]

== Features

=== declare annotation supports compound signature patterns: https://bugs.eclipse.org/bugs/show_bug.cgi?id=287613[287613]

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

[source, java]
....
declare @method: * is*(): @FooBar;
declare @method: * get*(): @FooBar;
....

Now AspectJ allows compound patterns for declare
@method/@constructor/@field.

[source, java]
....
declare @method: (* is*()) || (* get*()): @FooBar;
....

=== Intertype declaration of member types

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:

[source, java]
....
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");
        }
    }
}
....

Only static member types are supported.

=== 'Optional' aspects: https://bugs.eclipse.org/bugs/show_bug.cgi?id=310506[310506]

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.

Here is an example, 'AspectA' will switch itself off if the type
'a.b.c.Anno' cannot be found:

[source, xml]
....
<aspect name="AspectA" requires="a.b.c.Anno"/>
....

=== Reduction in class file sizes: https://bugs.eclipse.org/bugs/show_bug.cgi?id=312839[312839]

More details here:
http://andrewclement.blogspot.com/2010/05/aspectj-size-is-important.html
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).

=== Transparent weaving: https://bugs.eclipse.org/bugs/show_bug.cgi?id=309743[309743]

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
https://bugs.eclipse.org/bugs/show_bug.cgi?id=309743[309743].

=== Overweaving: https://bugs.eclipse.org/bugs/show_bug.cgi?id=293450[293450]

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
https://bugs.eclipse.org/bugs/show_bug.cgi?id=293450[293450] and in this
http://andrewclement.blogspot.com/2010/05/aspectj-overweaving.html[blog
article]. 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.

=== AOP Scoping: https://bugs.eclipse.org/bugs/show_bug.cgi?id=124460[124460]

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.

Here is an example:

[source, xml]
....
<aspectj>
  <aspects>
    <aspect name="X"/>
    <aspect name="Y" scope="com.foo..*"/>
  </aspects>
  <weaver>
    <include within="com..*"/>
  </weaver>
</aspectj>
....

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.

=== Message inserts for declare warning/error messages

It is now possible to use joinpoint context in the messages attached to
declare warning and declare error constructs. Some examples:

[source, java]
....
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}";
....

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.

=== declare warning/error for type patterns

It is now possible to use a type pattern with declare warning and
declare error. For example:

[source, java]
....
declare warning: I+ && !hasfield(int i): "Implementations of I are expected to have a int field called i";
....

=== Type category type patterns

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:

[source, java]
....
execution(* (!is(InnerType)).m(..)) {}
!within(* && is(InnerType)) {}
....

Options for use in is() are: ClassType, AspectType, InterfaceType,
InnerType, AnonymousType, EnumType, AnonymousType.

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:

[source, java]
....
class Boo {
  void foo() {}
  class Bar {
    void foo() {}
  }
}
....

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.

=== Intertype fields preserve visibility and name

Some users always expect this:

[source, java]
....
class C {
}

aspect X {
  private int C.someField;
}
....

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.

Here is the output of javap when that is built with 1.6.8:

[source, java]
....
class C extends java.lang.Object{
    public int ajc$interField$X$someField;
    C();
}
....

Here is the output of javap when that is built with 1.6.9:

[source, java]
....
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);
}
....

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.

=== AspectJ snapshots in a maven repo

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 `maven.springframework.org/snapshot/org/aspectj` -
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:

[source, xml]
....
<repository>
    <id>maven.springframework.org</id>
    <name>SpringSource snapshots</name>
    <url>http://maven.springframework.org/snapshot</url>
</repository>
....

and then the version to depend upon is: 1.6.9.BUILD-SNAPSHOT

'''''