1.13. Environment Abstraction

上一节 1.12. Java-based Container Configuration

目录

下一节 1.14. Registering a LoadTimeWeaver

1.13. Environment Abstraction

The Environment interface is an abstraction integrated in the container that models two key aspects of the application environment: profiles and properties.

1.13. 环境抽象类
环境接口是集成在容器中的抽象类,它为应用程序环境的两个关键方面建模: 
profiles和properties。

A profile is a named, logical group of bean definitions to be registered with the container only if the given profile is active. Beans may be assigned to a profile whether defined in XML or with annotations. The role of the Environment object with relation to profiles is in determining which profiles (if any) are currently active, and which profiles (if any) should be active by default.

profile是一个命名的bean definitions逻辑组,只有在给定的 profile 
处于活动状态时才向容器注册。
bean可以被分配给一个配置文件,无论这个配置文件是用XML定义的还是用注释定义的。
与概要文件相关的Environment对象的作用是确定哪些概要文件(如果有的话)
当前处于活动状态,以及默认情况下哪些概要文件(如果有的话)应该处于活动状态。

Properties play an important role in almost all applications and may originate from a variety of sources: properties files, JVM system properties, system environment variables, JNDI, servlet context parameters, ad-hoc Properties objects, Map objects, and so on. The role of the Environment object with relation to properties is to provide the user with a convenient service interface for configuring property sources and resolving properties from them.

Properties在几乎所有的应用程序中都扮演着重要的角色,并且可以来自各种来源:
properties文件、JVM系统属性、系统环境变量、JNDI、servlet上下文参数、
ad-hoc 属性对象、Map对象等等。
与属性相关的环境对象的作用是为用户提供一个方便的服务接口,用于配置
property资源和从属性源解析属性。

1.13.1. Bean Definition Profiles

Bean definition profiles provide a mechanism in the core container that allows for registration of different beans in different environments. The word, “environment,” can mean different things to different users, and this feature can help with many use cases, including:

1.13.1. Bean定义概要文件
Bean definition profiles 文件在核心容器中提供了一种机制,
允许在不同环境中注册不同的Bean。
“环境”这个词对不同的用户可能意味着不同的东西,这个特性可以帮助很多用例,
包括:

  • Working against an in-memory datasource in development versus looking up that same datasource from JNDI when in QA or production.
  • Registering monitoring infrastructure only when deploying an application into a performance environment.
  • Registering customized implementations of beans for customer A versus customer B deployments.
* 在开发中使用内存中的数据源,而在QA或生产中从JNDI查找相应的数据源。
* 只有在部署应用程序到性能环境时才注册监控基础设施。
* 为客户A和客户B部署注册定制的bean实现。

Consider the first use case in a practical application that requires a DataSource. In a test environment, the configuration might resemble the following:

考虑需要数据源的实际应用程序中的第一个用例。在测试环境中,配置可能类似如下:

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("my-schema.sql")
        .addScript("my-test-data.sql")
        .build();
}

Now consider how this application can be deployed into a QA or production environment, assuming that the datasource for the application is registered with the production application server’s JNDI directory. Our dataSource bean now looks like the following listing:

现在考虑如何将该应用程序部署到QA或生产环境中,
假设应用程序的数据源已注册到生产应用程序服务器的JNDI目录中。
我们的数据源bean现在看起来如下所示:

@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}

The problem is how to switch between using these two variations based on the current environment. Over time, Spring users have devised a number of ways to get this done, usually relying on a combination of system environment variables and XML statements containing ${placeholder} tokens that resolve to the correct configuration file path depending on the value of an environment variable. Bean definition profiles is a core container feature that provides a solution to this problem.

问题是如何根据当前环境在使用这两种状况之间切换。
随着时间的推移,Spring用户已经设计了许多方法来实现这一点,
通常依赖于系统环境变量和XML <import/> 包含${placeholder}标记的语句,
根据环境变量的值解析为正确的配置文件路径。
Bean definition profile 文件是为这个问题提供解决方案的核心容器特性。

If we generalize the use case shown in the preceding example of environment-specific bean definitions, we end up with the need to register certain bean definitions in certain contexts but not in others. You could say that you want to register a certain profile of bean definitions in situation A and a different profile in situation B. We start by updating our configuration to reflect this need.

如果我们泛化前面环境特定bean definition示例中所示的用例,
我们最终需要在某些上下文中注册某些bean定义,而不是在其他上下文中。
您可以说,您希望在情形A 中注册某个bean定义的 profile文件,
在情形b中注册一个不同的 profile文件。
我们首先更新配置以反映这一需求。

