BT

Annotation Hammer

Posted by Venkat Subramaniam on Jul 25, 2006 |

Abstract

Annotations in Java 5 provide a very powerful metadata mechanism. Yet, like anything else, we need to figure out where it makes sense to use it. In this article we will take a look at why Annotations matter and discuss cases for their use and misuse.

 

Expressing Metadata

Let's start with what we're familiar with as good old Java programmers. We want to express that an instance of a class may be serialized. We can say this by implementing the Serializable interface as shown here:

public class MyClass implements java.io.Serializable
{
}

How many methods does the Serializable interface have? The answer, of course, is zero. Now, why would we have an interface with zero methods and inherit from it? I call it the use of the inheritance hammer. We didn't use inheritance in this case to derive any behavior, or express a specific contract, but to provide our consent that it is OK to serialize an object of this class if a user of the class so desires. We call the Serializable interface a tagging interface. Other interfaces like Cloneable fall into this tradition of tagging interfaces. Now, what if I have a field within my object and I don't want it to be serialized? Java uses the transient keyword to express this as shown below:

public class MyClass implements java.io.Serializable
{
    private int val1;
    private transient int val2;
}

So, we needed an interface (Serializable) and a keyword (transient) to get our job done in the above example.

Let's proceed further with this example. Assume that I have a framework that provides some service. You may send objects of your class to my framework. However, I need to know if your objects are thread-safe, after all if it's not thread-safe you wouldn't want me to use it concurrently from multiple threads. Continuing from what we've learned from the above example, I can define a tagging interface (let me call it ThreadSafe). If you implement this interface, then I can figure out that your class is thread-safe.

public class MyClass
implements java.io.Serializable, VenkatsFramework.ThreadSafe
{
    private int val1;
    private transient int val2;
}

See that was simple! Now, let's assume you have a method of the class which, for whatever reason, should not be called from multiple threads. How do we do that? No problem. We can kindly request a new keyword to be introduced into the Java language, so we can mark our method using the new keyword (or you can argue that we can use the synchronized keyword, but you can see the limitation of this approach of using a keyword).

