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.
when you declare @MyDao(“myOrderDao”) how do you know it associates with repository and not another annotation from the MyDao interface? other than that (for me), this is a very well written tutorial thank you.
For reference, such circumstances are handled by the “@AliasFor” annotation. If there were other annotations which may conflict you could define the above:
// Some other conflicting annotation
@Repository
@interface MyDao {
@AliasFor(annotation = Repository.class, attribute = “value”)
String name();
}