A new approach to Spring configuration
Since Spring 2.5 it is possible to do less XML configuration and more of that configuration using annotations like @Component and @Autowired. Many people embraced this change in configuration. From Spring 3.0 on Spring’s java configuration project is merged into the framework, allowing to configure your beans in configuration classes.
A basic example to configure a businessService bean is as follows. The application context uses the ServiceConfig class to configure the Spring container.
@Configuration
public class ServiceConfig {
public @Bean BusinessService businessService {
return new BusinessServiceImpl();
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ServiceConfig.class);
// get the businessService
BusinessService service = ctx.getBean(BusinessService.class);
}
Now this does not bring anything of an advantage over configuring the businessService bean with @Service and a context:component-scan in XML (see annotation config in the Spring reference guide). But let’s take the configuration bean to a next level.
Spring 3.1 introduces feature specification support to the java-based configuration. This allows to configure features like transaction support and component scanning to be configured in code. Let’s see what that’s like. Like with any other code we first write a test, followed by the implementation.
@Test public void testScanShouldGetComponentScanSpec() {
ComponentScanSpec componentScanSpec = new ContextConfig().scan();
assertNotNull("No component scan spec was created.", componentScanSpec);
ProblemCollector problems = new SimpleProblemCollector(componentScanSpec);
ProblemReporter reporter = new FailFastProblemReporter();
componentScanSpec.doValidate(problems);
problems.reportProblems(reporter);
}
@FeatureConfiguration
public class ContextConfig {
@Feature public ComponentScanSpec scan() {
return new ComponentScanSpec("nl.iprofs.blogs").excludeFilters(
new AnnotationTypeFilter(Configuration.class),
new AnnotationTypeFilter(FeatureConfiguration.class));
}
}
Having the BusinessServiceImpl now defined as an @Service it will be picked up by the component scan spec. The test validates whether the component scan spec is properly configured, not that it can be executed as this is mainly up to the environment it is executed within (for testing it is too bad the set base packages are not visible though). An integration test to see if the feature configuration can be properly executed is a welcome addition to test the configuration in the environment (i.e. all the bean implementations).
As you can see the exclude filter of the component scan spec filters any configuration and feature configuration class. The reason is that @Configuration and @FeatureConfiguration classes must be specified to the AnnotationConfigApplicationContext as configuration classes, and they end up in the container that way. This allows for great flexibility when it comes to configuration as you can inject any other bean and use it at configuration time.
With the feature specification support of Spring 3.1 the need for XML configuration is finally being eliminated. Not that XML isn’t good for configuration, code just is better. The first milestone release supports feature specifications for component scanning, annotation-driven transaction configuration, and a lot of MVC features. The second milestone (not yet available at time of writing) will bring aspectj autoproxy and mbean support.
Recent Comments