Using @Profile

The @Profile annotation lets you indicate that a component is eligible for registration when one or more specified profiles are active. Using our preceding example, we can rewrite the dataSource configuration as follows:

使用 @Profile
当一个或多个指定的 profiles文件处于活动状态时,
@Profile注释可以指示组件是否有资格注册。
使用我们前面的例子,我们可以重写数据源配置如下:

@Configuration
@Profile("development")
public class StandaloneDataConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }
}
@Configuration
@Profile("production")
public class JndiDataConfig {
    @Bean(destroyMethod="")
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

As mentioned earlier, with @Bean methods, you typically choose to use programmatic JNDI lookups, by using either Spring’s JndiTemplate/JndiLocatorDelegate helpers or the straight JNDI InitialContext usage shown earlier but not the JndiObjectFactoryBean variant, which would force you to declare the return type as the FactoryBean type.

@bean方法,如前所述,您通常选择使用程序化的JNDI查找,
通过使用Spring的JndiTemplate / JndiLocatorDelegate 帮助类
或直接使用JNDI InitialContext ,但不是早些时候显示的
JndiObjectFactoryBean变体,
这将迫使你声明返回类型作为FactoryBean类型。

The profile string may contain a simple profile name (for example, production) or a profile expression. A profile expression allows for more complicated profile logic to be expressed (for example, production & us-east). The following operators are supported in profile expressions:

profile 字符串可以包含一个简单的profile 名称(例如,产品)或概要表达式。
profile表达式允许表达更复杂的profile逻辑(例如,production & us-east)。
配置文件表达式支持以下操作符:

  • !: A logical “not” of the profile
  • &: A logical “and” of the profiles
  • |: A logical “or” of the profiles

You cannot mix the & and | operators without using parentheses. For example, production & us-east | eu-central is not a valid expression. It must be expressed as production & (us-east | eu-central).

如果不使用圆括号,就不能混合使用&和|操作符。
例如,production & us-east | eu-central不是一个有效的表达式。
它必须表示为 production & (us-east | eu-central)。


parentheses 
英 /pə'renθəsɪz/  美 /pə'rɛnθəsɪz/
圆括号括号圆括弧小括弧

You can use @Profile as a meta-annotation for the purpose of creating a custom composed annotation. The following example defines a custom @Production annotation that you can use as a drop-in replacement for @Profile(“production”):

您可以使用@Profile作为元注释,以创建自定义组合注释。
下面的例子定义了一个自定义的@Production注释,你可以使用它来替代@Profile(“production”):

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("production")
public @interface Production {
}

If a @Configuration class is marked with @Profile, all of the @Bean methods and @Import annotations associated with that class are 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 is not registered or processed unless profiles ‘p1’ or ‘p2’ have been activated. If a given profile is prefixed with the NOT operator (!), the annotated element is registered only 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.

如果一个@Configuration类被标记为@Profile,那么与该类关联的
所有@Bean方法和@Import注释都将被绕过,除非指定的一个或
多个概要文件是活动的。
如果@Component或@Configuration类被标记为
@Profile({“p1”,“p2”}),那么这个类就不会被注册或处理,
除非配置文件“p1”或“p2”是激活状态。
如果给定的概要文件以NOT操作符(!)作为前缀,那么仅在概要文件
不活动时才会注册注释元素。例如,给定@Profile({“p1”,“!p2”}),
如果配置文件“p1”是活动的,或者配置文件“p2”不是活动的,就会进行注册。

@Profile can also be declared at the method level to include only one particular bean of a configuration class (for example, for alternative variants of a particular bean), as the following example shows:

@Profile也可以在方法级别声明,只包含配置类的一个特定bean
(例如,一个特定bean的其他变体),如下面的例子所示:

@Configuration
public class AppConfig {
    @Bean("dataSource")
    @Profile("development")  @1 
    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")  @2
    public DataSource jndiDataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

@1 The standaloneDataSource method is available only in the development profile.
@2 The jndiDataSource method is available only in the production profile.

@1 standaloneDataSource方法只在开发环境的profile文件中可用。
@2 jndiDataSource方法只在生产环境profile文件中可用。

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), a @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 matters. Therefore, @Profile can 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.

对于@Bean方法上的@Profile,可能会应用一种特殊的场景:
在重载了相同Java方法名的@Bean方法的情况下(类似于构造函数重载),
需要在所有重载的方法上一致地声明一个@Profile条件。
如果条件不一致,则只有重载方法中第一个声明的条件才会起作用。
因此,@Profile不能用于选择具有特定参数签名的重载方法。
同一个bean的所有工厂方法之间的解析遵循Spring的构造函数解析算法。

If you want to define alternative beans with different profile conditions, use distinct Java method names that point to the same bean name by using the @Bean name attribute, as shown in the preceding example. If the argument signatures are all the same (for example, 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).

如果您希望定义具有不同 profile 文件条件的可选bean,
请使用不同的Java方法名称,通过使用@Bean name属性指向相同的bean名称,
如前面的示例所示。
如果参数签名都是相同的(例如,所有的变量都不带参数工厂方法),这是唯一的
方式来表示这种安排在第一时间有效的Java类
(因为只能有一个方法的名称和参数签名)。

XML Bean Definition Profiles

The XML counterpart is the profile attribute of the element. Our preceding sample configuration can be rewritten in two XML files, as follows:

XML 格式的Bean Definition Profile文件
XML对应的是profile文件属性  <beans>元素。
我们前面的示例配置可以在两个XML文件中重写,如下:

<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"
    xsi:schemaLocation="...">

