1.12. Java-based Container Configuration

上一节 1.11. Annotation-based Container Configuration

目录

下一节 1.13. Java-based Container Configuration

1.12. Java-based Container Configuration

1.12. 基于java的容器配置

This section covers how to use annotations in your Java code to configure the Spring container. It includes the following topics:

本节介绍如何在Java代码中使用注释来配置Spring容器。它包括以下主题:

  • Basic Concepts: @Bean and @Configuration
  • Instantiating the Spring Container by Using AnnotationConfigApplicationContext
  • Using the @Bean Annotation
  • Using the @Configuration annotation
  • Composing Java-based Configurations
  • Bean Definition Profiles
  • PropertySource Abstraction
  • Using @PropertySource
  • Placeholder Resolution in Statements
* 基本概念:@Bean和@Configuration
* 使用AnnotationConfigApplicationContext实例化Spring容器
* 使用@Bean注释
* 使用@Configuration注释
* 编写基于java的配置
* Bean Definition配置文件
* PropertySource抽象
* 使用@PropertySource
* 语句中的占位符解析
1.12.1. Basic Concepts: @Bean and @Configuration
1.12.1. 基本概念:@Bean和@Configuration

The central artifacts in Spring’s new Java-configuration support are @Configuration-annotated classes and @Bean-annotated methods.

Spring新的java配置支持中的核心构件是@configuration注释的类和@bean注释的方法。

The @Bean annotation is used to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container. For those familiar with Spring’s XML configuration, the @Bean annotation plays the same role as the element. You can use @Bean-annotated methods with any Spring @Component. However, they are most often used with @Configuration beans.

@Bean注释用于指示方法实例化、配置和初始化由Spring IoC容器管理的新对象。
对于那些熟悉 Spring XML配置<beans/>的开发者,@Bean注释的作用与<bean/>
元素一样。
您可以对任何Spring @Component使用 @Bean-annotated  的方法。
但是,它们最常与@Configuration bean一起使用。

Annotating a class with @Configuration indicates that its primary purpose is as a source of bean definitions. Furthermore, @Configuration classes let inter-bean dependencies be defined by calling other @Bean methods in the same class. The simplest possible @Configuration class reads as follows:

用@Configuration注释类表明它的主要用途是作为bean definitions的资源。
此外,@Configuration类通过调用同一类中的其他@Bean方法来定义bean间的依赖关系。
最简单的@Configuration类如下:

@Configuration
public 
class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

The preceding AppConfig class is equivalent to the following Spring XML:

前面的AppConfig类相当于下面的XML格式的 Spring <beans/> :

<beans>
    <bean id="myService" class="com.acme.services.MyServiceImpl"/></beans>
Full @Configuration vs “lite” @Bean mode?
使用完整的@Configuration 还是 “轻量的”@Bean?

When @Bean methods are declared within classes that are not annotated with @Configuration, they are referred to as being processed in a “lite” mode. Bean methods declared in a @Component or even in a plain old class are considered to be “lite”, with a different primary purpose of the containing class and a @Bean method being a sort of bonus there. For example, service components may expose management views to the container through an additional @Bean method on each applicable component class. In such scenarios, @Bean methods are a general-purpose factory method mechanism.

当@Bean方法在没有使用@Configuration注释的类中声明时,
它们被称为在“lite”模式下处理。
在@Component甚至普通旧类中声明的Bean方法被认为是“lite”的,
因为包含类的主要目的不同,而@Bean方法则是一种额外的好处。
例如,service 组件可以通过每个适用组件类上的附加@Bean方法向容器公开管理视图。
在这种情况下,@Bean方法是一种通用工厂方法机制。

Unlike full @Configuration, lite @Bean methods cannot declare inter-bean dependencies. Instead, they operate on their containing component’s internal state and, optionally, on arguments that they may declare. Such a @Bean method should therefore not invoke other @Bean methods. Each such method is literally only a factory method for a particular bean reference, without any special runtime semantics. The positive side-effect here is that no CGLIB subclassing has to be applied at runtime, so there are no limitations in terms of class design (that is, the containing class may be final and so forth).

与完整的@Configuration不同,lite @Bean方法不能声明bean之间的依赖关系。
相反,它们对包含它们的组件的内部状态进行操作,并可以自己选择对它们可能
声明的参数进行操作。
因此,这样的@Bean方法不应该调用其他的@Bean方法。
每个这样的方法字面上只是一个特定bean引用的工厂方法,没有任何特殊的运行时语义。
这里的积极副作用是,在运行时不需要应用CGLIB子类,因此在类设计方面没有限制(也就是说,包含的类可能是final等等)。

In common scenarios, @Bean methods are to be declared within @Configuration classes, ensuring that “full” mode is always used and that cross-method references therefore get redirected to the container’s lifecycle management. This prevents the same @Bean method from accidentally being invoked through a regular Java call, which helps to reduce subtle bugs that can be hard to track down when operating in “lite” mode.

在常见的场景中,@Bean方法将在@Configuration类中声明,
以确保始终使用“完整”模式,并因此将交叉方法引用重定向到容器的生命周期管理。
这可以防止通过常规Java调用意外地调用相同的@Bean方法,
这有助于减少在“轻量”模式下操作时难以跟踪的细微错误。

The @Bean and @Configuration annotations are discussed in depth in the following sections. First, however, we cover the various ways of creating a spring container using by Java-based configuration.

下面几节将深入讨论@Bean和@Configuration注释。
但是,首先,我们将介绍使用基于java的配置创建spring容器的各种方法。

1.12.2. Instantiating the Spring Container by Using AnnotationConfigApplicationContext

The following sections document Spring’s AnnotationConfigApplicationContext, introduced in Spring 3.0. This versatile ApplicationContext implementation is capable of accepting not only @Configuration classes as input but also plain @Component classes and classes annotated with JSR-330 metadata.

下面的小节记录了Spring 3.0中引入的AnnotationConfigApplicationContext。
这个通用的ApplicationContext实现不仅能够接受@Configuration类作为输入,
还能够接受普通的@Component类和用JSR-330元数据注释的类。

versatile 
英 /ˈvɜːsətaɪl/  美 /ˈvɜːrsətl/  全球(英国)  
adj. 多才多艺的;通用的,万能的;多面手的

When @Configuration classes are provided as input, the @Configuration class itself is registered as a bean definition and all declared @Bean methods within the class are also registered as bean definitions.

当提供@Configuration类作为输入时,@Configuration类本身被注册
为bean definition,类中声明的所有@Bean方法也被注册为bean定义。

When @Component and JSR-330 classes are provided, they are registered as bean definitions, and it is assumed that DI metadata such as @Autowired or @Inject are used within those classes where necessary.

当提供了@Component和JSR-330类时,它们被注册为bean definitions,
并且假设在需要时在这些类中使用依赖注入的元数据(如@Autowired或@Inject)。

Simple Construction

In much the same way that Spring XML files are used as input when instantiating a ClassPathXmlApplicationContext, you can use @Configuration classes as input when instantiating an AnnotationConfigApplicationContext. This allows for completely XML-free usage of the Spring container, as the following example shows:

与实例化ClassPathXmlApplicationContext时使用Spring XML文件作为
输入的方式非常相似,在实例化AnnotationConfigApplicationContext时
可以使用@Configuration类作为输入。
这允许使用完全无XML的Spring容器,如下面的示例所示:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

As mentioned earlier, AnnotationConfigApplicationContext is not limited to working only with @Configuration classes. Any @Component or JSR-330 annotated class may be supplied as input to the constructor, as the following example shows:

正如前面提到的,AnnotationConfigApplicationContext并不仅限于
处理@Configuration类。
任何@Component或JSR-330注释类都可以作为输入提供给构造函数,
如下面的示例所示:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

The preceding example assumes that MyServiceImpl, Dependency1, and Dependency2 use Spring dependency injection annotations such as @Autowired.

前面的示例假设MyServiceImpl、Dependency1和Dependency2
使用Spring依赖注入注释,如@Autowired。

Building the Container Programmatically by Using register(Class<?>…)

You can instantiate an AnnotationConfigApplicationContext by using a no-arg constructor and then configure it by using the register() method. This approach is particularly useful when programmatically building an AnnotationConfigApplicationContext. The following example shows how to do so:

通过使用 register(Class<?>…) 编程构建容器
您可以使用无参数构造函数实例化一个AnnotationConfigApplicationContext,
然后使用register()方法对其进行配置。
当以编程方式构建AnnotationConfigApplicationContext时,这种方法特别有用。
下面的例子展示了如何做到这一点:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register(AppConfig.class, OtherConfig.class);
    ctx.register(AdditionalConfig.class);
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}
Enabling Component Scanning with scan(String…)

To enable component scanning, you can annotate your @Configuration class as follows:

使用scan(String…) 启用组件扫描 
要启用组件扫描,您可以注释您的@Configuration类如下:

@Configuration
@ComponentScan(basePackages = "com.acme")  @1
public class AppConfig  {
    ...
}
@1This annotation enables component scanning.

> Experienced Spring users may be familiar with the XML declaration equivalent from Spring’s context: namespace, shown in the following example:

有经验的Spring用户可能熟悉Spring上下文名称空间中的等价XML声明,
如下面的例子所示:

```xml
<beans>
    <context:component-scan base-package="com.acme"/></beans>

In the preceding example, the com.acme package is scanned to look for any @Component-annotated classes, and those classes are registered as Spring bean definitions within the container. AnnotationConfigApplicationContext exposes the scan(String…) method to allow for the same component-scanning functionality, as the following example shows:

在前面的示例中,com.acme 包以查找任何@component注释的类,
并且这些类被注册为容器中的Spring bean definitions。
AnnotationConfigApplicationContext提供scan(String…)方法来
允许相同的组件扫描功能,如下面的示例所示:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}

Remember that @Configuration classes are meta-annotated with @Component, so they are candidates for component-scanning. In the preceding example, assuming that AppConfig is declared within the com.acme package (or any package underneath), it is picked up during the call to scan(). Upon refresh(), all its @Bean methods are processed and registered as bean definitions within the container.

请记住,@Configuration类是用@Component进行元注释的,
因此它们是组件扫描的候选对象。
在前面的示例中,假设AppConfig在com.acme包(或下面的任何包)
中声明,它在调用scan()期间被获取。
在refresh()时,它的所有@Bean方法都被处理并在容器中注册
为bean definitions。

Support for Web Applications with AnnotationConfigWebApplicationContext
支持带有AnnotationConfigWebApplicationContext注释的Web应用程序

A WebApplicationContext variant of AnnotationConfigApplicationContext is available with AnnotationConfigWebApplicationContext. You can use this implementation when configuring the Spring ContextLoaderListener servlet listener, Spring MVC DispatcherServlet, and so forth. The following web.xml snippet configures a typical Spring MVC web application (note the use of the contextClass context-param and init-param):

AnnotationConfigApplicationContext的WebApplicationContext变体
可以通过AnnotationConfigWebApplicationContext获得。
您可以在配置Spring ContextLoaderListener servlet监听器、
Spring MVC DispatcherServlet等时使用此实现。
下面的web.xml代码片段配置了一个典型的Spring MVC web应用程序
(注意contextClass上下文参数和init参数的使用):

<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>

    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 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
            </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>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/* </url-pattern>
    </servlet-mapping></web-app>

1.12.3. Using the @Bean Annotation

1.12.3. 使用 @Bean 注释

@Bean is a method-level annotation and a direct analog of the XML element. The annotation supports some of the attributes offered by , such as: * init-method * destroy-method * autowiring * name.

@Bean是一个方法级注释,直接类似于XML <bean/>元素。
该注释支持 <bean/> 提供的一些属性,
例如:* init-method * destroy-method * autowiring * name。

You can use the @Bean annotation in a @Configuration-annotated or in a @Component-annotated class.

您可以在注释了@ configuration或注释了@ component的类中
使用@Bean注释。

Declaring a Bean

To declare a bean, you can annotate a method with the @Bean annotation. You use this method to register a bean definition within an ApplicationContext of the type specified as the method’s return value. By default, the bean name is the same as the method name. The following example shows a @Bean method declaration:

声明一个bean
要声明一个bean,您可以使用@Bean注释一个方法。
您可以使用此方法在一个ApplicationContext中注册一个指定为方法返回值的
类型的bean definition。默认情况下,bean名称与方法名称相同。
下面的例子显示了@Bean方法声明:

@Configuration
public class AppConfig {
    @Bean
    public TransferServiceImpl transferService() {
        return new TransferServiceImpl();
    }
}

The preceding configuration is exactly equivalent to the following Spring XML:

上面的配置与下面的Spring XML完全相同:

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

Both declarations make a bean named transferService available in the ApplicationContext, bound to an object instance of type TransferServiceImpl, as the following text image shows:

这两个声明使得一个名为transferService的bean在ApplicationContext中可用,
绑定到一个类型为TransferServiceImpl的对象实例,如下面的文本所示:

transferService -> com.acme.TransferServiceImpl

You can also declare your @Bean method with an interface (or base class) return type, as the following example shows:

你也可以用接口(或者基类)返回类型来声明你的@Bean方法,如下面的例子所示

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }
}

However, this limits the visibility for advance type prediction to the specified interface type (TransferService). Then, with the full type (TransferServiceImpl) known to the container only once, the affected singleton bean has been instantiated. Non-lazy singleton beans get instantiated according to their declaration order, so you may see different type matching results depending on when another component tries to match by a non-declared type (such as @Autowired TransferServiceImpl, which resolves only once the transferService bean has been instantiated).

但是,这将预先类型预测的可见性限制为指定的接口类型(TransferService)。
然后,容器只知道完整类型(TransferServiceImpl)一次,受影响的 
singleton bean就被实例化了。
非惰性 singleton bean根据它们的声明顺序被实例化,因此您可能会看到
不同的类型匹配结果,这取决于其他组件何时尝试通过一个未声明的类型进行匹配
(例如@Autowired TransferServiceImpl,它只在transferService bean
被实例化后才解析)。

If you consistently refer to your types by a declared service interface, your @Bean return types may safely join that design decision. However, for components that implement several interfaces or for components potentially referred to by their implementation type, it is safer to declare the most specific return type possible (at least as specific as required by the injection points that refer to your bean).

如果您始终通过声明的服务接口引用您的类型,那么您的@Bean返回类型
可以安全地加入设计决策。
但是,对于实现多个接口的组件,或者对于可能由其实现类型引用的组件,
声明可能最特定的返回类型(至少与引用bean的注入点所要求的特定程度相同)
更为安全。

Bean Dependencies

A @Bean-annotated method can have an arbitrary number of parameters that describe the dependencies required to build that bean. For instance, if our TransferService requires an AccountRepository, we can materialize that dependency with a method parameter, as the following example shows:

Bean的依赖
带@ bean注释的方法可以有任意数量的参数,用于描述构建该bean所需的依赖关系。
例如,如果我们的TransferService需要一个AccountRepository,
我们可以用一个方法参数来具体化这个依赖关系,如下面的例子所示:

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

The resolution mechanism is pretty much identical to constructor-based dependency injection. See the relevant section for more details.

解析机制与基于构造方法的依赖项注入非常相似。更多细节请参阅相关部分。

Receiving Lifecycle Callbacks

Any classes defined with the @Bean annotation support the regular lifecycle callbacks and can use the @PostConstruct and @PreDestroy annotations from JSR-250. See JSR-250 annotations for further details.

接受生命周期回调
任何用@Bean注释定义的类都支持常规的生命周期回调,并且可以使用JSR-250中的@PostConstruct和@PreDestroy注释。
更多细节请参见JSR-250注释。

The regular Spring lifecycle callbacks are fully supported as well. If a bean implements InitializingBean, DisposableBean, or Lifecycle, their respective methods are called by the container.

常规的Spring生命周期回调也得到了完全支持。如果一个bean实现了InitializingBean、DisposableBean或Lifecycle,容器将调用它们各自的方法。

The standard set of *Aware interfaces (such as BeanFactoryAware, BeanNameAware, MessageSourceAware, ApplicationContextAware, and so on) are also fully supported.

 * Aware 接口的标准集也完全支持(例如BeanFactoryAware、BeanNameAware、MessageSourceAware、applicationcontext taware等)。

The @Bean annotation supports specifying arbitrary initialization and destruction callback methods, much like Spring XML’s init-method and destroy-method attributes on the bean element, as the following example shows:

@Bean注释支持指定任意的初始化和销毁回调方法,很像Spring XML在bean元素上的init-method和destroy-method属性,
如下面的例子所示:

public class BeanOne {
    public void init() {
        // initialization logic
    }
}

public class BeanTwo {
    public void cleanup() {
        // destruction logic
    }
}

@Configuration
public class AppConfig {
    @Bean(initMethod = "init")
    public BeanOne beanOne() {
        return new BeanOne();
    }

    @Bean(destroyMethod = "cleanup")
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

By default, beans defined with Java configuration that have a public close or shutdown method are automatically enlisted with a destruction callback. If you have a public close or shutdown method and you do not wish for it to be called when the container shuts down, you can add @Bean(destroyMethod="") to your bean definition to disable the default (inferred) mode.

默认情况下,使用Java配置定义的具有公共关闭或关闭方法的bean将与
销毁回调一起被自动征用。
如果您有一个公共close或shutdown方法,并且您不希望在容器关闭时
调用它,那么您可以在bean定义中添加@Bean(destroyMethod="")
来禁用默认(推断)模式。

You may want to do that by default for a resource that you acquire with JNDI, as its lifecycle is managed outside the application. In particular, make sure to always do it for a DataSource, as it is known to be problematic on Java EE application servers.

默认情况下,您可能希望对使用JNDI获取的资源执行此操作,因为它的生命周期
是在应用程序之外管理的。
特别是,确保总是对数据源执行此操作,因为在Java EE应用程序服务器上这是有问题的。

The following example shows how to prevent an automatic destruction callback for a DataSource:

下面的例子展示了如何防止数据源的自动销毁回调:

@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
    return (DataSource) jndiTemplate.lookup("MyDS");
}

Also, with @Bean methods, you typically use programmatic JNDI lookups, either by using Spring’s JndiTemplate or JndiLocatorDelegate helpers or straight JNDI InitialContext usage but not the JndiObjectFactoryBean variant (which would force you to declare the return type as the FactoryBean type instead of the actual target type, making it harder to use for cross-reference calls in other @Bean methods that intend to refer to the provided resource here).

同样,通过@bean方法,您通常使用编码方式的JNDI查找,通过使用Spring的
JndiTemplate 或者 JndiLocatorDelegate helper 或直接使用
JNDI InitialContext但不是JndiObjectFactoryBean变体
(这将迫使你声明返回类型作为FactoryBean类型,而不是实际的目标类型,
因此很难使用交叉引用调用@bean方法,打算在其他参考所提供的资源)。

In the case of BeanOne from the example above the preceding note, it would be equally valid to call the init() method directly during construction, as the following example shows:

对于上面例子中的BeanOne,在构造过程中直接调用init()方法同样有效,
如下面的例子所示:

@Configuration
public class AppConfig {
    @Bean
    public BeanOne beanOne() {
        BeanOne beanOne = new BeanOne();
        beanOne.init();
        return beanOne;
    }

    // ...
}

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.

当您直接在Java中工作时,您可以对对象做任何您喜欢的事情,
而不总是需要依赖容器的生命周期。

Specifying Bean Scope
指定Bean作用域

Spring includes the @Scope annotation so that you can specify the scope of a bean.

Spring包含@Scope注释,以便您可以指定bean的作用域。

Using the @Scope Annotation
使用 @Scope注释

You can specify that your beans defined with the @Bean annotation should have a specific scope. You can use any of the standard scopes specified in the Bean Scopes section.

您可以指定用@Bean注释定义的bean应该具有特定的作用域。您可以使用Bean作用域部分中指定的任何标准作用域。

The default scope is singleton, but you can override this with the @Scope annotation, as the following example shows:

默认的作用域是singleton,但是你可以用@Scope注释覆盖它,如下面的例子所示:

@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    public Encryptor encryptor() {
        // ...
    }
}
@Scope and scoped-proxy

Spring offers a convenient way of working with scoped dependencies through scoped proxies. The easiest way to create such a proxy when using the XML configuration is the aop:scoped-proxy/ element. Configuring your beans in Java with a @Scope annotation offers equivalent support with the proxyMode attribute. The default is no proxy (ScopedProxyMode.NO), but you can specify ScopedProxyMode.TARGET_CLASS or ScopedProxyMode.INTERFACES.

@Scope 和 作用域代理
Spring提供了一种通过作用域代理处理作用域依赖关系的方便方法。
在使用XML配置时,创建这样一个代理的最简单方法是 <aop:scoped-proxy/>元素。
用@Scope注释配置Java中的bean可以提供与proxyMode属性同等的支持。
默认是没有代理(ScopedProxyMode.no),但是您可以指定
ScopedProxyMode.TARGET_CLASS或ScopedProxyMode.INTERFACES。

If you port the scoped proxy example from the XML reference documentation (see scoped proxies) to our @Bean using Java, it resembles the following:

如果您使用Java将范围代理示例从XML参考文档(参见作用域代理)移植到我们的@Bean,
它类似于以下情况:

// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
    return new UserPreferences();
}

@Bean
public Service userService() {
    UserService service = new SimpleUserService();
    // a reference to the proxied userPreferences bean
    service.setUserPreferences(userPreferences());
    return service;
}
Customizing Bean Naming

By default, configuration classes use a @Bean method’s name as the name of the resulting bean. This functionality can be overridden, however, with the name attribute, as the following example shows:

个性化bean名称
默认情况下,配置类使用@Bean方法的名称作为生成的bean的名称。
但是,可以使用name属性覆盖此功能,如下面的示例所示:

@Configuration
public class AppConfig {
    @Bean(name = "myThing")
    public Thing thing() {
        return new Thing();
    }
}
Bean Aliasing

As discussed in Naming Beans, 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. The following example shows how to set a number of aliases for a bean:

Bean别称
正如在 Naming Beans 章节中所讨论的,有时希望给单个bean起多个名称,
也称为bean别称。
为此,@Bean注释的name属性接受一个字符串数组。
下面的例子展示了如何为一个bean设置多个别名:

@Configuration
public class AppConfig {
    @Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
    public DataSource dataSource() {
        // instantiate, configure and return DataSource bean...
    }
}
Bean Description

Sometimes, it is helpful to provide a more detailed textual description of a bean. This can be particularly useful when beans are exposed (perhaps through JMX) for monitoring purposes.

Bean描述
有时,为bean提供更详细的文本描述是有帮助的。
当以监控为目的而公开bean(可能通过JMX)时,这尤其有用。

To add a description to a @Bean, you can use the @Description annotation, as the following example shows:

要向@Bean添加描述,可以使用@Description注释,如下面的示例所示:

@Configurationpublic class AppConfig {
    @Bean
    @Description("Provides a basic example of a bean")
    public Thing thing() {
        return new Thing();
    }
}
1.12.4. Using the @Configuration annotation
1.12.4. 使用 @Configuration 注解

@Configuration is a class-level annotation indicating that an object is a source of bean definitions. @Configuration classes declare beans through public @Bean annotated methods. Calls to @Bean methods on @Configuration classes can also be used to define inter-bean dependencies. See Basic Concepts: @Bean and @Configuration for a general introduction.

@Configuration是一个类级注释,指示对象是bean definitions 的资源。
@Configuration类通过公共的@Bean注释方法声明bean。
在@Configuration类上调用@Bean方法也可以用来定义bean之间的依赖关系。
请参阅 Basic Concepts: @Bean and @Configuration 章节获得进一步的介绍。

Injecting Inter-bean Dependencies
注入Inter-bean依赖性

When beans have dependencies on one another, expressing that dependency is as simple as having one bean method call another, as the following example shows:

当bean相互依赖时,表达这种依赖就像让一个bean方法调用另一个bean方法一样简单,
如下面的例子所示:

@Configuration
public class AppConfig {
    @Bean
    public BeanOne beanOne() {
        return new BeanOne(beanTwo());
    }

    @Bean
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

In the preceding example, beanOne receives a reference to beanTwo through constructor injection.

在前面的示例中,beanOne通过构造函数注入接收到对beanTwo的引用。

This method of declaring inter-bean dependencies works only when the @Bean method is declared within a @Configuration class. You cannot declare inter-bean dependencies by using plain @Component classes.

这种声明bean间依赖关系的方法仅在@Bean方法在@Configuration类中声明时有效。
不能通过使用纯@Component类来声明bean之间的依赖关系。

Lookup Method Injection

As noted earlier, lookup method injection is an advanced feature that you should use rarely. It is useful in cases where a singleton-scoped bean has a dependency on a prototype-scoped bean. Using Java for this type of configuration provides a natural means for implementing this pattern. The following example shows how to use lookup method injection:

查找方法注入
如前所述,查找方法注入是一种高级特性,应该很少使用。
当 singleton 作用域bean依赖于原型作用域bean时,它非常有用。
将Java用于这种类型的配置提供了一种实现这种模式的自然方法。
下面的例子展示了如何使用查找方法注入:

public abstract class CommandManager {
    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}

By using Java configuration, you can create a subclass of CommandManager where the abstract createCommand() method is overridden in such a way that it looks up a new (prototype) command object. The following example shows how to do so:

通过使用Java配置,您可以创建CommandManager的一个子类,
其中抽象createCommand()方法被重写,
其方式是查找新的(prototype) command对象。
下面的例子展示了如何做到这一点:

@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
    AsyncCommand command = new AsyncCommand();
    // inject dependencies here as required
    return command;
}

@Bean
public CommandManager commandManager() {
    // return new anonymous implementation of CommandManager with createCommand()
    // overridden to return a new prototype Command object
    return new CommandManager() {
        protected Command createCommand() {
            return asyncCommand();
        }
    }
}

Further Information About How Java-based Configuration Works InternallyConsider the following example, which shows a @Bean annotated method being called twice:

关于基于java的配置如何在内部工作的进一步信息,请考虑下面的例子,
它显示了被调用两次的@Bean注释方法:

@Configuration
public class AppConfig {
    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }
}

clientDao() has been called once in clientService1() and once in clientService2(). Since this method creates a new instance of ClientDaoImpl and returns it, you would normally expect to have two instances (one for each service). That definitely would be problematic: In Spring, instantiated beans have a singleton scope by default. This is where the magic comes in: All @Configuration classes are subclassed at startup-time with CGLIB. In the subclass, the child method checks the container first for any cached (scoped) beans before it calls the parent method and creates a new instance.

在clientService1()和clientService2()中分别调用了一次clientDao()。
由于此方法创建了ClientDaoImpl的一个新实例并返回它,因此通常需要
两个实例(每个服务一个)。
这肯定是有问题的:在Spring中,实例化的bean在默认情况下有一个 
singleton作用域。
这就是神奇之处:所有@Configuration类在启动时都由CGLIB生成子类。
在子类中,子方法在调用父方法并创建一个新实例之前,首先检查容器
是否有缓存的(作用域的)bean。

The behavior could be different according to the scope of your bean. We are talking about singletons here.

根据bean 作用域,行为可能不同。我们在这里讨论的是singletons。

As of Spring 3.2, it is no longer necessary to add CGLIB to your classpath because CGLIB classes have been repackaged under org.springframework.cglib and included directly within the spring-core JAR.

从Spring 3.2开始,不再需要将CGLIB添加到类路径中,因为CGLIB类已经
在org.springframework下重新打包并直接包含在spring-core JAR中。

There are a few restrictions due to the fact that CGLIB dynamically adds features at startup-time. In particular, configuration classes must not be final. However, as of 4.3, any constructors are allowed on configuration classes, including the use of @Autowired or a single non-default constructor declaration for default injection.
If you prefer to avoid any CGLIB-imposed limitations, consider declaring your @Bean methods on non-@Configuration classes (for example, on plain @Component classes instead). Cross-method calls between @Bean methods are not then intercepted, so you have to exclusively rely on dependency injection at the constructor or method level there.

由于CGLIB在启动时动态添加特性,所以有一些限制。
特别的是,configuration类不能是final。
然而,在4.3中,配置类允许使用任何构造函数,包括使用@Autowired或
为默认注入使用单一的非默认构造函数声明。
如果您希望避免任何cglib强加的限制,可以考虑在非@configuration类上
声明@Bean方法(例如,在纯@Component类上声明)。
这样,@Bean方法之间的交叉方法调用就不会被拦截,因此您只能在
构造函数或方法级别上独家依赖于依赖注入。

1.12.5. Composing Java-based Configurations
1.12.5. 编写基于java的配置

Spring’s Java-based configuration feature lets you compose annotations, which can reduce the complexity of your configuration.

Spring的基于java的配置特性允许编写注释,这可以降低配置的复杂性。

Using the @Import Annotation

Much as the element is used within Spring XML files to aid in modularizing configurations, the @Import annotation allows for loading @Bean definitions from another configuration class, as the following example shows:

使用 @Import 标签
就像<import/>元素在Spring XML文件中用于帮助模块化配置,
@Import注释允许从另一个配置类加载@Bean定义,
如下面的示例所示:

@Configuration
public class ConfigA {
    @Bean
    public A a() {
        return new A();
    }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {
    @Bean
    public 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, as the following example shows:

现在,在实例化上下文时,不需要同时指定configA.class和configB.class,
只需要显式地提供ConfigB,如下面的示例所示:

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 you to remember a potentially large number of @Configuration classes during construction.

这种方法简化了容器实例化,因为只需要处理一个类,
而不需要在构造期间记住可能存在的大量@Configuration类。

As of Spring Framework 4.2, @Import also supports references to regular component classes, analogous to the AnnotationConfigApplicationContext.register method. This is particularly useful if you want to avoid component scanning, by using a few configuration classes as entry points to explicitly define all your components.

在Spring Framework 4.2中,@Import还支持对常规组件类的引用,类似于AnnotationConfigApplicationContext.register 方法。
如果您想要避免组件扫描,通过使用几个配置类作为入口点显式地定义所有组件,
这一点特别有用。

Injecting Dependencies on Imported @Bean Definitions
注入导入的@Bean定义的依赖项

The preceding example works but is simplistic. In most practical scenarios, beans have dependencies on one another across configuration classes. When using XML, this is not an issue, because no compiler is involved, and you can declare ref=“someBean” and trust Spring to work it out during container initialization. When using @Configuration classes, the Java compiler places constraints on the configuration model, in that references to other beans must be valid Java syntax.

前面的示例可以工作,但过于简单。
在大多数实际场景中,bean跨configuration类相互依赖。
在使用XML时,这不是问题,因为不涉及任何编译器,您可以声明ref="someBean",
并相信Spring会在容器初始化期间解决这个问题。
在使用@Configuration类时,Java编译器会对配置模型施加约束,因为对其他bean的
引用必须是有效的Java语法。

Fortunately, solving this problem is simple. As we already discussed, a @Bean method can have an arbitrary number of parameters that describe the bean dependencies. Consider the following more real-world scenario with several @Configuration classes, each depending on beans declared in the others:

幸运的是,解决这个问题很简单。
正如我们已经讨论过的,@Bean方法可以有任意数量的描述bean依赖关系的参数。
考虑以下更真实的场景,有几个@Configuration类,每个类都依赖于其他类中声明的bean:

@Configuration
public class ServiceConfig {
    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {
    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

There is another way to achieve the same result. Remember that @Configuration classes are ultimately only another bean in the container: This means that they can take advantage of @Autowired and @Value injection and other features the same as any other bean.

还有另一种方法可以达到同样的效果。
请记住,@Configuration类最终只是容器中的另一个bean:
这意味着它们可以利用与任何其他bean相同的@Autowired和
@Value注入以及其他特性。

Make sure that the dependencies you inject that way are of the simplest kind only. @Configuration classes are processed quite early during the initialization of the context, and forcing a dependency to be injected this way may lead to unexpected early initialization. Whenever possible, resort to parameter-based injection, as in the preceding example.

确保以这种方式注入的依赖项只属于最简单的类型。
@Configuration类在上下文初始化过程中很早就被处理,
强制以这种方式注入依赖项可能会导致意外的早期初始化。
尽可能使用基于参数的注入,如前面的示例所示。

Also, be particularly careful with BeanPostProcessor and BeanFactoryPostProcessor definitions through @Bean. Those should usually be declared as static @Bean methods, not triggering the instantiation of their containing configuration class. Otherwise, @Autowired and @Value may not work on the configuration class itself, since it is possible to create it as a bean instance earlier than AutowiredAnnotationBeanPostProcessor.

另外,对于通过@Bean定义的BeanPostProcessor和
BeanFactoryPostProcessor要特别小心。
这些方法通常应该声明为静态的@Bean方法,而不是触发其包含的配置类的实例化。
否则,@Autowired和@Value可能不能在配置类本身上工作,因为它可以
在AutowiredAnnotationBeanPostProcessor之前创建一个bean实例。

The following example shows how one bean can be autowired to another bean:

下面的例子展示了一个bean如何自动连接到另一个bean:

@Configuration
public class ServiceConfig {
    @Autowired
    private AccountRepository accountRepository;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {
    private final DataSource dataSource;

    public RepositoryConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

Constructor injection in @Configuration classes is only supported as of Spring Framework 4.3. Note also that there is no need to specify @Autowired if the target bean defines only one constructor.

在Spring Framework 4.3中只支持@Configuration类中的构造方法注入。
还要注意,如果目标bean只定义了一个构造函数,就没有必要指定@Autowired。

Fully-qualifying imported beans for ease of navigation

In the preceding scenario, 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 is not explicit in the code, and this may be just fine. Remember that the Spring Tools for Eclipse provides tooling that can render graphs showing how everything is wired, which may be all you need. Also, your Java IDE can easily find all declarations and uses of the AccountRepository type and quickly show you the location of @Bean methods that return that type.

完全限定导入的bean以方便导航
在前面的场景中,使用@Autowired工作得很好,并且提供了所需的模块化,
但是确定autowired bean定义在哪里声明仍然有点不明确。
例如,作为一个正在查看ServiceConfig的开发人员,您如何知道@Autowired AccountRepository bean在哪里声明?
它在代码中没有明确表示,这可能很好。
请记住,用于Eclipse的Spring工具提供了一些工具,可以呈现显示如何连接
所有内容的图形,这可能是您所需要的全部内容。
而且,Java IDE可以很容易地找到AccountRepository类型的所有声明和使用,
并快速显示返回该类型的@Bean方法的位置。

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. The following example shows how to do so:

如果这种模糊性是不可接受的,并且您希望在IDE中从一个@Configuration
类直接导航到另一个,请考虑自动装配configuration类本身。
下面的例子展示了如何做到这一点:

@Configuration
public class ServiceConfig {
    @Autowired
    private RepositoryConfig repositoryConfig;

    @Bean
    public TransferService transferService() {
        // navigate 'through' the config class to the @Bean method!
        return new TransferServiceImpl(repositoryConfig.accountRepository());
    }
}

In the preceding situation, where AccountRepository is defined is completely explicit. However, ServiceConfig is now tightly coupled to RepositoryConfig. That is the tradeoff. This tight coupling can be somewhat mitigated by using interface-based or abstract class-based @Configuration classes. Consider the following example:

在上述情况下,定义AccountRepository是完全明确的。
但是,ServiceConfig现在与RepositoryConfig紧密耦合。
这就是权衡。通过使用基于接口或基于抽象类的@Configuration类,
可以在一定程度上减轻这种紧密耦合。
考虑下面的例子:

@Configuration
public class ServiceConfig {
    @Autowired
    private RepositoryConfig repositoryConfig;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(repositoryConfig.accountRepository());
    }
}

@Configuration
public interface RepositoryConfig {
    @Bean
    AccountRepository accountRepository();
}

@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(...);
    }
}

@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class})  // import the concrete config!
public class SystemTestConfig {
    @Bean
    public DataSource dataSource() {
        // return DataSource
    }

}

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: You can easily 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.

现在,ServiceConfig与具体的DefaultRepositoryConfig松散耦合,
并且内置的IDE工具仍然有用:
您可以轻松获得RepositoryConfig实现的类型层次结构。
这样,导航@Configuration类及其依赖项与导航基于接口的代码的通常过程没有什么不同。

If you want to influence the startup creation order of certain beans, consider declaring some of them as @Lazy (for creation on first access instead of on startup) or as @DependsOn certain other beans (making sure that specific other beans are created before the current bean, beyond what the latter’s direct dependencies imply).

如果你想影响某些bean的启动创建订单,考虑将其中一些声明为@Lazy
(用于创建在第一次访问,而不是在启动时)或@DependsOn某些其他bean
(确保特定的其他bean创建当前bean之前,超出后者的直接依赖关系暗示)。

Conditionally Include @Configuration Classes or @Bean Methods

It is often useful to conditionally enable or disable a complete @Configuration class or even individual @Bean methods, based on some arbitrary system state. One common example of this is to use the @Profile annotation to activate beans only when a specific profile has been enabled in the Spring Environment (see Bean Definition Profiles for details).

有条件地包括@Configuration类或@Bean方法
根据任意的系统状态,有条件地启用或禁用一个完整的@Configuration类,
甚至是单个的@Bean方法,这通常很有用。
一个常见的例子是只有在Spring环境中启用了特定的概要文件时才使用
@Profile注释来激活Bean
(参见 Bean Definition Profiles 章节了解详细信息)。


The @Profile annotation is actually implemented by using a much more flexible annotation called @Conditional. The @Conditional annotation indicates specific org.springframework.context.annotation.Condition implementations that should be consulted before a @Bean is registered.

@Profile注释实际上是通过使用一个更灵活的注释@Conditional实现的。
@Conditional注释表示特定的org.springframework.context.annotation.Condition
实现在注册@Bean之前被调用。

Implementations of the Condition interface provide a matches(…) method that returns true or false. For example, the following listing shows the actual Condition implementation used for @Profile:

Condition接口的实现提供了一个matches(…)方法,该方法返回true或false。
例如,下面的清单显示了用于@Profile的实际条件实现:

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    // Read the @Profile annotation attributes
    MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
    if (attrs != null) {
        for (Object value : attrs.get("value")) {
            if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
                return true;
            }
        }
        return false;
    }
    return true;
}

See the @Conditional javadoc for more detail.

参考 @Conditional的 javadoc 获得更多信息

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 by using, for example, ClassPathXmlApplicationContext, or instantiate it in a “Java-centric” way by using AnnotationConfigApplicationContext and the @ImportResource annotation to import XML as needed.

结合Java和XML配置
Spring的@Configuration类支持并不是要100%完全替代Spring XML。
有些工具,如Spring XML名称空间,仍然是配置容器的理想方式。
在XML方便或必要的情况下,你有一个选择:要么在容器实例化在一个
“以XML为中心”的方式使用,例如,ClassPathXmlApplicationContext
或实例化它“以java为中心”的方式通过使用所和@ImportResource注释导入XML。

XML-centric Use of @Configuration 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 is easier to create @Configuration classes on an as-needed basis and include them from the existing XML files. Later in this section, we cover the options for using @Configuration classes in this kind of “XML-centric” situation.

使用以xml为中心的@Configuration类
最好是从XML引导Spring容器并以特别的方式包含@Configuration类。
例如,在使用Spring XML的大型现有代码库中,更容易根据需要创建
@Configuration类并从现有XML文件中包含它们。
在本节的后面,我们将介绍在这种“以xml为中心”的情况下使用
@Configuration类的选项。

Declaring @Configuration classes as plain Spring elements

Remember that @Configuration classes are ultimately bean definitions in the container. In this series examples, we create a @Configuration class named AppConfig and include it within system-test-config.xml as a definition. Because context:annotation-config/ is switched on, the container recognizes the @Configuration annotation and processes the @Bean methods declared in AppConfig properly.

声明@Configuration类为普通<bean/> 元素
请记住,@Configuration类最终是容器中的bean definitions。
在本系列示例中,我们创建了一个名为AppConfig的@Configuration类,
并将其作为bean包含在system-test-config.xml中。
因为<context:annotation-config/>设置为on,容器识别
@Configuration注释并正确处理在AppConfig中声明的@Bean方法。

The following example shows an ordinary configuration class in Java:

下面的例子展示了一个普通的Java配置类:

@Configuration
public class AppConfig {
    @Autowired
    private DataSource dataSource;

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataSource);
    }

    @Bean
    public TransferService transferService() {
        return new TransferService(accountRepository());
    }
}

The following example shows part of a sample system-test-config.xml file:

下面的示例显示了system-test-config.xml文件的一部分:

<beans>
    <!-- enable processing of annotations such as @Autowired and @Configuration -->
    <context:annotation-config/>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>

    <bean class="com.acme.AppConfig"/>

    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

The following example shows a possible jdbc.properties file:

下面的示例展示了一个可能的 jdbc.properties文件:

jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
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);
    // ...
}

In system-test-config.xml file, the AppConfig does not declare an id element. While it would be acceptable to do so, it is unnecessary, given that no other bean ever refers to it, and it is unlikely to be explicitly fetched from the container by name. Similarly, the DataSource bean is only ever autowired by type, so an explicit bean id is not strictly required.

在system-test.config.xml文件中,AppConfig <bean/>没有声明id元素。
虽然这样做是可以接受的,但是没有必要这样做,因为没有其他bean引用过它,
而且不太可能通过名称显式地从容器中获取它。
类似地,数据源bean只根据类型自动生成,因此显式bean id并不是严格要求的。

Using context:component-scan/ to pick up @Configuration classes

Because @Configuration is meta-annotated with @Component, @Configuration-annotated classes are automatically candidates for component scanning. Using the same scenario as describe in the previous example, we can redefine system-test-config.xml to take advantage of component-scanning. Note that, in this case, we need not explicitly declare context:annotation-config/, because context:component-scan/ enables the same functionality.

使用<context:component-scan/> ;获取@Configuration类
因为@Configuration是用@Component元注释的,
所以带有@Configuration注释的类是组件扫描的自动候选者。
使用前面示例中描述的相同场景,我们可以重新定义system-test-config.xml,
以利用组件扫描的优势。
注意,在这种情况下,我们不需要显式地声明<context:annotation-config/>,
因为<context:component-scan/>启用相同的功能。

The following example shows the modified system-test-config.xml file:

下面的例子显示了修改后的system-test .xml文件:

<beans>
    <!-- picks up and registers AppConfig as a bean definition -->
    <context:component-scan base-package="com.acme"/>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>

    <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
</beans>

@Configuration Class-centric Use of XML with @ImportResource

In applications where @Configuration classes are the primary mechanism for configuring the container, it is still likely necessary to use at least some XML. In these scenarios, you can use @ImportResource and define only as much XML as you need. Doing so achieves a “Java-centric” approach to configuring the container and keeps XML to a bare minimum. The following example (which includes a configuration class, an XML file that defines a bean, a properties file, and the main class) shows how to use the @ImportResource annotation to achieve “Java-centric” configuration that uses XML as needed:

使用@ImportResource以@Configuration类为中心使用XML
在以@Configuration类作为配置容器的主要机制的应用程序中,
仍然可能需要使用至少一些XML。
在这些场景中,您可以使用@ImportResource并只定义所需的XML。
这样做可以实现一种“以java为中心”的方法来配置容器,
并将XML保持在最低限度。
下面的例子(包括configuration类、定义bean的XML文件、properties文件和主类)
展示了如何使用@ImportResource注释来实现“以java为中心”的配置,
根据需要使用XML:

@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, username, password);
    }
}

properties-config.xml

<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>
jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    TransferService transferService = ctx.getBean(TransferService.class);
    // ...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值