diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java index a9762efcd5f..23bdf1a40aa 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java @@ -23,15 +23,18 @@ import org.springframework.util.Assert; /** * Standalone application context, accepting annotated classes as input - in particular - * {@link org.springframework.context.annotation.Configuration @Configuration}-annotated - * classes, but also plain {@link org.springframework.stereotype.Component @Components} - * and JSR-330 compliant classes using {@code javax.inject} annotations. Allows for - * registering classes one by one ({@link #register}) as well as for classpath scanning - * ({@link #scan}). + * {@link Configuration @Configuration}-annotated classes, but also plain + * {@link org.springframework.stereotype.Component @Component} types and JSR-330 compliant + * classes using {@code javax.inject} annotations. Allows for registering classes one by + * one using {@link #register(Class...)} as well as for classpath scanning using + * {@link #scan(String...)}. * - *

In case of multiple Configuration classes, {@link Bean} methods defined in later - * classes will override those defined in earlier classes. This can be leveraged to - * deliberately override certain bean definitions via an extra Configuration class. + *

In case of multiple {@code @Configuration} classes, @{@link Bean} methods defined in + * later classes will override those defined in earlier classes. This can be leveraged to + * deliberately override certain bean definitions via an extra {@code @Configuration} + * class. + * + *

See @{@link Configuration} Javadoc for usage examples. * * @author Chris Beams * @author Juergen Hoeller diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java index 818ce705261..d154d42e4bc 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java @@ -67,8 +67,7 @@ import org.springframework.beans.factory.annotation.Autowire; * @Bean * public static PropertyPlaceholderConfigurer ppc() { * // instantiate, configure and return ppc ... - * } - * + * } * By marking this method as {@code static}, it can be invoked without causing instantiation of its * declaring {@code @Configuration} class, thus avoiding the above-mentioned lifecycle conflicts. * Note however that {@code static} {@code @Bean} methods will not be enhanced for scoping and AOP diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java index 86ef6ee73cc..a730a96c477 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,37 +28,274 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** - * Indicates that a class declares one or more {@link Bean} methods and may be processed - * by the Spring container to generate bean definitions and service requests for those beans - * at runtime. + * Indicates that a class declares one or more @{@link Bean} methods and may be processed + * by the Spring container to generate bean definitions and service requests for those + * beans at runtime, for example: + *

+ * @Configuration
+ * public class AppConfig {
+ *     @Bean
+ *     public MyBean myBean() {
+ *         // instantiate, configure and return bean ...
+ *     }
+ * }
* - *

Configuration is meta-annotated as a {@link Component}, therefore Configuration - * classes are candidates for component-scanning and may also take advantage of - * {@link Autowired} at the field and method but not at the constructor level. - * Externalized values may be wired into Configuration classes using the {@link Value} - * annotation. + *

Bootstrapping {@code @Configuration} classes

+ *

Via {@code AnnotationConfigApplicationContext}

+ * {@code @Configuration} classes are typically bootstrapped using either + * {@link AnnotationConfigApplicationContext} or its web-capable variant, + * {@link org.springframework.web.context.support.AnnotationConfigWebApplicationContext + * AnnotationConfigWebApplicationContext}. + * A simple example with the former follows: + *
+ * AnnotationConfigApplicationContext ctx =
+ *     new AnnotationConfigApplicationContext();
+ * ctx.register(AppConfig.class);
+ * ctx.refresh();
+ * MyBean myBean = ctx.getBean(MyBean.class);
+ * // use myBean ...
* - *

May be used in conjunction with the {@link Lazy} annotation to indicate that all Bean - * methods declared within this class are by default lazily initialized. + * See {@link AnnotationConfigApplicationContext} Javadoc for further details and see + * {@link org.springframework.web.context.support.AnnotationConfigWebApplicationContext + * AnnotationConfigWebApplicationContext} for {@code web.xml} configuration instructions. * - *

Constraints

+ *

Via Spring {@code } XML

+ *

As an alternative to registering {@code @Configuration} classes directly against an + * {@code AnnotationConfigApplicationContext}, {@code @Configuration} classes may be + * declared as normal {@code } definitions within Spring XML files: + *

+ * {@code
+ * 
+ *    
+ *    
+ * 
+ * }
+ * + * In the example above, {@code } is required in order to + * enable {@link ConfigurationClassPostProcessor} and other annotation-related + * post processors that facilitate handling {@code @Configuration} classes. + * + *

Via component scanning

+ *

{@code @Configuration} is meta-annotated with @{@link Component}, therefore + * {@code @Configuration} classes are candidates for component scanning (typically using + * Spring XML's {@code } element) and therefore may also take + * advantage of @{@link Autowired}/@{@link Inject} at the field and method level (but not + * at the constructor level). + *

{@code @Configuration} classes may not only be bootstrapped using + * component scanning, but may also themselves configure component scanning using + * the @{@link ComponentScan} annotation: + *

+ * @Configuration
+ * @ComponentScan("com.acme.app.services")
+ * public class AppConfig {
+ *     // various @Bean definitions ...
+ * }
+ * + * See @{@link ComponentScan} Javadoc for details. + * + * + *

Working with externalized values

+ *

Using the {@code Environment} API

+ * Externalized values may be looked up by injecting the Spring + * {@link org.springframework.core.env.Environment Environment} into a + * {@code @Configuration} class: + *
+ * @Configuration
+ * public class AppConfig {
+ *     @Inject Environment env;
+ *
+ *     @Bean
+ *     public MyBean myBean() {
+ *         MyBean myBean = new MyBean();
+ *         myBean.setName(env.getProperty("bean.name"));
+ *         return myBean;
+ *     }
+ * }
+ * + * Properties resolved through the {@code Environment} reside in one or more "property + * source" objects, and {@code @Configuration} classes may contribute property sources to + * the {@code Environment} object using the @{@link PropertySources} annotation: + *
+ * @Configuration
+ * @PropertySource("classpath:/com/acme/app.properties")
+ * public class AppConfig {
+ *     @Inject Environment env;
+ *
+ *     @Bean
+ *     public MyBean myBean() {
+ *         return new MyBean(env.getProperty("bean.name"));
+ *     }
+ * }
+ * + * See {@link org.springframework.core.env.Environment Environment} + * and @{@link PropertySource} Javadoc for further details. + * + *

Using the {@code @Value} annotation

+ * Externalized values may be 'wired into' {@code @Configuration} classes using + * the @{@link Value} annotation: + *
+ * @Configuration
+ * @PropertySource("classpath:/com/acme/app.properties")
+ * public class AppConfig {
+ *     @Value("${bean.name}") String beanName;
+ *
+ *     @Bean
+ *     public MyBean myBean() {
+ *         return new MyBean(beanName);
+ *     }
+ * }
+ * + * This approach is most useful when using Spring's + * {@link org.springframework.context.support.PropertySourcesPlaceholderConfigurer + * PropertySourcesPlaceholderConfigurer}, usually enabled via XML with + * {@code }. See the section below on composing + * {@code @Configuration} classes with Spring XML using {@code @ImportResource}, + * see @{@link Value} Javadoc, and see @{@link Bean} Javadoc for details on working with + * {@code BeanFactoryPostProcessor} types such as + * {@code PropertySourcesPlaceholderConfigurer}. + * + *

Composing {@code @Configuration} classes

+ *

With the {@code @Import} annotation

+ *

{@code @Configuration} classes may be composed using the @{@link Import} annotation, + * not unlike the way that {@code } works in Spring XML. Because + * {@code @Configuration} objects are managed as Spring beans within the container, + * imported configurations may be injected using {@code @Autowired} or {@code @Inject}: + *

+ * @Configuration
+ * public class DatabaseConfig {
+ *     @Bean
+ *     public DataSource dataSource() {
+ *         // instantiate, configure and return DataSource
+ *     }
+ * }
+ *
+ * @Configuration
+ * @Import(DatabaseConfig.class)
+ * public class AppConfig {
+ *     @Inject DatabaseConfig dataConfig;
+ *
+ *     @Bean
+ *     public MyBean myBean() {
+ *         // reference the dataSource() bean method
+ *         return new MyBean(dataConfig.dataSource());
+ *     }
+ * }
+ * + * Now both {@code AppConfig} and the imported {@code DatabaseConfig} can be bootstrapped + * by registering only {@code AppConfig} against the Spring context: + * + *
+ * new AnnotationConfigApplicationContext(AppConfig.class);
+ * + *

With the {@code @Profile} annotation

+ * {@code @Configuration} classes may be marked with the @{@link Profile} annotation to + * indicate they should be processed only if a given profile or profiles are + * active: + *
+ * @Profile("embedded")
+ * @Configuration
+ * public class EmbeddedDatabaseConfig {
+ *     @Bean
+ *     public DataSource dataSource() {
+ *         // instantiate, configure and return embedded DataSource
+ *     }
+ * }
+ *
+ * @Profile("production")
+ * @Configuration
+ * public class ProductionDatabaseConfig {
+ *     @Bean
+ *     public DataSource dataSource() {
+ *         // instantiate, configure and return production DataSource
+ *     }
+ * }
+ * + * See @{@link Profile} and {@link org.springframework.core.env.Environment} Javadoc for + * further details. + * + *

With Spring XML using the {@code @ImportResource} annotation

+ * As mentioned above, {@code @Configuration} classes may be declared as regular Spring + * {@code } definitions within Spring XML files. It is also possible to + * import Spring XML configuration files into {@code @Configuration} classes using + * the @{@link ImportResource} annotation. Bean definitions imported from XML can be + * injected using {@code @Autowired} or {@code @Import}: + *
+ * @Configuration
+ * @ImportResource("classpath:/com/acme/database-config.xml")
+ * public class AppConfig {
+ *     @Inject DataSource dataSource; // from XML
+ *
+ *     @Bean
+ *     public MyBean myBean() {
+ *         // inject the XML-defined dataSource bean
+ *         return new MyBean(this.dataSource);
+ *     }
+ * }
+ * + *

Configuring lazy initialization

+ *

By default, {@code @Bean} methods will be eagerly instantiated at container + * bootstrap time. To avoid this, {@code @Configuration} may be used in conjunction with + * the @{@link Lazy} annotation to indicate that all {@code @Bean} methods declared within + * the class are by default lazily initialized. Note that {@code @Lazy} may be used on + * individual {@code @Bean} methods as well. + * + *

Testing support for {@code @Configuration} classes

+ * The Spring TestContext framework available in the {@code spring-test} module + * provides the + * {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration} + * annotation, which as of Spring 3.1 can accept an array of {@code @Configuration} + * {@code Class} objects: + *
+ * @RunWith(SpringJUnit4ClassRunner.class)
+ * @ContextConfiguration(classes={AppConfig.class, DatabaseConfig.class})
+ * public class MyTests {
+ *
+ *     @Autowired MyBean myBean;
+ *
+ *     @Autowired DataSource dataSource;
+ *
+ *     @Test
+ *     public void test() {
+ *         // assertions against myBean ...
+ *     }
+ * }
+ * + * See TestContext framework reference documentation for details. + * + *

Enabling built-in Spring features using {@code @Enable} annotations

+ * Spring features such as asynchronous method execution, scheduled task execution, + * annotation driven transaction management, and even Spring MVC can be enabled and + * configured from {@code @Configuration} + * classes using their respective "{@code @Enable}" annotations. See + * {@link org.springframework.scheduling.annotation.EnableAsync @EnableAsync}, + * {@link org.springframework.scheduling.annotation.EnableScheduling @EnableScheduling}, + * {@link org.springframework.transaction.annotation.EnableTransactionManagement @EnableTransactionManagement}, and + * {@link org.springframework.web.servlet.config.annotation.EnableWebMvc @EnableWebMvc} + * for details. + * + *

Constraints when authoring {@code @Configuration} classes

*
    - *
  • Configuration classes must be non-final - *
  • Configuration classes must be non-local (may not be declared within a method) - *
  • Configuration classes must have a default/no-arg constructor and may not use - * {@link Autowired} constructor parameters. Nested configuration classes must be - * {@code static} + *
  • @Configuration classes must be non-final + *
  • @Configuration classes must be non-local (may not be declared within a method) + *
  • @Configuration classes must have a default/no-arg constructor and may not + * use @{@link Autowired} constructor parameters. Any nested configuration classes + * must be {@code static} *
* * @author Rod Johnson * @author Chris Beams * @since 3.0 - * @see Import - * @see Lazy * @see Bean - * @see ConfigurationClassPostProcessor + * @see Profile + * @see Import + * @see ImportResource + * @see ComponentScan + * @see Lazy + * @see PropertySource * @see AnnotationConfigApplicationContext - * @see org.springframework.context.annotation.Profile + * @see ConfigurationClassPostProcessor + * @see org.springframework.core.env.Environment + * @see org.springframework.test.context.ContextConfiguration */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Import.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Import.java index 4f406fdd663..36d6d557321 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Import.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Import.java @@ -23,12 +23,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Indicates one or more {@link Configuration @Configuration} classes to import. + * Indicates one or more @{@link @Configuration} classes to import. * *