    <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"/>
    </jdbc:embedded-database>
</beans>
<beans profile="production"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>

It is also possible to avoid that split and nest elements within the same file, as the following example shows:

也可以在同一个文件中,避免 分裂和嵌套<beans/>元素,如下例所示:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <!-- other bean definitions -->

    <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"/>
        </jdbc:embedded-database>
    </beans>

    <beans profile="production">
        <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
    </beans>
</beans>

The spring-bean.xsd has been constrained to allow such elements only as the last ones in the file. This should help provide flexibility without incurring clutter in the XML files.

spring bean.xsd被限制为只允许将这样的元素作为文件中的最后一个元素。
这将有助于提供灵活性,而不会导致XML文件的混乱。

The XML counterpart does not support the profile expressions described earlier. It is possible, however, to negate a profile by using the ! operator. It is also possible to apply a logical “and” by nesting the profiles, as the following example shows:

对应的XML格式不支持前面描述的 profile文件表达式。
但是,可以通过使用!操作符使 profile 失效。
也可以通过嵌套的profile文件来应用逻辑“和”,如下面的例子所示:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <!-- other bean definitions -->

    <beans profile="production">
        <beans profile="us-east">
            <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
        </beans>
    </beans>
</beans>

In the preceding example, the dataSource bean is exposed if both the production and us-east profiles are active.

在前面的示例中,如果production 和 us-east profiles文件都是活动的,
则将公开数据源bean。

Activating a Profile

Now that we have updated our configuration, we still need to instruct Spring which profile is active. If we started our sample application right now, we would see a NoSuchBeanDefinitionException thrown, because the container could not find the Spring bean named dataSource.

激活一个 Profile 文件
现在我们已经更新了配置,我们仍然需要指示Spring哪个配置文件是活动的。
如果我们现在启动示例应用程序,我们将看到抛出NoSuchBeanDefinitionException异常,
因为容器无法找到名为dataSource的Spring bean。

Activating a profile can be done in several ways, but the most straightforward is to do it programmatically against the Environment API which is available through an ApplicationContext. The following example shows how to do so:

激活一个profile文件可以通过多种方式完成,但是最直接的方式是根据
通过ApplicationContext提供的Environment API编程地激活它。
下面的例子展示了如何做到这一点:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

In addition, you can also declaratively activate profiles through the spring.profiles.active property, which may be specified through system environment variables, JVM system properties, servlet context parameters in web.xml, or even as an entry in JNDI (see PropertySource Abstraction). In integration tests, active profiles can be declared by using the @ActiveProfiles annotation in the spring-test module (see context configuration with environment profiles).

此外,您也可以通过spring.profiles.active 属性声明性地激活配置文件,
可以通过系统环境变量、JVM系统属性、web.xml 中的servlet上下文参数
或者甚至作为JNDI中的一个条目来指定(请参阅章节-PropertySource Abstraction)。
在集成测试中,可以使用spring-test模块中的@ActiveProfiles注释来声明活动概要文件
(请参阅章节-context configuration with environment profiles)。

Note that profiles are not an “either-or” proposition. You can activate multiple profiles at once. Programmatically, you can provide multiple profile names to the setActiveProfiles() method, which accepts String… varargs. The following example activates multiple profiles:

请注意,配置文件不是一个“非此即彼”的命题。
您可以同时激活多个配置文件。
通过编程,您可以向setActiveProfiles()方法提供多个概要文件名称,
该方法接受  String… 可变参数。
下面的示例激活多个配置文件:

ctx.getEnvironment().setActiveProfiles("profile1", "profile2");

Declaratively, spring.profiles.active may accept a comma-separated list of profile names, as the following example shows:

声明,spring.profiles.active 可以接受以逗号分隔的配置文件名称列表,如下例所示:

