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 usingContextLoaderListener
--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- ConfigureContextLoaderListener
to useJavaConfigWebApplicationContext
instead of the defaultXmlWebApplicationContext
--> <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 MVCDispatcherServlet
as usual --> <servlet> <servlet-name>test</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- ConfigureDispatcherServlet
to useJavaConfigWebApplicationContext
instead of the defaultXmlWebApplicationContext
--> <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 ApplicationContext
s. 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