Join point selection pattern language
You can utilize two types of wildcards when constructing your patterns:
..
wildcard as the
"last" thing specified. I.e. this is
not
possible:
foo.bar..test.MyClass
, but this is:
foo.bar..
. The same thing holds for method
parameters.
Combining the patternsThe patterns normally consists of a combination of a class and a method pattern or a class and a field pattern.
Example of a full method pattern:
Example of a full field pattern:
Class selectionsFor the class selections specify the full package name of the class along with some wildcards. Examples:
Method selectionsThe methods are selected by specifying a pattern that consists of:
All method patterns must follow this structure:
Examples
Field selectionsThe fields are selected by specifying a pattern that consists of:
All field patterns must follow this structure:
Examples
Subtype patternsIt is possible to pick out all subtypes of a type with the "+" wildcard. The "+" wildcard follows immediately a type name pattern. So, while
picks out all method call join points where an instance of exactly type Foo is constructed,
picks out all method call join points where an instance of any subtype of Foo (including Foo itself) is constructed. Array type patternsA type name pattern or subtype pattern can be followed by one or more sets of square brackets to make array type patterns. So Object[ ] is an array type pattern, and so is foo.bar.*[ ] [ ] . Abbreviations
When picking out the return and parameter types it is
possible to use predefined abbreviations for the classes
in the
Examples You can use:
Apart from these abbreviations you always have to specify the fully qualified name of the class (along with the wildcards). Passing parameters to advices
You also have the option of passing parameters to your advices.
This can be very convenient if you want to reuse the same
advice but with a different configuration. To pass a parameter
to the advice you simply add a
<advice-def ... > <param name="timeout" value="10"/> </advice-def>
If you prefer the
/** * ... * @aspectwerkz.advice-param advice-ref=advices/MyAdvice * name=timeout * value=10 */ public class MyAdvice extends AroundAdvice {..} You can pass as many parameters to your advices as you want.
At runtime you can then retrieve the parameters in your
String timeOut = getParameter("timeout"); Advice stacks
An
Advice stacks can come in very handy when you have a bunch of
advices that logically belongs together and are used in the same
order at many places in the definition. If the order between the
advices is critical then it is recommended that you arrange the
advices using an
If the order between some advices is critical then it is
recommended that you arrange the advices using an
Example
You define an
<advices-def name="advicestack"> <advice-ref name="acl"/> <advice-ref name="logging"/> <advice-ref name="caching"/> </advices-def>
This
<advice pointcut="pc1"> <advices-ref name="advicestack"/> </advice> Package namespacesYou have two ways of defining a package namespace:
Example
<aspectwerkz base-package="foo"> <!-- All classes are prefixed by 'foo' --> <package name="bar"> <!-- All classes within these 'package' tags are prefixed by 'foo.bar' --> </package> <package name="baz.buzz"> <!-- All classes within these 'package' tags are prefixed by 'foo.baz.buzz' --> </package> </aspectwerkz> Transformation scopesUsing transformation scopes you can choose to perform the transformation within certain packages only. E.g. filter out all classes from all other packages in the transformation process. This can speed up the transformation process a lot as well as assure you that only classes within the packages you have defined is getting transformed no matter how freely you define your pointcut patterns.
A transformation scope is defined using the
Exam ple
<aspectwerkz> <!-- Transformations will only take place within the 'org.codehaus.package' package and its subpackages --> <transformation-scope package="org.codehaus"/> ... </aspectwerkz> DTD for XML definition
The DTD is provided since 0.8. Each distribution comes with a bundled DTD so that it is not looked
for on the web at runtime.
<!DOCTYPE aspectwerkz PUBLIC "-//AspectWerkz//DTD 0.8.1//EN" "http://aspectwerkz.codehaus.org/dtd/aspectwerkz_0_8_1.dtd"> <!DOCTYPE aspectwerkz PUBLIC "-//AspectWerkz//DTD 0.8//EN" "http://aspectwerkz.codehaus.org/dtd/aspectwerkz_0_8.dtd"> The DTD of the latest release is also referenced <!DOCTYPE aspectwerkz PUBLIC "-//AspectWerkz//DTD//EN" "http://aspectwerkz.codehaus.org/dtd/aspectwerkz.dtd"> Example of an XML definition
Here is an example where all the definitions are put together
into a single
<!DOCTYPE aspectwerkz PUBLIC "-//AspectWerkz//DTD 0.8.1//EN" "http://aspectwerkz.codehaus.org/dtd/aspectwerkz_0_8_1.dtd"> <aspectwerkz> <!-- ============================================= --> <!-- Define the advices --> <!-- ============================================= --> <advice-def name="log" advice="advices.LoggingAdvice" deployment-model="perInstance"/> <advice-def name="cache" advice="advices.CachingAdvice" deployment-model="perClass"/> <advice-def name="persistent" advice="advices.PersistenceAdvice" deployment-model="perJVM"/> <advices-def name="log_and_cache"> <advice-ref name="log"/> <advice-ref name="cache"/> </advices-def> <!-- ============================================= --> <!-- Define the introductions --> <!-- ============================================= --> <introduction-def name="serializable" interface="java.io.Serializable"/> <introduction-def name="mixin" interface="mixins.Mixin" implementation="mixins.MixinImpl" deployment-model="perInstance"/> <!-- ============================================= --> <!-- Define the aspects --> <!-- ============================================= --> <abstract-aspect name="MyAbstractAspect"> <advice cflow="facadeCalls" pointcut="setters AND !getters"> <advices-ref name="log_and_cache"/> </advice> <advice pointcut="persistentFields"> <advice-ref name="persistent"/> </advice> </aspect> <aspect name="MyAspect" extends="MyAbstractAspect"> <introduction class="domain.*"> <introduction-ref name="serializable"/> <introduction-ref name="mixin"/> </introduction> <pointcut-def name="facadeCalls" type="cflow" pattern="* *..facade.*.*(..)"/> <pointcut-def name="setters" type="method" pattern="String domain.*.set*(..)"/> <pointcut-def name="getters" type="method" pattern="String domain.*.get*(..)"/> <pointcut-def name="persistentFields" type="setField" pattern="* domain.*.*"> </aspect> </aspectwerkz> Runtime attributes
At the moment you can use attributes to define advices and introductions as well as to reference them in your classes. You can also pass parameters to your advices using attributes.
You compile you attributes using the
If you are defining your whole system
only
using attributes
(yes, it is possible) then you
don't
need the XML definition
at all at runtime. I.e. you can skip the
Definition tagsYou can then use attributes to define both your advices and your introductions. The syntax for the definition attributes are as follows:
After each tag you add the different definition attributes for your advice and/or introduction definition. Examples
/** * @aspectwerkz.introduction-def name=mixins/MyMixin * implementation=mixins.MyMixinImpl * deployment-model=perInstance * attribute=my_mixin */ public interface Mixin {..) /** * @aspectwerkz.advice-def name=advices/MyAroundAdvice * deployment-model=perJVM * attribute=log * @aspectwerkz.advice-param advice-ref=advices/MyAroundAdvice * name=param1 * value=value1 * @aspectwerkz.advice-param advice-ref=advices/MyAroundAdvice * name=param2 * value=value2 */ public class MyAroundAdvice extends AroundAdvice {..) Reference tagsYou can then use these attributes by decorating your source code (methods and fields) with them. The syntax for the reference attributes are as follows:
After each tag you add the attributes that you want to decorate
the method/field with.
If it is a
Example
/** * This class will now have the Mixin with the attribute "my_mixin" applied to it. * * @aspectwerkz.introduction my_mixin */ public class Target {..} /** * This method will now be advised by the advices with the attributes "log" and "cache" * (in this order). * * @aspectwerkz.advice.method log cache */ public Object someMethod(String arg) {..} /** * All the method invocations to this method within the "examples.caching.*" package * are advised by the advice with the attribute "cache_counter". * * @aspectwerkz.advice.callerside pattern=examples.caching.* cache_counter */ public Object someMethod() {..} /** * This method will start a cflow pointcut. * * @aspectwerkz.cflow pointcutname */ public Object someMethod(..) {..} /** * This field is now monitored by the advice with the attribute "persistent". * * @aspectwerkz.advice.setfield persistent */ private int m_field; /** * Here we define a join point controller for this join point. * * @aspectwerkz.joinpoint.controller examples.logging.MyJoinPointController */ public Object someMethod(..) {..} XML definition
If you want to define your advices and introductions in the
XML definition but want to use them using attributes then you
have to add the
<advice-def name="logging" class="advices.LoggingAdvice" deployment-model="perJVM" attribute="log"/> Attribute compilationIf you are using runtime attributes then you have to compile a the attributes to an XML definition. You can choose to compile a standalone XML definition file or merge with an existing definition.
To compile the attributes you have to use the
Compile from command line
You can run the
Deployment models
The four different deployment models are:
Join point controller
The
It allows you to (for example) control:
A little example of how a
Implementation
To implement your own
It might be useful to take a look at the implementation for the default
If you let your controller implementation extend the
Definition
If you don't specify a
Attributes
To specify which
/** * @aspectwerkz.joinpoint.controller foo.MyJoinPointController */ public void someMethod() { ... } XML definition
To specify which
<aspect name="MyAspect"> <pointcut-def name="pc1" type="method" pattern="* foo.Target.*(..)"/> <controller-def pointcut="pc1" class="foo.MyJoinPointController"/> ... </aspect> Non-reentrancy
By default
To prevent this you have the option of defining s
ome of your pointcuts as
Definition
Attributes
You can define the non-reentrancy in the
/** * @aspectwerkz.advice.method log non-reentrant=true */ public void someMethod() { ... } XML definition
To define a pointcut as
<aspect name="MyAspect"> <pointcut-def ... non-reentrant="true"/> ... </aspect> |