diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml
index 8ac318b000..6719d4d43f 100644
--- a/spring-framework-reference/src/beans.xml
+++ b/spring-framework-reference/src/beans.xml
@@ -143,7 +143,7 @@ The footnote should x-ref to first section in that chapter but I can't find the
- Java-based
+ Java-based
configuration: Starting with Spring 3.0, many features
provided by the Spring JavaConfig
@@ -5571,19 +5571,18 @@ public class CachingMovieCatalog implements MovieCatalog {
-
+ Java-based container configuration
-
- Using the @Configuration
- annotation
+
+ Basic concepts: @Configuration and @BeanThe central artifact in Spring's new Java-configuration support is
the @Configuration-annotated class. These
classes consist principally of
@Bean-annotated methods that define
- instantiation, configuration, and initialization logic for objects that
- are managed by the Spring IoC container.
+ instantiation, configuration, and initialization logic for objects to
+ be managed by the Spring IoC container.Annotating a class with the
@Configuration indicates that the class
@@ -5591,24 +5590,482 @@ public class CachingMovieCatalog implements MovieCatalog {
The simplest possible @Configuration
class would read as follows: @Configuration
public class AppConfig {
+ @Bean
+ public void MyService myService() {
+ return new MyServiceImpl();
+ }
+}
-}
+ For those more familiar with Spring <beans/>
+ XML, the AppConfig class above would be equivalent to:
- An application may use one
- @Configuration-annotated class, or many.
- @Configuration is meta-annotated as a
- @Component. Therefore,
- @Configuration-annotated classes are
- candidates for component-scanning and can also take advantage of
- @Autowired annotations at the field and
- method levels, but not at the constructor level.
- @Configuration-annotated classes must
- also have a default constructor. You can wire externalized values into
- @Configuration-annotated classes with the
- @Value annotation.
+ <beans>
+ <bean id="myService" class="com.acme.services.MyServiceImpl"/>
+</beans>
+
+ As you can see, the @Bean annotation plays the same role
+ as the <bean/> element. The @Bean
+ annotation will be discussed in depth in the sections below. First, however,
+ we'll cover the various ways of creating a spring container using Java-based
+ configuration.
-
+
+ Instantiating the Spring container using
+ AnnotationConfigApplicationContext
+
+ The sections below document Spring's
+ AnnotationConfigApplicationContext, new in Spring 3.0.
+ This versatile ApplicationContext implementation is
+ capable of accepting not only @Configuration classes
+ as input, but also plain @Component classes and classes
+ annotated with JSR-330 metadata.
+
+ When @Configuration classes are provided as input,
+ the @Configuration class itself is registered as a bean
+ definition, and all declared @Bean methods within the
+ class are also registered as bean definitions.
+
+ When @Component and JSR-330 classes are provided,
+ they are registered as bean definitions, and it is assumed that DI metadata
+ such as @Autowired or @Inject are used
+ within those classes where necessary.
+
+
+ Simple construction
+ In much the same way that Spring XML files are used as input when
+ instantiating a ClassPathXmlApplicationContext,
+ @Configuration classes may be used as input when
+ instantiating an AnnotationConfigApplicationContext.
+ This allows for completely XML-free usage of the Spring container:
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+}
+
+ As mentioned above, AnnotationConfigApplicationContext
+ is not limited to working only with @Configuration
+ classes. Any @Component or JSR-330 annotated class may
+ be supplied as input to the constructor. For example:
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+}
+
+The above assumes that MyServiceImpl, Dependency1 and Dependency2 use Spring dependency injection annotations such as @Autowired.
+
+
+
+ Building the container programmatically using register(Class<?>...)
+ An AnnotationConfigApplicationContext may be
+ instantiated using a no-arg constructor and then configured using the
+ register() method. This approach is particularly
+ useful when programmatically building an
+ AnnotationConfigApplicationContext.
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(AppConfig.class, OtherConfig.class);
+ ctx.register(AdditionalConfig.class);
+ ctx.refresh();
+ MyService myService = ctx.getBean(MyService.class);
+ myService.doStuff();
+}
+
+
+
+ Enabling component scanning with scan(String...)
+ Experienced Spring users will be familiar with the following
+ commonly-used XML declaration from Spring's context: namespace
+ <beans>
+ <context:component-scan base-package="com.acme"/>
+</beans>
+
+ In the example above, the com.acme package will
+ be scanned, looking for any @Component-annotated
+ classes, and those classes will be registered as Spring bean
+ definitions within the container.
+
+ AnnotationConfigApplicationContext exposes the
+ scan(String...) method to allow for the same
+ component-scanning functionality:public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.scan("com.acme");
+ ctx.refresh();
+ MyService myService = ctx.getBean(MyService.class);
+}
+
+ Remember that @Configuration classes are
+ meta-annotated with @Component, so they are
+ candidates for component-scanning! In the example above, assuming
+ that AppConfig is declared within the
+ com.acme package (or any package underneath),
+ it will be picked up during the call to scan(),
+ and upon refresh() all its @Bean
+ methods will be processed and registered as bean definitions within
+ the container.
+
+
+
+
+ Support for web applications with AnnotationConfigWebApplicationContext
+ A WebApplicationContext variant of AnnotationConfigApplicationContext is available with AnnotationConfigWebApplicationContext. This implementation may be used when configuring the Spring ContextLoaderListener servlet listener, Spring MVC DispatcherServlet, etc. What follows is a web.xml snippet that configures a typical Spring MVC web application. Note the use of the contextClass context-param and init-param:
+
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+
+
+
+ contextConfigLocation
+ com.acme.AppConfig
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ dispatcher
+ org.springframework.web.servlet.DispatcherServlet
+
+
+ contextClass
+
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+
+
+ contextConfigLocation
+ com.acme.web.MvcConfig
+
+
+
+
+
+ dispatcher
+ /main/*
+
+]]>
+
+
+
+
+ Composing Java-based configurations
+
+ Using the @Import annotation
+ Much as the <import/> element is used within
+ Spring XML files to aid in modularizing configurations, the
+ @Import annotation allows for loading @Bean
+ definitions from another configuration class:@Configuration
+public class ConfigA {
+ public @Bean A a() { return new A(); }
+}
+
+@Configuration
+@Import(ConfigA.class)
+public class ConfigB {
+ public @Bean B b() { return new B(); }
+}
+
+Now, rather than needing to specify both ConfigA.class and
+ConfigB.class when instantiating the context, only
+ConfigB needs to be supplied explicitly:public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
+
+ // now both beans A and B will be available...
+ A a = ctx.getBean(A.class);
+ B b = ctx.getBean(B.class);
+}
+
+ This approach simplifies container instantiation, as only one class needs to be dealt
+ with, rather than requiring the developer to remember a potentially large number of
+ @Configuration classes during construction.
+
+
+
+ Injecting dependencies on imported @Bean definitions
+ The example above works, but is simplistic. In most practical scenarios, beans
+ will have dependencies on one another across configuration classes. When using XML,
+ this is not an issue, per se, because there is no compiler involved, and one can
+ simply declare ref="someBean" and trust that Spring will work
+ it out during container initialization. Of course, when using
+ @Configuration classes, the Java compiler places constraints on
+ the configuration model, in that references to other beans must be valid Java syntax.
+
+ Fortunately, solving this problem is simple. Remember that
+ @Configuration classes are ultimately just another bean in the container
+ - this means that they can take advantage of @Autowired injection
+ metadata just like any other bean!
+
+ Let's consider a more real-world scenario with several @Configuration
+ classes, each depending on beans declared in the others:@Configuration
+public class ServiceConfig {
+ private @Autowired AccountRepository accountRepository;
+
+ public @Bean TransferService transferService() {
+ return new TransferServiceImpl(accountRepository);
+ }
+}
+
+@Configuration
+public class RepositoryConfig {
+ private @Autowired DataSource dataSource;
+
+ public @Bean AccountRepository accountRepository() {
+ return new JdbcAccountRepository(dataSource);
+ }
+}
+
+@Configuration
+@Import({ServiceConfig.class, RepositoryConfig.class})
+public class SystemTestConfig {
+ public @Bean DataSource dataSource() { /* return new DataSource */ }
+}
+
+public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
+ // everything wires up across configuration classes...
+ TransferService transferService = ctx.getBean(TransferService.class);
+ transferService.transfer(100.00, "A123", "C456");
+}
+
+
+ Fully-qualifying imported beans for ease of navigation
+ In the scenario above, using @Autowired works
+ well and provides the desired modularity, but determining exactly where
+ the autowired bean definitions are declared is still somewhat ambiguous.
+ For example, as a developer looking at ServiceConfig,
+ how do you know exactly where the @Autowired AccountRepository
+ bean is declared? It's not explicit in the code, and this may be just fine.
+ Remember that the SpringSource
+ Tool Suite provides tooling that can render graphs showing how everything
+ is wired up - that may be all you need. Also, your Java IDE can easily find all
+ declarations and uses of the AccountRepository type, and will
+ quickly show you the location of @Bean methods that return that
+ type.
+
+ In cases where this ambiguity is not acceptable and you wish to have
+ direct navigation from within your IDE from one @Configuration
+ class to another, consider autowiring the configuration classes themselves:
+ @Configuration
+public class ServiceConfig {
+ private @Autowired RepositoryConfig repositoryConfig;
+
+ public @Bean TransferService transferService() {
+ // navigate 'through' the config class to the @Bean method!
+ return new TransferServiceImpl(repositoryConfig.accountRepository());
+ }
+}
+
+ In the situation above, it is completely explicit where
+ AccountRepository is defined. However,
+ ServiceConfig is now tightly coupled to
+ RepositoryConfig; that's the tradeoff. This tight
+ coupling can be somewhat mitigated by using interface-based or abstract
+ class-based @Configuration classes. Consider the following:
+ @Configuration
+public class ServiceConfig {
+ private @Autowired RepositoryConfig repositoryConfig;
+
+ public @Bean TransferService transferService() {
+ return new TransferServiceImpl(repositoryConfig.accountRepository());
+ }
+}
+
+@Configuration
+public interface RepositoryConfig {
+ @Bean AccountRepository accountRepository();
+}
+
+@Configuration
+public class DefaultRepositoryConfig implements RepositoryConfig {
+ public @Bean AccountRepository accountRepository() {
+ return new JdbcAccountRepository(...);
+ }
+}
+
+@Configuration
+@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
+public class SystemTestConfig {
+ public @Bean DataSource dataSource() { /* return DataSource */ }
+}
+
+public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
+ TransferService transferService = ctx.getBean(TransferService.class);
+ transferService.transfer(100.00, "A123", "C456");
+}
+
+ Now ServiceConfig is loosely coupled with respect
+ to the concrete DefaultRepositoryConfig, and built-in IDE
+ tooling is still useful: it will be easy for the developer to get a type hierarchy
+ of RepositoryConfig implementations. In this way, navigating
+ @Configuration classes and their dependencies becomes no
+ different that the usual process of navigating interface-based code.
+
+
+
+
+
+ Combining Java and XML configuration
+ Spring's @Configuration class support does not aim to be a 100%
+ complete replacement for Spring XML. Some facilities such as Spring XML namespaces remain
+ an ideal way to configure the container. In cases where XML is convenient or necessary,
+ you have a choice: either instantiate the container in an "XML-centric" way using, for
+ example, ClassPathXmlApplicationContext, or in a "Java-centric" fashion
+ using AnnotationConfigApplicationContext and the
+ @ImportResource annotation to import XML as needed.
+
+
+ XML-centric use of @Configuration classes
+ It may be preferable to bootstrap the Spring container from XML and
+ include @Configuration classes in an ad-hoc fashion.
+ For example, in a large existing codebase that uses Spring XML, it will be
+ easier to create @Configuration classes on an as-needed
+ basis and include them from the existing XML files. Below you'll find the
+ options for using @Configuration classes in this kind
+ of "XML-centric" situation.
+
+
+ Declaring @Configuration classes as plain Spring
+ <bean/> elements
+ Remember that @Configuration classes are ultimately
+ just bean definitions in the container. In this example, we create a
+ @Configuration class named AppConfig
+ and include it within system-test-config.xml as a
+ <bean/>definition. Because
+ <context:annotation-config/> is switched on, the
+ container will recognize the @Configuration annotation,
+ and process the @Bean methods declared in
+ AppConfig properly.@Configuration
+public class AppConfig {
+ private @Autowired DataSource dataSource;
+
+ public @Bean AccountRepository accountRepository() {
+ return new JdbcAccountRepository(dataSource);
+ }
+
+ public @Bean TransferService transferService() {
+ return new TransferService(accountRepository());
+ }
+}
+ system-test-config.xml
+<beans>
+ <!-- enable processing of annotations such as @Autowired and @Configuration -->
+ <context:annotation-config/>
+ <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
+
+ <bean class="com.acme.AppConfig"/>
+
+ <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+ <property name="url" value="${jdbc.url}"/>
+ <property name="username" value="${jdbc.username}"/>
+ <property name="password" value="${jdbc.password}"/>
+ </bean>
+</beans>
+
+ jdbc.properties
+jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
+jdbc.username=sa
+jdbc.password=
+
+ public static void main(String[] args) {
+ ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
+ TransferService transferService = ctx.getBean(TransferService.class);
+ // ...
+}
+
+
+ In system-test-config.xml above, the
+ AppConfig<bean/> does not declare an
+ id element. While it would be acceptable to do
+ so, it is unnecessary given that no other bean will ever refer to it,
+ and it is unlikely that it will be explicitly fetched from the container
+ by name. Likewise with the DataSource bean - it is
+ only ever autowired by type, so an explicit bean id is not strictly
+ required.
+
+
+
+
+ Using <context:component-scan/> to pick up
+ @Configuration classes
+ Because @Configuration is meta-annotated with
+ @Component, @Configuration-annotated
+ classes are automatically candidates for component scanning. Using the same
+ scenario as above, we can redefine system-test-config.xml
+ to take advantage of component-scanning. Note that in this case, we don't
+ need to explicitly declare <context:annotation-config/>,
+ because <context:component-scan/> enables all the same
+ functionality.system-test-config.xml
+<beans>
+ <!-- picks up and registers AppConfig as a bean definition -->
+ <context:component-scan base-package="com.acme"/>
+ <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
+
+ <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+ <property name="url" value="${jdbc.url}"/>
+ <property name="username" value="${jdbc.username}"/>
+ <property name="password" value="${jdbc.password}"/>
+ </bean>
+</beans>
+
+
+
+
+
+ @Configuration class-centric use of XML with
+ @ImportResource
+ In applications where @Configuration classes are
+ the primary mechanism for configuring the container, it will still
+ likely be necessary to use at least some XML. In these scenarios,
+ simply use @ImportResource and define only as much
+ XML as is needed. Doing so achieves a "Java-centric" approach to
+ configuring the container and keeps XML to a bare minimum.
+ @Configuration
+@ImportResource("classpath:/com/acme/properties-config.xml")
+public class AppConfig {
+ private @Value("${jdbcProperties.url}") String url;
+ private @Value("${jdbcProperties.username}") String username;
+ private @Value("${jdbcProperties.password}") String password;
+
+ public @Bean DataSource dataSource() {
+ return new DriverManagerDataSource(url, username, password);
+ }
+}
+
+ properties-config.xml
+<beans>
+ <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
+</beans>
+ jdbc.properties
+jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
+jdbc.username=sa
+jdbc.password=
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ TransferService transferService = ctx.getBean(TransferService.class);
+ // ...
+}
+
+
+
+
+ Using the @Bean annotation@Bean is a method-level annotation
@@ -5625,7 +6082,7 @@ public class AppConfig {
a @Configuration-annotated or in a
@Component-annotated class.
-
+ Declaring a beanTo declare a bean, simply annotate a method with the
@@ -5658,7 +6115,7 @@ transferService -> com.acme.TransferServiceImpl
-
+ Injecting dependenciesWhen @Beans have dependencies on
@@ -5682,7 +6139,7 @@ public class AppConfig {
reference to bar via constructor injection.
-
+ Receiving lifecycle callbacksBeans created in a
@@ -5754,15 +6211,15 @@ public class AppConfig {
When you work directly in Java, you can do anything you like
- with your objects, and do not always need to rely on the
- container!
+ with your objects and do not always need to rely on the
+ container lifecycle!
-
+ Specifying bean scope
-
+ Using the @Scope
annotation
@@ -5786,7 +6243,7 @@ public class MyConfiguration {
}
-
+ @Scope and scoped-proxySpring offers a convenient way of working with scoped
@@ -5814,12 +6271,12 @@ public UserPreferences userPreferences() {
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
- service.seUserPreferences(userPreferences());
+ service.setUserPreferences(userPreferences());
return service;
}
-
+ Lookup method injectionAs noted earlier,
-
+ Customizing bean naming
- By default, Configuration-classes use a
+ By default, Configuration classes use a
@Bean methods name as the name of the
resulting bean. This functionality can be overridden, however, with
the name attribute. @Configuration
@@ -5881,6 +6338,23 @@ public class AppConfig {
return new Foo();
}
+}
+
+
+
+ Bean aliasing
+
+ As discussed in , it is sometimes desirable
+ to name a bean multiple names, otherwise known as bean aliasing.
+ The name attribute to the @Bean annotation accepts
+ a String array for this purpose. @Configuration
+public class AppConfig {
+
+ @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
+ public DataSource dataSource() {
+ // instantiate, configure and return DataSource bean...
+ }
+
}
@@ -5893,9 +6367,9 @@ public class AppConfig {
provides a load-time-weaver element.
<beans>
-
+
<context:load-time-weaver/>
-
+
</beans>Adding this element to an XML-based Spring configuration file
diff --git a/spring-framework-reference/src/new-in-3.xml b/spring-framework-reference/src/new-in-3.xml
index 63cfe828f1..ca0bf4e430 100644
--- a/spring-framework-reference/src/new-in-3.xml
+++ b/spring-framework-reference/src/new-in-3.xml
@@ -219,6 +219,10 @@
BeanFactory interface returns typed bean instances as far as
possible:
+
+ T getBean(Class<T> requiredType)
+
+
T getBean(String name, Class<T> requiredType)
@@ -266,7 +270,8 @@
across all the products in the Spring portfolio. Its language features
are driven by the requirements of the projects in the Spring portfolio,
including tooling requirements for code completion support within the
- Eclipse based SpringSource Tool Suite.
+ Eclipse based SpringSource
+ Tool Suite.The following is an example of how the Expression Language can be
used to configure some properties of a database setup @Import
+
+ @ImportResource
+
+
@Value
@@ -368,7 +377,16 @@ public class AppConfig {
scanning entry in your minimal application context XML file.
<context:component-scan base-package="org.example.config"/>
<util:properties id="jdbcProperties" location="classpath:org/example/config/jdbc.properties"/>
-
+
+ Or you can bootstrap a @Configuration class directly using
+ AnnotationConfigApplicationContext:
+ public static void main(String[] args) {
+ ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
+ FooService fooService = ctx.getBean(FooService.class);
+ fooService.doStuff();
+}
+ See for full information on
+ AnnotationConfigApplicationContext.
@@ -441,7 +459,7 @@ public class AppConfig {
@MVC additions
- A mvc namespace has been introduced that greatly simplifies Spring MVC configuration.
+ A mvc namespace has been introduced that greatly simplifies Spring MVC configuration.Additional annotations such as
@CookieValue and