public class MyClass
       implements java.io.Serializable, VenkatsFramework.ThreadSafe
{
    private int val1;
    private transient int val2;
public our_new_fangled_keyword void foo() // Not valid Java code { //... } }

As you can see, we lack the expressive power to extend the metadata. What we want to do is, so to say, color the classes, methods, and fields to say that it is Serializable, thread-safe, or whatever that we wish to express based on our need.

More Power to You

Enter Annotations. Annotations provide a way for us to extend the Java language with new metadata. It provides great expressive power. Let's see how we can express the concept we described in the previous example, elegantly using annotations.

//ThreadSafe.java
package VenkatsFramework;
public @interface ThreadSafe { } //NotThreadSafe.java package VenkatsFramework;
public @interface NotThreadSafe { }
//MyClass.java package com.agiledeveloper; import VenkatsFramework.ThreadSafe; import VenkatsFramework.NotThreadSafe; @ThreadSafe public class MyClass implements java.io.Serializable { private int val1; private transient int val2; @NotThreadSafe public void foo() { //... } }

The annotation ThreadSafe is written as if it is an interface (more about this later). In MyClass, I have used the annotation ThreadSafe (for the class) and NotThreadSafe (for the method). When using frameworks, we would often use annotations rather than defining them. However, it is interesting to learn how to define annotations.

Defining Annotations

Let's define an annotation called AuthorInfo which can be used to express who wrote a piece of code. Here is the code:

package com.agiledeveloper;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Inherited
public @interface AuthorInfo
{
    public String name();
    public String email() default "";
    public String comment() default "";
}

The AuthorInfo annotation has three elements: name, email, and comment. These are defined using a method declaration like syntax. The email and comment have default values, so these two may be left out when @AuthorInfo annotation is used. If an annotation has only a single value, you can specify that value without the member name.

Where (method, class, field, etc.) can you use the @AuthorInfo annotation? This is defined using the meta-annotation @Target (Nice: annotations eating their own dog food). The possible ElementType values for the @Target annotation are: ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, and TYPE. The @Inherited meta-annotation indicates that the annotation not only affects the class that declares the annotation, but also any class derived from the declaring class (In the case of AuthorInfo annotation, it really doesn't make sense to use Inherited as the author of a class may be different from the author of its base class).

Finally, the @Retention meta-annotation tells us how far the annotation will be. If the value is RetentionPolicy.SOURCE then the annotation is seen in the source code, but discarded by the compiler. The value of RetentionPolicy.CLASS means the annotation information will be retained in the class file, but not loaded into the virtual machine. The value of RetentionPolicy.RUNTIME means the value is retained at runtime and you can use reflection to explore the annotation details. One more meta-annotation not shown here is @Documented which indicates that the use of annotation may be documented in javadoc.

Using the Annotations

Here is an example of using the AuthorInfo annotation:

package com.agiledeveloper;

@com.agiledeveloper.AuthorInfo(name = "Venkat Subramaniam")
public class SomeClass
{
    @com.agiledeveloper.AuthorInfo(
	    name = "Venkat Subramaniam", comment = "bug free")
    public void foo()
    {

    }
}

SomeClass specifies the @AuthorInfo annotation with a value for the name element. Similarly the foo() method has the @AuthorInfo annotation.

The following example is not valid:

package com.agiledeveloper;

@com.agiledeveloper.AuthorInfo(name = "Venkat Subramaniam")
public class SomeClass2
{
    // ERROR 'com.agiledeveloper.AuthorInfo' not applicable to fields
    @com.agiledeveloper.AuthorInfo(name = "Venkat Subramaniam")
	// Not valid
    private int val1;
}

The compiler gives an error message since the @AuthorInfo is useable only on classes and methods (as defined by the @Target meta-annotation).

Exploring Annotations

As I mentioned earlier, most of the time we will use annotations rather than define them. However, if you are curious how a framework would use the annotation, here it is. Using reflection you can explore the details of annotation on your class, method, field, etc. An example code that explores the @AuthorInfo on the class is shown below:

package com.agiledeveloper;

import java.lang.reflect.Method;

public class Example
{
    public static void report(Class theClass)
    {
        if (theClass.isAnnotationPresent(AuthorInfo.class))
        {
            AuthorInfo authInfo =
     		(AuthorInfo) theClass.getAnnotation(AuthorInfo.class);

            System.out.println(theClass.getName() +
		     " has @AuthorInfo annotation:");
            System.out.printf("name = %s, email = %s, comment = %s\n",
		authInfo.name(),
		authInfo.email(), authInfo.comment());
        }
        else
        {
            System.out.println(theClass.getName()
	    + " doesn't have @AuthorInfo annotation");
        }

        System.out.println("-----------------");
    }

    public static void main(String[] args)
    {
        report(SomeClass.class);
        report(String.class);
    }
}

The output from the above program is shown below:

com.agiledeveloper.SomeClass has @AuthorInfo annotation:
name = Venkat Subramaniam, email = , comment =
-----------------
java.lang.String doesn't have @AuthorInfo annotation
-----------------

The isAnnotationPresent() method of Class tells us if the class has the expected Annotation. You can fetch the Annotation details using the getAnnotation() method.

An Example of Annotation

Let's take a look at an annotation built into Java.

package com.agiledeveloper;

public class POJOClass
{
    /**
     * @deprecated Replaced by someOtherFoo()...
     */
    public static void foo()
    {
    }

    @Deprecated public static void foo1()
    {
    }
}

The foo() method uses the traditional way to declare a method as deprecated. This approach lacked the expressiveness and, even though Sun compilers typically provide a warning if you use a method declared as deprecated, there is no guarantee that all compilers will issue a warning for this. A more standardized and portable version of this is to use @Deprecated annotation (though it lacks the power to provide the description for deprecation that the older approach allowed–so you typically would use it in combination with the older approach) as in:

    /**
     * @deprecated Replaced by someOtherFoo1()...
     */
    @Deprecated public static void foo1()
    {
    }

Annotation and the Hammer

"If the only tool you have is a hammer, then everything looks like a nail," goes a saying. While annotations are a good tool, not every situation warrants their use. Most of us have come to dislike XML configuration. However, suddenly, everything in the XML configuration shouldn't become annotation.

Use annotations for what you want to express intrinsically in code. For example, the @Persist annotation in Tapestry is a good example. You want to declare a property of a bean as persistent and Tapestry will take care of storing it (in the session for instance). I would much rather define this as annotation than using a verbose configuration to say the same. The chances are, if I decide not to make the property persistent, much is going to change in the code anyways.

To consider another good example, in defining a web service, how do you describe which methods of your class need to be exposed as a web service method, so its description can appear in the WSDL? We have come across solutions that use configuration files for this. One problem with configuration file approach is, if you modify the code (like change method name) you also have to modify the configuration file. Furthermore, you rarely really configure a method as a service method back and forth. Marking a method as web service method using annotation may make good sense.

The expressive power of annotations and their ability to extend the metadata of the language allow code generation tools to create code for you based on the characteristics you've expressed. Annotations can also help us express some aspects.

Now consider using annotation to configure security settings for a method. That would be a stretch. It's likely that you will modify the security settings during deployment. You may want to be able to alter it without having to modify the code and recompiling. Annotation is not the best choice to express things that are somewhat extrinsic and better expressed outside of the code. Does that mean we need to use extensive XML configuration for these? Not necessarily, as we discuss in the next section.

Convention over configuration

Certain things are better suited to be configured and expressed using Annotations. Certain things are better suited to be expressed external and separated from the code, may be in XML, YAML, etc. However, not every thing should be configured. Configuration provides flexibility. Just like in real life, too much of anything can be bad. Certain things may be easily figured out in the application based on convention rather than configuration.

For instance, in pre JUnit 4.0 versions, you would indicate that a method is a test method by prefixing it with test. In JUnit 4.0, you instead mark a method using the @Test annotation. Not looking at other features and benefits of JUnit 4.0, is this better? You may point out that the benefit you get from the use of annotation is that you don't have to extend your test class from the TestCase class. I agree, but, that's at the class level. At the method level, is it less noise, less clutter to simply write a method as:

public void testMethod1() {}

or

@Test public void method1() {}

Why not, by default, consider all methods in a test class as test methods? Then maybe you can specify (maybe using annotation) that a method is not a test method. Kind of like how in Java a method is considered virtual (polymorphic) unless you declare it final. Then you are making less noise to communicate your intent, isn't it?

The point I am making is that there is nothing wrong in using convention where it makes sense, improves the signal-to-noise ratio in the code, less clutter, and less typing.

To Annotate or Not To

When to use annotations is an interesting question to ask. Both the answers "Always" and "Never" are incorrect. There are places where annotation is suitable and even elegant. Then there are places where it may not be the best choice.

Use Annotation if:

  • Metadata is intrinsic
    • If you would have used a keyword, if available in the language, then this may be a candidate for annotation (transient for example).
  • Is simpler to express and easier to work with as annotation than otherwise
    • For instance, it is easier to mark a method as a web method in a web service instead of writing an xml configuration file to say the same.
  • Class based, not object specific
    • Represents metadata that is at the class level, irrespective of any specific object of the class

Don't use Annotation if:

  • Just because it's currently in xml config does not mean it should become an annotation now
    • Don't blindly convert your xml configuration information to annotations<
  • You already have an elegant way to specify this
    • If the way you are representing this information is already elegant and sufficient, don't fall into the pressure of using annotation.
  • Metadata is something you will want to change
    • You want this to be modified or configurable, for example security settings for a method of a bean-you may want to modify this at any time. These may be better left in a configuration file.
  • Your application can figure the details out from convention instead of configuration
    • You can configure (using annotation or otherwise) only things that are different from the obvious or the default.

Conclusion

Annotations are an interesting addition to the language. They provide a powerful construct for extending the Java language with new metadata. However, we need to take the time to evaluate its merit on a case by case basis. "The right use of annotations" is a design concern that deserves due consideration in application development - neither blind acceptance nor rejection of it is a good idea.

About the Author

Dr. Venkat Subramaniam, founder of Agile Developer, Inc., has trained and mentored more than 3000 software developers in the US, Canada, Europe, and India. Venkat helps his clients effectively apply and succeed with agile practices on their software projects, and speaks frequently at conferences. He is also an adjunct faculty at the University of Houston (where he received the 2004 CS department teaching excellence award) and teaches the professional software developer series at Rice University School of continuing studies. He is author of ".NET Gotchas" and coauthor of "Practices of an Agile Developer."

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Spring 2.0 by Corby Page

I am very surprised that current versions of the Spring 2.0 docs are emphasizing the use of annotations to define aspects, rather than XML configuration.

From the docs: Spring's support for @AspectJ aspects is the recommended approach for declaring aspects for use with the Spring AOP framework. "@AspectJ" refers to a style of declaring aspects as regular Java classes annotated with Java 5 annotations.

Aspects are the sort of thing where you are going to want an application-wide view of how they are cross-cutting your application. Without explicit AspectJ tooling support, you are not going to get that if you use annotations.

What's worse is that pointcuts are not very refactoring-friendly. Being able to assess all of your application's pointcuts in a single XML file is a good way to head off errors introduced by refactoring. Hunting down all of your pointcut annotations in individual class files is not a scalable process.

Re: Spring 2.0 by Uri Boness

AOP != Configuration != Meta-data!
It is time for developers to start seeing aspects as first class citizens of the application. You have classes to model concepts and you have aspects to model requirements (architecture requirements, domain requirements, or application requirements). The @AspectJ annotations is not there to configure the aspects, but to define them. I agree that it would probably be best if we could all use AspectJ traditional aspect constructs in our applications, but unfortunately not many tools support it at the moment (e.g. IntelliJ). @AspectJ annotation opens the window for us (IntelliJ users) to leverage AOP support in our applications by using this extremely powerful tool.

Re: Spring 2.0 by Corby Page

@AspectJ annotation opens the window for us (IntelliJ users) to leverage AOP support in our applications by using this extremely powerful tool.


I'm not following you. I'm an IntelliJ user, and I found it a pain in the ass to find all the classes that I had set up with @Aspect, and to track down their associated Pointcuts so I can see who is advising what.

Once I had moved these declarations into a config file, I could survey all of my aspects, and what they were cross-cutting, on a single page on my screen. Much better.

It's all fine and good to say that aspects need to be 'first class citizens', but IntelliJ is not a dedicated AOP development environment, so for right now there are two places we can specify our aspects: configuration or metadata.

Re: Spring 2.0 by Alexandre Poitras

AOP != Configuration != Meta-data!
It is time for developers to start seeing aspects as first class citizens of the application. You have classes to model concepts and you have aspects to model requirements (architecture requirements, domain requirements, or application requirements). The @AspectJ annotations is not there to configure the aspects, but to define them. I agree that it would probably be best if we could all use AspectJ traditional aspect constructs in our applications, but unfortunately not many tools support it at the moment (e.g. IntelliJ). @AspectJ annotation opens the window for us (IntelliJ users) to leverage AOP support in our applications by using this extremely powerful tool.


I agree with you.

Re: Spring 2.0 by Uri Boness


I'm not following you. I'm an IntelliJ user, and I found it a pain in the ass to find all the classes that I had set up with @Aspect, and to track down their associated Pointcuts so I can see who is advising what.


How do you track down classes in the application? or functionality in general? You probably use proper naming strategies/conventions, and well packaging. The same should be done with aspects - good packaging and naming should definitely make it easy to find your way around the pointcuts... actually, IMO defining all the aspects in the application context makes a mess out of it... well... it's much better now with the new namespaces, but still...

Re: Spring 2.0 by Corby Page

How do you track down classes in the application? or functionality in general? You probably use proper naming strategies/conventions, and well packaging.


That doesn't really get around the fact that I want to get an 'application-level' view of what is cross-cutting my application, and I still have to iterate through the aspects one at a time to get it with the annotations. If you use 'proper' organizational practices on your context.xml, you can access all of your aspects in a single, easy-to-read file.

Anyway, I think there is one place we can agree. The annotation support makes it easier for tools like IntelliJ to build plugins and extensions for a dedicated AOP UI that does make aspects a first-class citizen. Once that kind of support is in place, I would be just fine with using annotations.

Re: Spring 2.0 by Tomasz Blachowicz

I've been playing with @Configurable annotation from Spring 2.0 and it looks very nice. When I showed it to my mates, they felt really confused how it all happened :) I run sample application in JBoss AS with runtime weaving and it worked quite well. In general I'm big fun of annotations and I'm happy that Spring guys've started to use them.

What I miss... by Tomasz Blachowicz

What I miss is inheritance of annotations. I hope I was be able to define one generic annotation and then create a bunch of specialised ones with additional attributes. The problem is when you try to write generic code to explore them. Without annotation inheritance it's hard to do it well.

Re: What I miss... by Alex Popescu

I don't know the reasons why inheritance is not part of the annotation spec, but I know for sure that it was one of the most discussed things in the JSR group (unfortunately, I don't think these debates can be found somewhere so that we can understand the reasoning).

./alex
--
.w( the_mindstorm )p.

Two usage of annotations in AspectJ by Ramnivas Laddad

When annotations are discussed in the context of AOP/AspectJ, it could mean one of the two things.

1. Expressing aspect constructs
The traditional-style (also known as "code style") syntax extends the Java language using new keywords, and consequently requires a new compiler ('ajc'). The @AspectJ-style (also known as "annotation style"), on the other hand, extends the Java language using AspectJ-specific annotations instead of new keyword.

For example, here is a tracing aspect defined using the traditional style syntax.

public aspect TracingAspect {
pointcut trace()
: execution(* banking..*.*(..));

before() : trace() {
System.out.println("Entering " + thisJoinPointStaticPart);
}
}


Here is a functionally-identical aspect defined using the @AspectJ style syntax.

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TracingAspect {
@Pointcut("execution(* banking..*.*(..))")
void trace() {}

@Before("trace()")
public void log(JoinPoint.StaticPart thisJoinPointStaticPart) {
System.out.println("Entering " + thisJoinPointStaticPart);
}
}

While the above aspect may be compiled using 'javac', you will need to use the AspectJ weaver somewhere between compiling source code and byte code entering the VM. The choices for the weaver are compile-time weaver (use 'ajc' as the compiler), binary weaver (use 'ajc' as the weaver with classes and jar files as input), and load-time weaver (use a classloader or the AspectJ-supplied JVMTI agent as the weaver).

Advantages of the traditional style include compactness of the code and simplified static crosscutting. Advantages of the code style include tool-friendliness (IntelliJ will be happier with the code, since it is Java code from its point of view, and a post-build step can to the binary weaving).

Note that you will need an AspectJ-aware IDE to see the crosscutting reference view (relationship between program elements and aspects). IntelliJ users will not get this functionality easily (there is a standalone tool, 'ajbrowser' and there is 'ajdoc', but the user experience is not the same). Frankly, I am not sure how long IntelliJ can avoid adding the AspectJ support, given increasing use of AspectJ inside and outside the Spring community.

2. Selecting join points
This use of annotations help leveraging the metadata associated with the program constructs in selecting join points. This use is totally independent of the style used to express aspects. For example, you can write a pointcut
execution(@Secure * *(..))
to select all methods that carry a @Secure annotation. I have explored this use of annotation in a two full-length article series (part 1, part 2). The reason to prefer annotations over XML to express metadata is that with annotations it is much easier to write a pointcut to select the required join points.

-Ramnivas

Re: Two usage of annotations in AspectJ by Corby Page

The reason to prefer annotations over XML to express metadata is that with annotations it is much easier to write a pointcut to select the required join points.


You know, I really don't want to get into an AOP argument with Ramnivas Laddad. It's like getting into a drinking contest with Lindsay Lohan. I'm just going to end up looking stupid.

But here is your aspect, your pointcut, and your joinpoints in XML:

<aop:config>
<aop:aspect id="tracingAspect" ref="tracingAspectBean">
<aop:pointcut id="businessService" expression="execution(* banking..*.*(..))"/>
<aop:before pointcut-ref="businessService" method="log"/>
</aop:aspect>
</aop:config>

That was as least as easy and concise as what you did with annotations. And if it wasn't for crappy InfoQ formatting, it would have looked real slick, too.

Now, with XML I can fit all of my aspects on a single page in XML, and have an application-wide view of my architecture. Surely you have to concede that without an AOP-aware development environment this is preferable to dispersing annotations throughout my application.

Re: Two usage of annotations in AspectJ by Corby Page

Ah, here it is nice and pretty:


<aop:config>
<aop:aspect id="tracingAspect" ref="tracingAspectBean">
<aop:pointcut id="businessService" expression="execution(* banking..*.*(..))"/>
<aop:before pointcut-ref="businessService" method="log"/>
</aop:aspect>
</aop:config>


Simlarly, you can do:


<aop:config>
<aop:aspect id="tracingAspect" ref="tracingAspectBean">
<aop:pointcut id="businessService" expression="execution(@Secure * *(..))"/>
<aop:before pointcut-ref="businessService" method="log"/>
</aop:aspect>
</aop:config>


to select all methods that have a @Secure annotation.

Re: Two usage of annotations in AspectJ by Ramnivas Laddad

Corby, you can sure argue with me :-). More importantly, we can sure learn a thing or two from each other.