    -Dspring.profiles.active="profile1,profile2"
Default Profile

The default profile represents the profile that is enabled by default. Consider the following example:

默认的配置
默认profile文件表示默认启用的profile文件。考虑下面的例子:

@Configuration
@Profile("default")
public class DefaultDataConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .build();
    }
}

If no profile is active, the dataSource is created. You can see this as a way to provide a default definition for one or more beans. If any profile is enabled, the default profile does not apply.

如果没有配置文件是活动的,则创建数据源。
您可以将此看作为一个或多个bean提供默认定义的一种方法。
如果启用了任何配置文件,则不应用默认配置文件。

You can change the name of the default profile by using setDefaultProfiles() on the Environment or ,declaratively, by using the spring.profiles.default property.

您可以通过在环境中使用setDefaultProfiles()或声明性地
使用spring.profile.default属性来更改默认配置文件的名称。

1.13.2. PropertySource Abstraction

Spring’s Environment abstraction provides search operations over a configurable hierarchy of property sources. Consider the following listing:

1.13.2. PropertySource抽象类
Spring的环境抽象类提供了在property资源的可配置层次结构上的搜索操作。
考虑下面的清单:

ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
boolean containsMyProperty = env.containsProperty("my-property");
System.out.println("Does my environment contain the 'my-property' property? " + containsMyProperty);

In the preceding snippet, we see a high-level way of asking Spring whether the my-property property is defined for the current environment. To answer this question, the Environment object performs a search over a set of PropertySource objects. A PropertySource is a simple abstraction over any source of key-value pairs, and Spring’s StandardEnvironment is configured with two PropertySource objects — one representing the set of JVM system properties (System.getProperties()) and one representing the set of system environment variables (System.getenv()).

在前面的代码片段中,我们看到了一种高级方法,可以询问Spring是否
为当前环境定义了my-property属性。
要回答这个问题,环境对象对一组PropertySource对象执行搜索。
PropertySource是对任何键值对源的简单抽象类,
Spring的StandardEnvironment配置了两个PropertySource对象
—一个表示JVM系统属性集(system . getproperties()),
另一个表示系统环境变量集(system .getenv())。

These default property sources are present for StandardEnvironment, for use in standalone applications. StandardServletEnvironment is populated with additional default property sources including servlet config and servlet context parameters. It can optionally enable a JndiPropertySource. See the javadoc for details.
Concretely, when you use the StandardEnvironment, the call to env.containsProperty(“my-property”) returns true if a my-property system property or my-property environment variable is present at runtime.

这些默认property资源是为StandardEnvironment提供的,
用于独立应用程序。
StandardServletEnvironment使用其他默认属性源进行填充,
包括servlet配置和servlet上下文参数。
它可以选择性地启用JndiPropertySource。详细信息请参见javadoc。
具体地说,当您使用StandardEnvironment时,如果运行时存在
一个my-property系统属性或my-property环境变量,
那么对env.containsProperty("my-property")的调用将返回true。

The search performed is hierarchical. By default, system properties have precedence over environment variables. So, if the my-property property happens to be set in both places during a call to env.getProperty(“my-property”), the system property value “wins” and is returned. Note that property values are not merged but rather completely overridden by a preceding entry.

所执行的搜索是分层的。默认情况下,系统属性优先于环境变量。
因此,如果在调用env.getProperty(“my-property”)期间,
恰好在两个位置设置了my-property属性,则系统属性值“胜出”并被返回。
注意,属性值没有被合并,而是被前面的条目完全覆盖。

For a common StandardServletEnvironment, the full hierarchy is as follows, with the highest-precedence entries at the top:

  1. ServletConfig parameters (if applicable — for example, in case of a DispatcherServlet context)

  2. ServletContext parameters (web.xml context-param entries)

  3. JNDI environment variables (java:comp/env/ entries)

  4. JVM system properties (-D command-line arguments)

  5. JVM system environment (operating system environment variables)

对于一般的 StandardServletEnvironment,完整的层次结构如下所示,
最高优先级的条目位于顶部:
1. ServletConfig参数(如果适用
  ——例如,在DispatcherServlet上下文的情况下)