Provides functionality equivalent to the {@code } element in Spring XML. - * Only supported for actual {@code @Configuration}-annotated classes. + * Only supported for actual {@code @Configuration}-annotated classes and implementations + * of the {@link ImportSelector} interface. * - *

{@code @Bean} definitions declared in imported {@code @Configuration} classes + *

{@link Bean @Bean} definitions declared in imported {@code @Configuration} classes * should be accessed by using {@link Autowired @Autowired} injection. Either the bean * itself can be autowired, or the configuration class instance declaring the bean can be * autowired. The latter approach allows for explicit, IDE-friendly navigation between @@ -41,6 +42,7 @@ import java.lang.annotation.Target; * @since 3.0 * @see Configuration * @see ImportResource + * @see ImportSelector */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ImportSelector.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ImportSelector.java index 6527d10de4e..5cc718f867a 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ImportSelector.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ImportSelector.java @@ -18,15 +18,15 @@ package org.springframework.context.annotation; import org.springframework.core.type.AnnotationMetadata; - /** - * Interface to be implemented by types that determine - * which @{@link Configuration} class(es) should be imported based on - * a given selection criteria, usually an annotation attribute. + * Interface to be implemented by types that determine which @{@link Configuration} + * class(es) should be imported based on a given selection criteria, usually one or more + * annotation attributes. * * @author Chris Beams * @since 3.1 * @see Import + * @see Configuration */ public interface ImportSelector {