The Spring Framework started adding annotations to Spring development with version 2.  Each release has added more annotations.  Annotations provide a powerful means to define and wire your beans, configure cross cutting concerns (like transactions) and much more.  However, given the number of annotations added to your POJO classes to provide for Spring stereotyping, dependency injection, transactions, AOP, etc., you may forget what the actual business of the class is all about.  What’s more, you have to add the same annotations to many of the classes in your application.  Forgetting just one (like @Transactional) can have disastrous implications.  In this post, I continue my series on Spring 4 features and address meta annotations to help with the problem described above.

Meta Annotations  Defined

Many of Spring 4’s annotations can now be used as meta annotations.  A meta annotation is an annotation that can be applied to another annotation.  That means, you can now define your own custom annotations that are an amalgamation of many Spring annotations combined into one annotation.

Creating Composed Annotations

Custom or composed annotations are annotations you create from other Spring meta annotations.  These annotations serve two purposes.  First, they collapse many annotations into one annotation for coding simplicity.  Second, they help define a reusable annotation that allows common need(s) to be addressed without having to remember add all the individual annotations (and annotation attributes).

Take, for example, the following data access object (DAO).

package com.intertech;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 30, isolation=Isolation.SERIALIZABLE)
public class OrderDaoImpl implements OrderDao {
  ...
}

Without any business in the DAO yet, the declaration and annotation of the class is already up to 11 lines of code!

To simplify the DAO and to provide for a composed DAO annotation that can be used for any such DAO, define your own custom annotation (in this case called MyDao) using Spring meta-annotations.

package com.intertech;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 30, isolation=Isolation.SERIALIZABLE)
public @interface MyDao {
}

With the custom/composed annotation in place, you can now remove many of the annotations that litter the top of the DAO classes.

package com.intertech;
@MyDao
public class OrderDaoImpl implements OrderDao {
  ...
}
Annotation Attributes

In many cases, an annotation requires or allows for attributes.  Your custom annotation can provide for those attributes as well.  For example, the Repository annotation allows for the bean name to be provided by attribute as shown below.

@Repository("myOrderDao")

Because the custom annotation may be reused by several DAOs, it would not make sense to hard code the name into the @Repository meta annotation in the custom @MyDao annotation.  So, simply add the value attribute (the same attribute defined in @Repository) to your custom annotation.

@Repository
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 30, isolation=Isolation.SERIALIZABLE)
public @interface MyDao {
	String value();
}

Now you can provide the bean name through your custom annotation.

@MyDao("myOrderDao")
public class OrderDaoImpl implements OrderDao {
  ...
}
Wrap Up

You can learn more about meta annotations in Spring from the reference documentation here.