2. ServletContext参数(web.xml上下文参数项)
3.JNDI环境变量(java:comp/env/ entries)
4. JVM系统properties属性(-D命令行参数)
5. JVM系统environment变量(操作系统环境变量)

Most importantly, the entire mechanism is configurable. Perhaps you have a custom source of properties that you want to integrate into this search. To do so, implement and instantiate your own PropertySource and add it to the set of PropertySources for the current Environment. The following example shows how to do so:

最重要的是,整个机制是可配置的。
也许您有一个想要集成到这个搜索中的自定义属性源。
为此,实现并实例化您自己的PropertySource并将其添加到
当前环境的PropertySources集合中。
下面的例子展示了如何做到这一点:

ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new MyPropertySource());`

In the preceding code, MyPropertySource has been added with highest precedence in the search. If it contains a my-property property, the property is detected and returned, in favor of any my-property property in any other PropertySource. The MutablePropertySources API exposes a number of methods that allow for precise manipulation of the set of property sources.

在前面的代码中,在搜索中以最高的优先级添加了MyPropertySource。
如果它包含my-property属性,则检测并返回该属性,从而有利于任何
其他PropertySource中的任何my-property属性。
MutablePropertySources API公开了许多允许精确操作属性源集的方法。

1.13.3. Using @PropertySource

The @PropertySource annotation provides a convenient and declarative mechanism for adding a PropertySource to Spring’s Environment.

1.13.3. 使用 @PropertySource
@PropertySource注释为向Spring的环境添加PropertySource提供了
一种方便的声明性机制。

Given a file called app.properties that contains the key-value pair testbean.name=myTestBean, the following @Configuration class uses @PropertySource in such a way that a call to testBean.getName() returns myTestBean:

给定一个名为app.properties的文件,
其中包含键值对 testbean.name=myTestBean,
下面的@Configuration类使用@PropertySource,
调用testBean.getName()会返回myTestBean:

@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
    @Autowired
    Environment env;

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

Any ${…} placeholders present in a @PropertySource resource location are resolved against the set of property sources already registered against the environment, as the following example shows:

任何出现在@PropertySource资源位置的${…}占位符都会根据
已经在环境中注册的属性源进行解析,如下面的示例所示:

@Configuration
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
public class AppConfig {
    @Autowired
    Environment env;

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

Assuming that my.placeholder is present in one of the property sources already registered (for example, system properties or environment variables), the placeholder is resolved to the corresponding value. If not, then default/path is used as a default. If no default is specified and a property cannot be resolved, an IllegalArgumentException is thrown.

假设 my.placeholder出现在一个已注册的property 资源里面
(例如,系统属性或环境变量)中,占位符将解析为相应的值。
如果不是,则使用default/path作为默认值。
如果没有指定默认值,且无法解析属性,则抛出IllegalArgumentException。

The @PropertySource annotation is repeatable, according to Java 8 conventions. However, all such @PropertySource annotations need to be declared at the same level, either directly on the configuration class or as meta-annotations within the same custom annotation. Mixing direct annotations and meta-annotations is not recommended, since direct annotations effectively override meta-annotations.

根据Java 8的约定,@PropertySource注释是可重复的。
但是,所有这样的@PropertySource注释都需要在同一级别声明,
要么直接在配置类上声明,要么作为同一自定义注释中的元注释声明。
不推荐混合使用直接注释和元注释,因为直接注释有效地覆盖了元注释。

1.13.4. Placeholder Resolution in Statements
1.13.4. 语句中的占位符解析

Historically, the value of placeholders in elements could be resolved only against JVM system properties or environment variables. This is no longer the case. Because the Environment abstraction is integrated throughout the container, it is easy to route resolution of placeholders through it. This means that you may configure the resolution process in any way you like. You can change the precedence of searching through system properties and environment variables or remove them entirely. You can also add your own property sources to the mix, as appropriate.

过去,元素中的占位符的值只能根据JVM系统属性或环境变量解析。
现在情况已经不一样了。
因为环境抽象类集成在整个容器中,所以很容易通过它来解析占位符。
这意味着您可以以任何您喜欢的方式配置解析过程。
您可以更改搜索系统属性和环境变量的优先级,或者完全删除它们。
您还可以在适当的情况下添加您自己的属性源。

Concretely, the following statement works regardless of where the customer property is defined, as long as it is available in the Environment:

具体地说,无论 customer 属性定义在哪里,只要它在环境中可用,以下语句都有效:

<beans>
    <import resource="com/bank/service/${customer}-config.xml"/>
</beans>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值