diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Conditional.java b/spring-context/src/main/java/org/springframework/context/annotation/Conditional.java
index f47aecf1741..578a6e2a6c5 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/Conditional.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/Conditional.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -16,6 +16,7 @@
package org.springframework.context.annotation;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -55,8 +56,9 @@ import java.lang.annotation.Target;
* @since 4.0
* @see Condition
*/
-@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
public @interface Conditional {
/**
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java
index 04627fb749b..49019333114 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/Configuration.java
@@ -231,7 +231,7 @@ import org.springframework.stereotype.Component;
* indicate they should be processed only if a given profile or profiles are active:
*
*
- * @Profile("embedded")
+ * @Profile("development")
* @Configuration
* public class EmbeddedDatabaseConfig {
*
@@ -251,6 +251,22 @@ import org.springframework.stereotype.Component;
* }
* }
*
+ * Alternatively, you may also declare profile conditions at the {@code @Bean} method level,
+ * e.g. for alternative bean variants within the same configuration class:
+ *
+ *
+ * @Configuration
+ * public class ProfileDatabaseConfig {
+ *
+ * @Bean("dataSource")
+ * @Profile("development")
+ * public DataSource embeddedDatabase() { ... }
+ *
+ * @Bean("dataSource")
+ * @Profile("production")
+ * public DataSource productionDatabase() { ... }
+ * }
+ *
* See the {@link Profile @Profile} and {@link org.springframework.core.env.Environment}
* javadocs for further details.
*
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Profile.java b/spring-context/src/main/java/org/springframework/context/annotation/Profile.java
index 36f609798cc..0838238d4a5 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/Profile.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/Profile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2017 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.
@@ -57,12 +57,24 @@ import org.springframework.core.env.ConfigurableEnvironment;
*
* If a given profile is prefixed with the NOT operator ({@code !}), the annotated
* component will be registered if the profile is not active — for example,
- * given {@code @Profile({"p1", "!p2"})}, registration will occur if profile 'p1' is active or
- * if profile 'p2' is not active.
+ * given {@code @Profile({"p1", "!p2"})}, registration will occur if profile 'p1' is active
+ * or if profile 'p2' is not active.
*
*
If the {@code @Profile} annotation is omitted, registration will occur regardless
* of which (if any) profiles are active.
*
+ *
NOTE: With {@code @Profile} on {@code @Bean} methods, a special scenario may
+ * apply: In the case of overloaded {@code @Bean} methods of the same Java method name
+ * (analogous to constructor overloading), an {@code @Profile} condition needs to be
+ * consistently declared on all overloaded methods. If the conditions are inconsistent,
+ * only the condition on the first declaration among the overloaded methods will matter.
+ * {@code @Profile} can therefore not be used to select an overloaded method with a
+ * particular argument signature over another; resolution between all factory methods
+ * for the same bean follows Spring's constructor resolution algorithm at creation time.
+ * Use distinct Java method names pointing to the same {@link @Bean#name bean name}
+ * if you'd like to define alternative beans with different profile conditions;
+ * see {@code ProfileDatabaseConfig} in {@link Configuration @Configuration}'s javadoc.
+ *
*
When defining Spring beans via XML, the {@code "profile"} attribute of the
* {@code } element may be used. See the documentation in the
* {@code spring-beans} XSD (version 3.1 or greater) for details.
@@ -78,8 +90,8 @@ import org.springframework.core.env.ConfigurableEnvironment;
* @see Conditional
* @see org.springframework.test.context.ActiveProfiles
*/
-@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
diff --git a/src/asciidoc/core-beans.adoc b/src/asciidoc/core-beans.adoc
index a4472c1c8ea..aa8a32aa661 100644
--- a/src/asciidoc/core-beans.adoc
+++ b/src/asciidoc/core-beans.adoc
@@ -7402,6 +7402,9 @@ jdbc.password=
}
----
+
+
+
[[beans-environment]]
== Environment abstraction
@@ -7423,6 +7426,8 @@ on. The role of the `Environment` object with relation to properties is to provi
user with a convenient service interface for configuring property sources and resolving
properties from them.
+
+
[[beans-definition-profiles]]
=== Bean definition profiles
@@ -7497,7 +7502,7 @@ can rewrite the `dataSource` configuration as follows:
[subs="verbatim,quotes"]
----
@Configuration
- **@Profile("dev")**
+ **@Profile("development")**
public class StandaloneDataConfig {
@Bean
@@ -7549,8 +7554,20 @@ of creating a custom _composed annotation_. The following example defines a cust
}
----
+[TIP]
+====
+If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods and
+`@Import` annotations associated with that class will be bypassed unless one or more of
+the specified profiles are active. If a `@Component` or `@Configuration` class is marked
+with `@Profile({"p1", "p2"})`, that class will not be registered/processed unless
+profiles 'p1' and/or 'p2' have been activated. If a given profile is prefixed with the
+NOT operator (`!`), the annotated element will be registered if the profile is **not**
+active. For example, given `@Profile({"p1", "!p2"})`, registration will occur if profile
+'p1' is active or if profile 'p2' is not active.
+====
+
`@Profile` can also be declared at the method level to include only one particular bean
-of a configuration class:
+of a configuration class, e.g. for alternative variants of a particular bean:
[source,java,indent=0]
[subs="verbatim,quotes"]
@@ -7558,9 +7575,9 @@ of a configuration class:
@Configuration
public class AppConfig {
- @Bean
- **@Profile("dev")**
- public DataSource devDataSource() {
+ @Bean("dataSource")
+ **@Profile("development")**
+ public DataSource standaloneDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
@@ -7568,29 +7585,37 @@ of a configuration class:
.build();
}
- @Bean
+ @Bean("dataSource")
**@Profile("production")**
- public DataSource productionDataSource() throws Exception {
+ public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
----
-[TIP]
+[NOTE]
====
-If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods and
-`@Import` annotations associated with that class will be bypassed unless one or more of
-the specified profiles are active. If a `@Component` or `@Configuration` class is marked
-with `@Profile({"p1", "p2"})`, that class will not be registered/processed unless
-profiles 'p1' and/or 'p2' have been activated. If a given profile is prefixed with the
-NOT operator (`!`), the annotated element will be registered if the profile is **not**
-active. For example, given `@Profile({"p1", "!p2"})`, registration will occur if profile
-'p1' is active or if profile 'p2' is not active.
+With `@Profile` on `@Bean` methods, a special scenario may apply: In the case of
+overloaded `@Bean` methods of the same Java method name (analogous to constructor
+overloading), an `@Profile` condition needs to be consistently declared on all
+overloaded methods. If the conditions are inconsistent, only the condition on the
+first declaration among the overloaded methods will matter. `@Profile` can therefore
+not be used to select an overloaded method with a particular argument signature over
+another; resolution between all factory methods for the same bean follows Spring's
+constructor resolution algorithm at creation time.
+
+If you would like to define alternative beans with different profile conditions,
+use distinct Java method names pointing to the same bean name via the `@Bean` name
+attribute, as indicated in the example above. If the argument signatures are all
+the same (e.g. all of the variants have no-arg factory methods), this is the only
+way to represent such an arrangement in a valid Java class in the first place
+(since there can only be one method of a particular name and argument signature).
====
+
[[beans-definition-profiles-xml]]
-=== XML bean definition profiles
+==== XML bean definition profiles
The XML counterpart is the `profile` attribute of the `` element. Our sample
configuration above can be rewritten in two XML files as follows:
@@ -7598,7 +7623,7 @@ configuration above can be rewritten in two XML files as follows:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
- ` elements within the
-
+
@@ -7671,7 +7696,7 @@ it programmatically against the `Environment` API which is available via an
[subs="verbatim,quotes"]
----
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
- ctx.getEnvironment().setActiveProfiles("dev");
+ ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();
----