Let me clarify a bit. When I said, "prefer annotations over XML to express metadata", I was referring to the use of annotations in "Selecting join points" part. The use of XML you are showing belongs to the "Expressing aspect constructs" part.

Tools (as you point), specific project needs, and personal preference direct the choice between traditional, @AspectJ, and XML-based syntax. There are a few fundamental differences between them, though:
1. The traditional syntax needs specific support from tools such as IDE. However, when you do have the right support, you can write concise code and express static crosscutting more directly. Of course, you also get visibility into crosscutting structure (see screenshots in this article, for example).
2. The @AspectJ syntax works reasonably well in environment without specific support for AspectJ (IntelliJ, for example), since such environments can treat the AspectJ code as Java code. It also works great in environments that support AspectJ. For example, in Eclipse you get all the goodies such as crosscutting reference view etc.
3. The XML syntax too works in environment without specific support for AspectJ. It also allows making certain changes to crosscutting functionality without having to recompile. However, a drawback will be (at least with current tools) the lack of visibility into crosscutting structure.

I use the traditional syntax if the team is using Eclipse as the IDE and AspectJ in the fundamental part of the project, @AspectJ in non-Eclipse environments, and XML if quick configuration changes is a requirement (performance monitoring, for example). It is also not uncommon to see use of multiple syntaxes in the same project.

