AOP Mixin Implementation with AspectJ 5 and JSE 5.0
AspectJ5 is the latest release, targeting J2SE 5.0 features like
generics and
annotations. Annotations enable us to add metadata to code.
This metadata can be used in many ways to process the code. AspectJ
5 has added support for writing pointcuts to pick out join points
based on annotations. We can read the description of annotations
and look at a few examples to understand their meaning, especially
about retention policies and targets, which are briefly explained
below.
The enhanced pointcut language adds more power to AspectJ. Let
us rewrite our example using annotations. Since annotations add
metadata to describe Java code, we define two annotations to
describe important features of our example. The first annotation is
used to annotate the JavaBean, so the target is
ElementType.TYPE, which means that it can only be used
to annotate classes. The line
@Retention(RetentionPolicy.RUNTIME) is the retention
policy, which means that our metadata is accessible at runtime.
package com.blueprint.util.aspectj5.test;
import java.lang.annotation.*;
import java.lang.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface javaBean {
}
The second annotation is used to annotate the "setter" method that
changes the value of the property, so the target is
ElementType.METHOD. This means that it can only be
used to annotate methods.
package com.blueprint.util.aspectj5.test;
import java.lang.annotation.*;
import java.lang.*;
@Retention( RetentionPolicy.RUNTIME )
@Target({ ElementType.METHOD })
public @interface propertyChanger {
}
We can see below that the JavaBean has been annotated using our
custom annotations. Both @javaBean() and
@propertyChanger() are called marker
annotations. Readers familiar with marker interfaces should see
a comparison here. A marker annotation does not have any values
specified within braces.
package com.blueprint.util.aspectj5.test;
import java.io.Serializable;
@javaBean()
public class Bean implements Serializable{
private String name;
public String getName() {
return name;
}
@propertyChanger()
public void setName( String name ) {
this.name = name;
}
}
The pointcut in PropertySupportAspect.aj has to be rewritten
as:
pointcut callSetter( Bean b )
: call( @propertyChanger * *(..) ) && target( b );
@propertyChanger * *(..) will match any method with
any name, in any type, taking any arguments. The aspect below will
match our annotated bean now. @javaBean * matches any
type with a @javaBean annotation.
package com.blueprint.util.aspectj5.test;
import com.blueprint.util.aspectj5.test.
PropertySupportAspect5.PropertySupport;
public aspect BeanSupportAspectj {
declare parents: @javaBean * implements PropertySupport;
}
The flexibility and power of this new pointcut definition based
on annotations is now evident. Our AspectJ 5 implementation is
similar to our previous mixin that does not use annotations, but
this is just a simple example of AspectJ's annotation support. The
benefits of annotations and AspectJ5 could be the topic of a whole
article.
Incremental Compilation Bug
As of the writing of this article, an Inter-Type Declaration
(ITD) bug shows in the mixin implementations. The indication is at
the line:
b.addPropertyChangeListener( "name", this );
in the JUnit Test case in the Eclipse editor. I have seen a
solution that flips a flag to do a full build by checking the first
check box in the Other tab in Project -> Properties -> AspectJ
Compiler, but this could not remove the error. This does not impact
the code, though, and the test case should succeed.
Conclusion
Practical use of AOP is a very important factor in its adoption.
This article demonstrates one such use case with an example
focusing on how AOP complements OO by enabling us to write mixins
in a clean way. We have also seen that improving the modularity of
code is always beneficial. AOP implementations also add
extensibility, composability, and reusability to code in a way that
is richer than what OO can manage. Moreover, old concepts like
mixins are used with newer implementations with the advent of
AspectJ and dynamically typed scripting languages. I should also
add that since tools like the AspectJ Development Tools for Eclipse
(AJDT) are stabilizing after the introduction of the new features,
there is a chance that we might uncover a bug when working with the
latest JDK 5 features in AspectJ 5.
Resources
Mohan Radhakrishnan has been a professional Java developer since 1997, and currently works for Accenture solutions division in India.