diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml index 075d5cd71fc..d57474c2702 100644 --- a/spring-framework-reference/src/beans.xml +++ b/spring-framework-reference/src/beans.xml @@ -143,9 +143,8 @@ The footnote should x-ref to first section in that chapter but I can't find the - Java-based - configuration: Starting with Spring 3.0, many features - provided by the Java-based configuration: + Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. Thus you can define beans external to your application classes by using Java @@ -737,10 +736,19 @@ List userList service.getUsernameList(); createInstance() method must be a static method. - <bean id="exampleBean" - class="examples.ExampleBean2" + <bean id="clientService" + class="examples.ClientService" factory-method="createInstance"/> + public class ClientService { + private static ClientService clientService = new ClientService(); + private ClientService() {} + + public static ClientService createInstance() { + return clientService; + } +} + For details about the mechanism for supplying (optional) arguments to the factory method and setting object instance properties after the object is returned from the factory, see factory-method attribute. <!-- the factory bean, which contains a method called createInstance() --> -<bean id="serviceLocator" class="com.foo.DefaultServiceLocator"> +<bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- inject any dependencies required by this locator bean --> </bean> <!-- the bean to be created via the factory bean --> -<bean id="exampleBean" +<bean id="clientService" factory-bean="serviceLocator" - factory-method="createInstance"/> + factory-method="createClientServiceInstance"/> + + public class DefaultServiceLocator { + private static ClientService clientService = new ClientServiceImpl(); + private DefaultServiceLocator() {} + + public ClientService createClientServiceInstance() { + return clientService; + } +} + + One factory class can also hold more than one factory method as + shown here: + + +<bean id="serviceLocator" class="examples.DefaultServiceLocator"> + <!-- inject any dependencies required by this locator bean --> +</bean> +<bean id="clientService" + factory-bean="serviceLocator" + factory-method="createClientServiceInstance"/> + +<bean id="accountService" + factory-bean="serviceLocator" + factory-method="createAccountServiceInstance"/> + + public class DefaultServiceLocator { + private static ClientService clientService = new ClientServiceImpl(); + private static AccountService accountService = new AccountServiceImpl(); + + private DefaultServiceLocator() {} + + public ClientService createClientServiceInstance() { + return clientService; + } + + public AccountService createAccountServiceInstance() { + return accountService; + } +} This approach shows that the factory bean itself can be managed and configured through dependency injection (DI). See Spring's XML format, set the autowire-candidate attribute of the <bean/> element to false; the container makes that specific bean - definition unavailable to the autowiring infrastructure (including - annotation style configurations such as - @Autowired). - + definition unavailable to the autowiring infrastructure (including + annotation style configurations such as @Autowired). You can also limit autowire candidates based on pattern-matching against bean names. The top-level <beans/> @@ -2300,8 +2346,9 @@ public class CommandManager implements ApplicationContextAware { You can read more about the motivation for Method Injection in - this blog - entry. + this + blog entry.
@@ -3211,9 +3258,9 @@ beanFactory.registerScope("thread", threadScope In addition to the initialization and destruction callbacks, Spring-managed objects may also implement the - Lifecycle interface so that those - objects can participate in the startup and shutdown process as - driven by the container's own lifecycle. + Lifecycle interface so that those objects + can participate in the startup and shutdown process as driven by the + container's own lifecycle. The lifecycle callback interfaces are described in this section. @@ -3475,9 +3522,9 @@ beanFactory.registerScope("thread", threadScope Any Spring-managed object may implement that interface. Then, when the ApplicationContext itself starts and stops, it will cascade - those calls to all Lifecycle implementations defined within that context. - It does this by delegating to a LifecycleProcessor: - + those calls to all Lifecycle implementations defined within that + context. It does this by delegating to a + LifecycleProcessor: public interface LifecycleProcessor extends Lifecycle { @@ -3487,10 +3534,11 @@ beanFactory.registerScope("thread", threadScope } - Notice that the LifecycleProcessor - is itself an extension of the Lifecycle - interface. It also adds two other methods for reacting to the context - being refreshed and closed. + Notice that the + LifecycleProcessor is itself an + extension of the Lifecycle interface. + It also adds two other methods for reacting to the context being + refreshed and closed. The order of startup and shutdown invocations can be important. If a "depends-on" relationship exists between any two objects, the @@ -3498,12 +3546,13 @@ beanFactory.registerScope("thread", threadScope and it will stop before its dependency. However, at times the direct dependencies are unknown. You may only know that objects of a certain type should start prior to objects of another - type. In those cases, the SmartLifecycle - interface defines another option, namely the getPhase() - method as defined on its super-interface, Phased. - + type. In those cases, the + SmartLifecycle interface defines + another option, namely the getPhase() method + as defined on its super-interface, + Phased. - public interface Phased { + public interface Phased { int getPhase(); @@ -3518,52 +3567,60 @@ public interface SmartLifecycle extends Lifecycle, Phased { } - When starting, the objects with the lowest phase start first, and - when stopping, the reverse order is followed. Therefore, an object that - implements SmartLifecycle and whose getPhase() - method returns Integer.MIN_VALUE would be among the first - to start and the last to stop. At the other end of the spectrum, a phase - value of Integer.MAX_VALUE would indicate that the - object should be started last and stopped first (likely because it - depends on other processes to be running). When considering the phase value, - it's also important to know that the default phase for any "normal" - Lifecycle object that does not implement - SmartLifecycle would be 0. Therefore, any - negative phase value would indicate that an object should start before - those standard components (and stop after them), and vice versa for any - positive phase value. + When starting, the objects with the lowest phase start first, + and when stopping, the reverse order is followed. Therefore, an object + that implements SmartLifecycle and + whose getPhase() method returns Integer.MIN_VALUE + would be among the first to start and the last to stop. At the other + end of the spectrum, a phase value of + Integer.MAX_VALUE would indicate that the object + should be started last and stopped first (likely because it depends on + other processes to be running). When considering the phase value, it's + also important to know that the default phase for any "normal" + Lifecycle object that does not + implement SmartLifecycle would be 0. + Therefore, any negative phase value would indicate that an object + should start before those standard components (and stop after them), + and vice versa for any positive phase value. - As you can see the stop method defined by SmartLifecycle - accepts a callback. Any implementation must invoke that - callback's run() method after that implementation's shutdown process is complete. - That enables asynchronous shutdown where necessary since the default - implementation of the LifecycleProcessor - interface, DefaultLifecycleProcessor, will wait - up to its timeout value for the group of objects within each phase to - invoke that callback. The default per-phase timeout is 30 seconds. You - can override the default lifecycle processor instance by defining a bean - named "lifecycleProcessor" within the context. If you only want to modify - the timeout, then defining the following would be sufficient: + As you can see the stop method defined by + SmartLifecycle accepts a callback. Any + implementation must invoke that callback's run() + method after that implementation's shutdown process is complete. That + enables asynchronous shutdown where necessary since the default + implementation of the + LifecycleProcessor interface, + DefaultLifecycleProcessor, will wait up to its + timeout value for the group of objects within each phase to invoke + that callback. The default per-phase timeout is 30 seconds. You can + override the default lifecycle processor instance by defining a bean + named "lifecycleProcessor" within the context. If you only want to + modify the timeout, then defining the following would be + sufficient: - - - -]]> + <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> + <!-- timeout value in milliseconds --> + <property name="timeoutPerShutdownPhase" value="10000"/> +</bean> - As mentioned, the LifecycleProcessor interface - defines callback methods for the refreshing and closing of the context as well. The - latter will simply drive the shutdown process as if stop() had been called explicitly, - but it will happen when the context is closing. The 'refresh' callback on the other - hand enables another feature of SmartLifecycle beans. - When the context is refreshed (after all objects have been instantiated and initialized), - that callback will be invoked, and at that point the default lifecycle processor will - check the boolean value returned by each SmartLifecycle - object's isAutoStartup() method. If "true", then that object - will be started at that point rather than waiting for an explicit invocation of the - context's or its own start() method (unlike the context refresh, the context start does - not happen automatically for a standard context implementation). The "phase" value as - well as any "depends-on" relationships will determine the startup order in the same way - as described above. + As mentioned, the + LifecycleProcessor interface defines + callback methods for the refreshing and closing of the context as + well. The latter will simply drive the shutdown process as if stop() + had been called explicitly, but it will happen when the context is + closing. The 'refresh' callback on the other hand enables another + feature of SmartLifecycle beans. When + the context is refreshed (after all objects have been instantiated and + initialized), that callback will be invoked, and at that point the + default lifecycle processor will check the boolean value returned by + each SmartLifecycle object's + isAutoStartup() method. If "true", then that + object will be started at that point rather than waiting for an + explicit invocation of the context's or its own start() method (unlike + the context refresh, the context start does not happen automatically + for a standard context implementation). The "phase" value as well as + any "depends-on" relationships will determine the startup order in the + same way as described above.
@@ -3670,27 +3727,32 @@ public final class Boot { InitializingBeans afterPropertiesSet or a custom init-method.
- +
Other <interfacename>Aware</interfacename> interfaces - + Besides ApplicationContextAware and - BeanNameAware discussed above, Spring offers a range - of Aware interfaces that allow beans - to indicate to the container that they require a certain infrastructure dependency. - The most important Aware interfaces are summarized below - as a general rule, - the name is a good indication of the dependency type: - + BeanNameAware discussed above, Spring + offers a range of + Aware interfaces + that allow beans to indicate to the container that they require a + certain infrastructure dependency. The most + important Aware interfaces are summarized + below - as a general rule, the name is a good indication of the + dependency type: + <interfacename>Aware</interfacename> interfaces - + Name + Injected Dependency + Explained in... @@ -3698,86 +3760,152 @@ public final class Boot { ApplicationContextAware - Declaring ApplicationContext - + + Declaring + ApplicationContext + + + ApplicationEventPublisherAware - Event publisher of the enclosing ApplicationContext - + + Event publisher of the enclosing + ApplicationContext + + + BeanClassLoaderAware - Class loader used to load the bean classes. - + + Class loader used to load the bean + classes. + + + BeanFactoryAware - Declaring BeanFactory - + + Declaring + BeanFactory + + + BeanNameAware + Name of the declaring bean - + + + BootstrapContextAware - Resource adapter BootstrapContext the container runs in. Typically available only - in JCA aware ApplicationContexts - + + Resource adapter + BootstrapContext the container + runs in. Typically available only in JCA aware + ApplicationContexts + + + LoadTimeWeaverAware - Defined weaver for processing class definition at load time - + + Defined weaver for processing + class definition at load time + + + MessageSourceAware - Configured strategy for resolving messages (with support for parametrization and internationalization) - + + Configured strategy for resolving messages (with + support for parametrization and + internationalization) + + + NotificationPublisherAware + Spring JMX notification publisher - + + + PortletConfigAware - Current PortletConfig the container runs in. Valid only in a web-aware Spring + + Current + PortletConfig the container runs + in. Valid only in a web-aware Spring ApplicationContext - + + + PortletContextAware - Current PortletContext the container runs in. Valid only in a web-aware Spring + + Current + PortletContext the container runs + in. Valid only in a web-aware Spring ApplicationContext - + + + ResourceLoaderAware - Configured loader for low-level access to resources - + + Configured loader for low-level access to + resources + + + ServletConfigAware - Current ServletConfig the container runs in. Valid only in a web-aware Spring + + Current + ServletConfig the container runs + in. Valid only in a web-aware Spring ApplicationContext - + + + ServletContextAware - Current ServletContext the container runs in. Valid only in a web-aware Spring + + Current + ServletContext the container runs + in. Valid only in a web-aware Spring ApplicationContext - + + -
- - Note again that usage of these interfaces ties your code to the Spring API and does not follow the Inversion of Control - style. As such, they are recommended for infrastructure beans that require programmatic access to the container. - + + + Note again that usage of these interfaces ties your code to the + Spring API and does not follow the Inversion of Control style. As such, + they are recommended for infrastructure beans that require programmatic + access to the container.
@@ -4396,32 +4524,37 @@ dataSource.url=jdbc:mysql:mydb Annotation-based container configuration - Are annotations better then XML for configuring Spring? - - The introduction of annotation based configurations raised the question of whether - this approach is better or not then XML. The short answer is it depends.. - The long answer is that each approach has it's pros and cons and usually it's up to the developer - to decide which strategy suits her better. - Due to the way they are defined, annotations provide a lot of context in their declaration leading - to shorter, more concise configurations. However XML excels at wiring up components without touching - their source code or recompile them. Some prefer having the wiring close to the source while - others argue that annotated classes are no longer POJOs and further more that the configuration becomes - decentralized and harder to control. - - No matter the choice, Spring can accomodate both styles and even mix them together. It's worth pointing - out that through its JavaConfig option, Spring allows annotations to - be used in a non-invasive way, without touching the target components source code and that - in terms of tooling, all configuration styles are supported by the SpringSource Tool Suite. - + Are annotations better then XML for configuring Spring? + + The introduction of annotation based configurations raised the + question of whether this approach is better or not then XML. The short + answer is it depends.. The long answer is that each + approach has it's pros and cons and usually it's up to the developer to + decide which strategy suits her better. Due to the way they are defined, + annotations provide a lot of context in their declaration leading to + shorter, more concise configurations. However XML excels at wiring up + components without touching their source code or recompile them. Some + prefer having the wiring close to the source while others argue that + annotated classes are no longer POJOs and further more that the + configuration becomes decentralized and harder to control. + + No matter the choice, Spring can accomodate both styles and even + mix them together. It's worth pointing out that through its JavaConfig option, Spring allows annotations + to be used in a non-invasive way, without touching the target components + source code and that in terms of tooling, all configuration styles are + supported by the SpringSource Tool + Suite. - - - An alternative to XML setups is provided by annotation-based configuration which rely - on the bytecode metadata for wiring up components instead on angle-bracket declarations. - Instead of using XML to describe a bean wiring, the developers moves the configuration into - the component class itself by using annotations on relevant class, method or field declaration. - - As mentioned in , using a + + An alternative to XML setups is provided by annotation-based + configuration which rely on the bytecode metadata for wiring up components + instead on angle-bracket declarations. Instead of using XML to describe a + bean wiring, the developers moves the configuration into the component + class itself by using annotations on relevant class, method or field + declaration. As mentioned in , using a BeanPostProcessor in conjunction with annotations is a common means of extending the Spring IoC container. For example, Spring 2.0 introduced the possibility of enforcing required @@ -4441,17 +4574,16 @@ dataSource.url=jdbc:mysql:mydb @Qualifier, @Named, and @Provider if the JSR330 jar is present on the classpath. Use of these annotations also requires that certain BeanPostProcessors be registered - within the Spring container. - - Annotation injection is performed before XML injection, thus - the latter configuration will override the former for properties wired - through both approaches. - - - As always, you can register them as - individual bean definitions, but they can also be implicitly registered by - including the following tag in an XML-based Spring configuration (notice - the inclusion of the context namespace): + within the Spring container. + Annotation injection is performed + + before + + XML injection, thus the latter configuration will override the former for properties wired through both approaches. + As always, you can register them as individual bean definitions, + but they can also be implicitly registered by including the following tag + in an XML-based Spring configuration (notice the inclusion of the + context namespace): <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -5342,7 +5474,8 @@ public class JpaMovieFinder implements MovieFinder { by including the annotation-config attribute with a value of false. - - - contextClass - + Support for web applications with + <literal>AnnotationConfigWebApplicationContext</literal> + + 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: + +<web-app> + <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext + instead of the default XmlWebApplicationContext --> + <context-param> + <param-name>contextClass</param-name> + <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - + </param-value> + </context-param> - - - contextConfigLocation - com.acme.AppConfig - + specified for component-scanning --> + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value>com.acme.AppConfig</param-value> + </context-param> - - - org.springframework.web.context.ContextLoaderListener - + <!-- Bootstrap the root application context as usual using ContextLoaderListener --> + <listener> + <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> + </listener> - - - dispatcher - org.springframework.web.servlet.DispatcherServlet - - - contextClass - + <!-- Declare a Spring MVC DispatcherServlet as usual --> + <servlet> + <servlet-name>dispatcher</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> + <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext + instead of the default XmlWebApplicationContext --> + <init-param> + <param-name>contextClass</param-name> + <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - - contextConfigLocation - com.acme.web.MvcConfig - - + </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>com.acme.web.MvcConfig</param-value> + </init-param> + </servlet> - - - dispatcher - /main/* - -]]> + <!-- map all requests for /main/* to the dispatcher servlet --> + <servlet-mapping> + <servlet-name>dispatcher</servlet-name> + <url-pattern>/main/*</url-pattern> + </servlet-mapping> +</web-app>
Composing Java-based configurations +
Using the <literal>@Import</literal> 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 + + 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(); } } @@ -5925,40 +6076,43 @@ public class ConfigA { @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) { +} 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. - +} 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 <literal>@Bean</literal> 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. + Injecting dependencies on imported <literal>@Bean</literal> + 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! + @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 + 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; @@ -5990,24 +6144,30 @@ public static void main(String[] args) { }
- 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. + Fully-qualifying imported beans for ease of + navigation - 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 + 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; @@ -6015,15 +6175,13 @@ public class ServiceConfig { // 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, +} 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 + 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; @@ -6054,50 +6212,63 @@ 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 than the usual process of navigating interface-based code. +} 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 than 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. + + 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 <literal>@Configuration</literal> 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. + XML-centric use of <literal>@Configuration</literal> + 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 <literal>@Configuration</literal> classes as plain Spring - <literal><bean/></literal> 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 + Declaring <literal>@Configuration</literal> classes as + plain Spring <literal><bean/></literal> 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 + <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; @@ -6108,8 +6279,8 @@ public class AppConfig { public @Bean TransferService transferService() { return new TransferService(accountRepository()); } -} - system-test-config.xml +} system-test-config.xml <beans> <!-- enable processing of annotations such as @Autowired and @Configuration --> <context:annotation-config/> @@ -6122,14 +6293,11 @@ public class AppConfig { <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> -</beans> - - jdbc.properties +</beans> jdbc.properties jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa -jdbc.password= - - public static void main(String[] args) { +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); // ... @@ -6138,26 +6306,31 @@ jdbc.password= 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. + 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 <literal><context:component-scan/></literal> to pick up - <literal>@Configuration</literal> 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 + Using <literal><context:component-scan/></literal> to + pick up <literal>@Configuration</literal> 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"/> @@ -6168,21 +6341,21 @@ jdbc.password= <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> -</beans> - +</beans>
- <literal>@Configuration</literal> class-centric use of XML with - <literal>@ImportResource</literal> - 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 + <literal>@Configuration</literal> class-centric use of XML + with <literal>@ImportResource</literal> + + 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; @@ -6192,17 +6365,15 @@ public class AppConfig { public @Bean DataSource dataSource() { return new DriverManagerDataSource(url, username, password); } -} - - properties-config.xml +} properties-config.xml <beans> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> -</beans> - jdbc.properties +</beans> jdbc.properties jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa -jdbc.password= - public static void main(String[] args) { +jdbc.password= public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); TransferService transferService = ctx.getBean(TransferService.class); // ... @@ -6357,8 +6528,8 @@ 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 lifecycle! + with your objects and do not always need to rely on the container + lifecycle!
@@ -6490,10 +6661,12 @@ public class AppConfig {
Bean aliasing - As discussed in , it is sometimes desirable - to give a single bean multiple names, otherwise known as bean aliasing. - The name attribute of the @Bean annotation accepts - a String array for this purpose. @Configuration + As discussed in , it is + sometimes desirable to give a single bean multiple names, otherwise + known as bean aliasing. The + name attribute of the @Bean + annotation accepts a String array for this purpose. @Configuration public class AppConfig { @Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })