AnnotationApplicationContext presented a
naming conflict with Spring 2.5's Annotation-Driven Configuration. To
avoid this problem it has been renamed to
JavaConfigApplicationContext. Beyond the
renaming, JavaConfigApplicationContext has
several new features worth discussing. See below for details.
AnnotationApplicationContext will be
removed entirely in JavaConfig 1.0.0.rc1
JavaConfigApplicationContext,
JavaConfigWebApplicationContext and the
ConfigurationSupport base class now all expose
type-safe getBean methods, allowing for
looking up beans by type, rather than by name.
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
@Bean
public NotificationService notificationService() {
return new NotificationServiceImpl();
}
}
public class SimpleApp {
public static void main(String... args) {
JavaConfigApplicationContext context = new JavaConfigApplicationContext(AppConfig.class);
// use the type-safe getBean method to avoid casting and string-based lookups
TransferService transferService = context.getBean(TransferService.class);
TransferService notificationService = context.getBean(NotificationService.class);
// ...
}
}
See Section 4.3.2.1, “Type-safe access” for details.
By popular demand, a
WebApplicationContext variant of
JavaConfigApplicationContext has been created.
This allows for seamless bootstrapping of JavaConfig bean definitions
within web.xml requiring no Spring XML whatsoever.
<web-app>
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Configure ContextLoaderListener to use JavaConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.config.java.JavaConfigWebApplicationContext</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.RootApplicationConfig</param-value>
</context-param>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use JavaConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.config.java.JavaConfigWebApplicationContext</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.web.WebBeansConfig</param-value>
</init-param>
</servlet>
</web-app>
For basic information regarding initialization parameters to
DispatcherServlet and use of
ContextLoaderListener, see Chapter
13. Web MVC framework in the Core Spring Framework
documentation.
For complete details on using JavaConfig in the web tier, see Chapter 7, Developing web applications with JavaConfig.
Consider the case of nested
@Configuration classes:
@Configuration
public class OuterConfig {
@Bean
public Foo outerBean() {
// ...
}
}
@Configuration
public static class InnerConfig {
@Bean
public Bar innerBean() {
// ...
}
}
In previous milestones, any nested
@Configuration classes (such as
InnerConfig above) were treated as just another
source of bean definitions and were processed inline with the rest of
the beans in the declaring @Configuration
class. Ultimately, all bean definitions ended up in the same
BeanFactory/ApplicationContext.
Now and going forward, nested
@Configuration classes will be processed as
child ApplicationContexts. Perhaps better said,
any declaring (outer) @Configuration classes
will be processed as parent
ApplicationContexts. Using the example
above, Instantiate an
ApplicationContext using
InnerConfig as an argument
JavaConfigApplicationContext context = new JavaConfigApplicationContext(InnerConfig.class);
context.getBean("innerBean"); // locally defined beans are available
context.getBean("outerBean"); // as are beans defined in the declaring OuterConfig class.
Note that when supplying OuterConfig
as the argument, InnerConfig is ignored
entirely. If it were to be processed, it would become a child context,
but its beans would would be inaccessible (parent contexts have no
access to child context beans).
JavaConfigApplicationContext context = new JavaConfigApplicationContext(OuterConfig.class);
context.getBean("outerBean"); // works fine
context.getBean("innerBean"); // throws NoSuchBeanDefinitionException!
See Section 5.6, “Nesting @Configuration classes” for full
details.
JavaConfig now has the equivalent of XML configuration's
<import/> element. One configuration class can
import any number of other configuration classes, and their bean
definitions will be processed as if locally defined.
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(...);
}
}
@Configuration
@Import(DataSourceConfig.class)
public class AppConfig extends ConfigurationSupport {
@Bean
public void TransferService transferService() {
return new TransferServiceImpl(getBean(DataSource.class);
}
}
Importing multiple configurations can be done by supplying an
array of classes to the @Import annotation
@Configuration
@Import({ DataSourceConfig.class, TransactionConfig.class })
public class AppConfig extends ConfigurationSupport {
// bean definitions here can reference bean definitions in DataSourceConfig or TransactionConfig
}
See ??? for full details.
Important: This functionality may change!. We are currently evaluating approaches for best supporting externalized values. See SJC-74 for more details.
Somewhat similar to the way that
@ExternalBean makes it possible to reference
beans defined outside of the current
@Configuration,
@ExternalBean allows for accessing externalized
string values in properties files. This is ideal for use when
configuring up infrastructural resources with properties that may
change at deployment time, or otherwise need to be externally
accessible for modification.
@Configuration
@ResourceBundles("classpath:/com/myapp/datasource")
public abstract class AppConfig {
@Bean
public DataSource myDataSource() {
DataSource dataSource = new MyDataSource();
dataSource.setUsername(username());
dataSource.setPassword(password());
dataSource.setUrl(url());
return dataSource;
}
@ExternalValue
public abstract String username();
@ExternalValue
public abstract String password();
@ExternalValue("jdbc.url")
public abstract String url();
}
com/myapp/datasource.properties:
username=scott password=tiger jdbc.url=...
See Section 5.5, “Externalizing values with @ExternalValue
and @ResourceBundles” for full
details