Enterprise Spring Best Practices Series
In part 4, Spring Annotation Configuration.
In this edition of Enterprise Spring Best Practices, let’s look at annotations. Several of the annotations became available in Spring 2.5. Spring 3.0 added convenient annotation discovery mechanisms which we’ll see here.
Annotations are available for Dependency Injection, Bean discovery and instantiation, post processing (required fields, initialization method, etc).
Annotations may or may NOT be discovered in java interfaces, refer to the documentation or JavaDoc for details on whether the annotation discovery mechanism will traverse upward in the class hierarchy.
Sections
- Annotation Style Decision
- Annotation Discovery from XML
- Application Component Scanning
- MVC Component Scanning
- Component Scanning Best Practices
- Further Reading
- Social Me
Annotation Style Decision
Annotations help simplify configuration. All annotations in Java 5 and above, require some discovery mechanism.
Within Spring, we have 3 strategies for bean discovery and dependency injection
- XML based discovery
- JavaConfig
- Hybrid Configuration
Hybrid configuration is simply mixing standard XML <bean/> declarations with annotation methods discussed below. In the next blog, I will discuss JavaConfig, so for now lets focus on XML based discovery of Annotations.
Annotation Discovery from XML
All annotations REQUIRE a discovery directive. We MUST know which XML directives discover particular annotations, or the beans will not be processed.
For Spring annotation discovery detail, see Annotation Reference for Spring Projects
Option 1 – Register individual bean post processors
There are several individual Bean Post Processors that can be registered to discover specific annotation categories
- RequiredAnnotationBeanPostProcessor – (
@Required) - CommonAnnotationBeanPostProcessor – (
@PostConstruct, @PreDestroy, @Resource, etc.) - AutowiredAnnotationBeanPostProcessor – (
@Autowired, @Value, @Inject, etc.) - PersistenceAnnotationBeanPostProcessor – (
@PersistenceUnit, @PersistenceContext, etc.)
Option 2 – Use the annotation-config directive
Automatically registers the Bean Post Processors above.
<context:annotation-config/>
Option 3 – Use the component-scan directive
Automatically registers the Bean Post Processors above AND scans for component annotations @Component, @Repository, @Service, @Controller, and more…
<context:context:component-scan
base-package="com.gordondickens.enterprisespring"/>
Application Component Scanning
Exclude configuration elements that are not part of the underlying application. Controllers are part of the application that deals with the user interface but are not pertinent to Web Services.
Within
applicationContext-bootstrap.xml
<context:component-scan
base-package="com.gordondickens.enterprisespring">
<context:exclude-filter
expression="org.springframework.stereotype.Controller"
type="annotation"/>
</context:component-scan>
MVC Component Scanning
Exclude components are not part of the entire application. If our application serves UI clients and web service clients, only the base components should be discovered in the main application configuration. We will discuss MVC configuration in a future blog.
Within applicationContext-webmvc.xml
<context:component-scan
base-package="com.gordondickens.enterprisespring"
use-default-filters="false"/>
<context:include-filter
expression="org.springframework.stereotype.Controller"
type="annotation"/>
</context:component-scan>
Component Scanning Best Practices
When Spring creates the application context, it aggregates all of the configuration into a single context, no matter how many configuration files or annotations are used.
- Component scanning should ONLY be configured in the bootstrap config file, not in every XML config file
- Do NOT also include the
<context:annotation-config/>directive, it is automatically included by component scan - Do NOT start scanning from “com” and/or “org”, as this will scan ALL sub packages in all of the project and jars for candidates!
- Be as specific as possible with the packages
- Do NOT cross application boundaries with
component-scan- Create an
applicationContext-services.xmlfor scanning services - Create an
applicationContext-persistence.xmlfor persistence and entity beans - Create an
applicationContext-webmvc.xmlfor persistence and entity beans - Create an
applicationContext-webservice.xmlfor web service beans - Import these references into the
applicationContext-bootstrap.xmlto these elements
- Create an
Why separate the discovery files into layer specific configuration?
- Unit testing is easier as discovery of beans is more specific
- Allows the project to be separated into multiple Jar/Wars
- Lowers risk of widely scoped discovery issues, overscanning and beans being replaced by multiple scanners
For Spring annotation discovery detail, see Annotation Reference for Spring Projects
Further Reading
- Enterprise Spring Best Practices – Part 1 – Project Configuration
- Enterprise Spring Best Practices – Part 2 – Application Architecture
- Enterprise Spring Best Practices – Part 3 – XML Config
- Enterprise Spring Best Practices – Source Code
- FREE Spring Framework PDF (848 pages)
- Apache Maven
- SLF4J
- Logback
- Gradle
Social Me
Twitter – twitter.com/gdickens
LinkedIn – linkedin.com/in/gordondickens
GitHub: github.com/gordonad
gordon@gordondickens.com