Let me get back to the "prefer annotations over XML to express metadata" point. From AOP's perspective, it is easier to select the required join points when program elements themselves carry annotations instead of putting them in an associated XML file. For example,

@Entity
public class Customer implements Serializable {
@Id Long id;
...

is preferable to

public class Customer implements Serializable {
private Long id;
...

along with

<hibernate>
<class name="com.infoq.domain.Customer" table="customers">
<id name="id" column="ID"/>
...


Just to be sure, I am discussing XML vs. annotation only from AOP's join point selection convenience; there are other reasons to prefer one over other. When program elements themselves carry metadata using annotations, I can leverage that metadata easily in pointcut expressions. For example, I can select my trace points as all methods in domain classes with a pointcut such as execution(* (@Entity *).*(..)) (using traditional, @AspectJ, or XML syntax).

-Ramnivas

Re: Two usage of annotations in AspectJ by Alex Popescu

I use the traditional syntax if the team is using Eclipse as the IDE and AspectJ in the fundamental part of the project, @AspectJ in non-Eclipse environments, and XML if quick configuration changes is a requirement (performance monitoring, for example). It is also not uncommon to see use of multiple syntaxes in the same project.


Excellent summary Ramnivas. IMO, this should be included in the AspectJ FAQ for reference ;-].

Not-so-unrelated: the IntelliJ IDEA 6.0 version will be able to work with Eclipse compiler. I see some new open doors for AspectJ in the future (indeed it is still far, but we've already touched this discussion on the AJ mailing list).

./alex
--
.w( the_mindstorm )p.

Two style of using XML, too by Ramnivas Laddad

I need to add one more point to already lengthy replies!

When we say XML-based syntax, it may mean one of the two things: The AspectJ way of defining concrete subaspects or the Spring way of defining typed advice. It may also mean using pointcut expression while defining proxy beans (but I will not discuss that, since it is quite simple to understand). Most of the generic discussion of XML-based syntax applies to all these styles.

The AspectJ way of defining subaspect targets the use cases that need changes to the selected join points without having to recompile. This is a purposefully limited syntax, where pretty much the only thing you can do is define subaspects and provide a definition for abstract pointcuts in the base aspects. You use aspects defined in this manner with the load-time weaver (although it is theoretically possible that compile-time and binary weaver will understand this syntax as well). Except for the style, there are no semantic differences between aspects defined using XML and using code. Here is an example of aspect defined using AspectJ's XML-based syntax.


<!-- META-INF/aop.xml -->
<aspectj>
<aspects>
<!-- Assume com.aspectivity.monitoring.JDBCMonitoringAspect
is an abstract aspect with an abstract monitoredOps() pointcut -->
<concrete-aspect
name="com.aspectivity.monitoring.JDBCMonitoringAspect"
extends="com.aspectivity.monitoring.MonitoringAspect">
<pointcut name="monitoredOps"
expression="call(* java.sql.*.*(..))"/>
</concrete-aspect>
...
</aspects>
...
</aspectj>


Now if you needed, for example, to monitor execution of methods in banking classes in addition to JDBC, you can simply change the pointcut to the following definition. No need to recompile the classes:

<pointcut name="monitoredOps"
expression="call(* java.sql.*.*(..)) || execution(* banking..*.*(..))"/>


Corby's example is one of Spring's typed advice. This syntax targets the use cases that need to use Spring's proxy-based AOP framework (that does not need a special compiler or load-time weaver). Compared to traditional Spring AOP, this allows expressing (strongly) typed advice i.e. use more specific types instead of Object as the type for the collected join point context. The limitation of this style stems from its use of proxy-based AOP. Specially,
1. You can only crosscut objects managed by Spring. In Corby's example, execution(* banking..*(..)) will select methods matching the expression only for the object created through Spring.
2. You can't use pointcuts such as get(), set(), and handler().
3. You cannot also use execution() or target() pointcut to select constructor execution.

All these syntaxes have pros and cons, with a no clear winner in all situations. This realization is behind AspectJ's and Spring's support for multiple syntaxes and weaving models. A typical developer using Spring framework is expected to first use AspectJ-based pointcut expressions when defining proxy beans in XML, then move on to use typed advice (both using proxy-based AOP and without using any special weaver). Then when he will need stronger AOP support (for fine-grained dependency using @Configurable annotation, among other things), he will use AspectJ.

-Ramnivas

Re: Two style of using XML, too by Corby Page

Thanks, Ramnivas, that's very helpful.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

16 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2014 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT