Recommendation for consistent @Profile declarations on overloaded @Bean methods
Issue: SPR-15266
(cherry picked from commit 5d3249f)
This commit is contained in:
parent
a2b356162e
commit
6c370ed28d
|
|
@ -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 {
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ import org.springframework.stereotype.Component;
|
|||
* indicate they should be processed only if a given profile or profiles are <em>active</em>:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Profile("embedded")
|
||||
* @Profile("development")
|
||||
* @Configuration
|
||||
* public class EmbeddedDatabaseConfig {
|
||||
*
|
||||
|
|
@ -251,6 +251,22 @@ import org.springframework.stereotype.Component;
|
|||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* Alternatively, you may also declare profile conditions at the {@code @Bean} method level,
|
||||
* e.g. for alternative bean variants within the same configuration class:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* public class ProfileDatabaseConfig {
|
||||
*
|
||||
* @Bean("dataSource")
|
||||
* @Profile("development")
|
||||
* public DataSource embeddedDatabase() { ... }
|
||||
*
|
||||
* @Bean("dataSource")
|
||||
* @Profile("production")
|
||||
* public DataSource productionDatabase() { ... }
|
||||
* }</pre>
|
||||
*
|
||||
* See the {@link Profile @Profile} and {@link org.springframework.core.env.Environment}
|
||||
* javadocs for further details.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
|||
*
|
||||
* <p>If a given profile is prefixed with the NOT operator ({@code !}), the annotated
|
||||
* component will be registered if the profile is <em>not</em> active — for example,
|
||||
* given {@code @Profile({"p1", "!p2"})}, registration will occur if profile 'p1' is active or
|
||||
* if profile 'p2' is <em>not</em> active.
|
||||
* given {@code @Profile({"p1", "!p2"})}, registration will occur if profile 'p1' is active
|
||||
* or if profile 'p2' is <em>not</em> active.
|
||||
*
|
||||
* <p>If the {@code @Profile} annotation is omitted, registration will occur regardless
|
||||
* of which (if any) profiles are active.
|
||||
*
|
||||
* <p><b>NOTE:</b> 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.
|
||||
* <b>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</b>;
|
||||
* see {@code ProfileDatabaseConfig} in {@link Configuration @Configuration}'s javadoc.
|
||||
*
|
||||
* <p>When defining Spring beans via XML, the {@code "profile"} attribute of the
|
||||
* {@code <beans>} 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 {
|
||||
|
|
|
|||
|
|
@ -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,34 +7554,6 @@ of creating a custom _composed annotation_. The following example defines a cust
|
|||
}
|
||||
----
|
||||
|
||||
`@Profile` can also be declared at the method level to include only one particular bean
|
||||
of a configuration class:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
**@Profile("dev")**
|
||||
public DataSource devDataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScript("classpath:com/bank/config/sql/schema.sql")
|
||||
.addScript("classpath:com/bank/config/sql/test-data.sql")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
**@Profile("production")**
|
||||
public DataSource productionDataSource() throws Exception {
|
||||
Context ctx = new InitialContext();
|
||||
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[TIP]
|
||||
====
|
||||
If a `@Configuration` class is marked with `@Profile`, all of the `@Bean` methods and
|
||||
|
|
@ -7589,8 +7566,56 @@ active. For example, given `@Profile({"p1", "!p2"})`, registration will occur if
|
|||
'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, e.g. for alternative variants of a particular bean:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean("dataSource")
|
||||
**@Profile("development")**
|
||||
public DataSource standaloneDataSource() {
|
||||
return new EmbeddedDatabaseBuilder()
|
||||
.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScript("classpath:com/bank/config/sql/schema.sql")
|
||||
.addScript("classpath:com/bank/config/sql/test-data.sql")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean("dataSource")
|
||||
**@Profile("production")**
|
||||
public DataSource jndiDataSource() throws Exception {
|
||||
Context ctx = new InitialContext();
|
||||
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
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 `<beans>` 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"]
|
||||
----
|
||||
<beans profile="dev"
|
||||
<beans profile="development"
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
|
|
@ -7637,7 +7662,7 @@ It is also possible to avoid that split and nest `<beans/>` elements within the
|
|||
|
||||
<!-- other bean definitions -->
|
||||
|
||||
<beans profile="dev">
|
||||
<beans profile="development">
|
||||
<jdbc:embedded-database id="dataSource">
|
||||
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
|
||||
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
|
||||
|
|
@ -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();
|
||||
----
|
||||
|
|
|
|||
Loading…
Reference in New Issue