Spring参考文档翻译11--IOC容器09

1.9. Annotation-based Container Configuration

基于注解的容器配置

Are annotations better than XML for configuring Spring?

在配置 Spring 时,注解是否比 XML 更好?

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML. The short answer is “it depends.” The long answer is that each approach has its pros and cons, and, usually, it is up to the developer to decide which strategy suits them better. Due to the way they are defined, annotations provide a lot of context in their declaration, leading to shorter and more concise configuration. However, XML excels at wiring up components without touching their source code or recompiling them. Some developers prefer having the wiring close to the source while others argue that annotated classes are no longer POJOs and, furthermore, that the configuration becomes decentralized and harder to control.

基于注释的配置的引入提出了这种方法是否比 XML“更好”的问题。简短的回答是“视情况而定”。长答案是每种方法都有其优点和缺点,通常由开发人员决定哪种策略更适合他们。由于它们的定义方式,注释在其声明中提供了大量上下文,从而使配置更短、更简洁。然而,XML 擅长在不触及源代码或重新编译它们的情况下连接组件。一些开发人员更喜欢在源附近进行布线,而另一些开发人员则认为带注释的类不再是 POJO,此外,配置变得分散且更难控制。

No matter the choice, Spring can accommodate both styles and even mix them together. It is worth pointing out that through its JavaConfig option, Spring lets annotations be used in a non-invasive way, without touching the target components source code and that, in terms of tooling, all configuration styles are supported by the Spring Tools for Eclipse.

无论选择如何,Spring 都可以同时适应这两种风格,甚至可以将它们混合在一起。值得指出的是,通过其JavaConfig选项,Spring 允许以非侵入性的方式使用注释,而无需触及目标组件的源代码,并且在工具方面, Spring Tools for Eclipse支持所有配置样式。

An alternative to XML setup is provided by annotation-based configuration, which relies on the bytecode metadata for wiring up components instead of angle-bracket declarations. Instead of using XML to describe a bean wiring, the developer moves the configuration into the component class itself by using annotations on the relevant class, method, or field declaration. As mentioned in Example: The AutowiredAnnotationBeanPostProcessor, using a BeanPostProcessor in conjunction with annotations is a common means of extending the Spring IoC container. For example, Spring 2.0 introduced the possibility of enforcing required properties with the @Required annotation. Spring 2.5 made it possible to follow that same general approach to drive Spring’s dependency injection. Essentially, the @Autowired annotation provides the same capabilities as described in Autowiring Collaborators but with more fine-grained control and wider applicability. Spring 2.5 also added support for JSR-250 annotations, such as @PostConstruct and @PreDestroy. Spring 3.0 added support for JSR-330 (Dependency Injection for Java) annotations contained in the javax.inject package such as @Inject and @Named. Details about those annotations can be found in the relevant section.

基于注释的配置提供了 XML 设置的替代方案,它依赖于字节码元数据来连接组件,而不是尖括号声明。开发人员不使用 XML 来描述 bean 连接,而是通过在相关类、方法或字段声明上使用注释将配置移动到组件类本身。如示例中所述:AutowiredAnnotationBeanPostProcessor ,BeanPostProcessor与注释一起使用是扩展 Spring IoC 容器的常用方法。例如,Spring 2.0 引入了使用@Required注解强制执行所需属性的可能性。Spring 2.5 使得遵循相同的通用方法来驱动 Spring 的依赖注入成为可能。本质上,@Autowiredannotation 提供了与Autowiring Collaborators中描述的相同的功能,但具有更细粒度的控制和更广泛的适用性。Spring 2.5 还增加了对 JSR-250 注释的支持,例如 @PostConstruct@PreDestroy. Spring 3.0 增加了对包中包含的 JSR-330(Java 依赖注入)注解的支持,javax.inject例如@Inject@Named. 有关这些注释的详细信息,请参见 相关部分

Annotation injection is performed before XML injection. Thus, the XML configuration overrides the annotations for properties wired through both approaches.
注解注入在 XML 注入之前执行。因此,XML 配置覆盖了通过这两种方法连接的属性的注释。

As always, you can register the post-processors as individual bean definitions, but they can also be implicitly registered by including the following tag in an XML-based Spring configuration (notice the inclusion of the context namespace):

与往常一样,您可以将后处理器注册为单独的 bean 定义,但也可以通过在基于 XML 的 Spring 配置中包含以下标记来隐式注册它们(注意包含context命名空间):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
</beans>

The <context:annotation-config/> element implicitly registers the following post-processors:

<context:annotation-config/>元素隐式注册以下后处理器:

<context:annotation-config/> only looks for annotations on beans in the same application context in which it is defined. This means that, if you put <context:annotation-config/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Autowired beans in your controllers, and not your services. See The DispatcherServlet for more information.
<context:annotation-config/>仅在定义它的同一应用程序上下文中查找 bean 上的注释。这意味着,如果您 <context:annotation-config/>输入 a WebApplicationContextfor a DispatcherServlet,它只会检查@Autowired您的控制器中的 bean,而不是您的服务。有关详细信息,请参阅 DispatcherServlet

1.9.1. @Required

The @Required annotation applies to bean property setter methods, as in the following example:

注释适用于 bean 属性设置方法,@Required如下例所示:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Required
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}

This annotation indicates that the affected bean property must be populated at configuration time, through an explicit property value in a bean definition or through autowiring. The container throws an exception if the affected bean property has not been populated. This allows for eager and explicit failure, avoiding NullPointerException instances or the like later on. We still recommend that you put assertions into the bean class itself (for example, into an init method). Doing so enforces those required references and values even when you use the class outside of a container.

此注解指示必须在配置时通过 bean 定义中的显式属性值或通过自动装配来填充受影响的 bean 属性。如果受影响的 bean 属性尚未填充,则容器将引发异常。这允许急切和明确NullPointerException 的失败,避免以后出现实例等。我们仍然建议您将断言放入 bean 类本身(例如放入 init 方法)。即使您在容器外部使用类,这样做也会强制执行这些必需的引用和值。

The RequiredAnnotationBeanPostProcessor must be registered as a bean to enable support for the @Required annotation.
必须将其RequiredAnnotationBeanPostProcessor 注册为 bean 以启用对@Required注解的支持。
The @Required annotation and RequiredAnnotationBeanPostProcessor are formally deprecated as of Spring Framework 5.1, in favor of using constructor injection for required settings (or a custom implementation of InitializingBean.afterPropertiesSet() or a custom @PostConstruct method along with bean property setter methods).
从Spring Framework 5.1 开始,@Required注解和RequiredAnnotationBeanPostProcessor正式弃用,支持使用构造函数注入进行所需设置(或自定义实现InitializingBean.afterPropertiesSet() 或自定义@PostConstruct方法以及 bean 属性设置方法)。

1.9.2. Using @Autowired

使用@Autowired

JSR 330’s @Inject annotation can be used in place of Spring’s @Autowired annotation in the examples included in this section. See here for more details.
在本节包含的示例中,@Inject可以使用JSR 330 的注解代替 Spring 的注解。@Autowired有关更多详细信息,请参见此处

You can apply the @Autowired annotation to constructors, as the following example shows:

您可以将@Autowired注释应用于构造函数,如以下示例所示:

public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
As of Spring Framework 4.3, an @Autowired annotation on such a constructor is no longer necessary if the target bean defines only one constructor to begin with. However, if several constructors are available and there is no primary/default constructor, at least one of the constructors must be annotated with @Autowired in order to instruct the container which one to use. See the discussion on constructor resolution for details.
从 Spring Framework 4.3 开始,@Autowired如果目标 bean 仅定义一个构造函数开始,则不再需要对此类构造函数进行注释。但是,如果有多个构造函数可用并且没有主/默认构造函数,则必须至少对其中一个构造函数进行注释,@Autowired以指示容器使用哪一个。有关详细信息,请参阅构造函数解析的讨论 。

You can also apply the @Autowired annotation to traditional setter methods, as the following example shows:

您还可以将@Autowired注解应用于传统的setter 方法,如以下示例所示:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}

You can also apply the annotation to methods with arbitrary names and multiple arguments, as the following example shows:

您还可以将注释应用于具有任意名称和多个参数的方法,如以下示例所示:

public class MovieRecommender {
    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}

You can apply @Autowired to fields as well and even mix it with constructors, as the following example shows:

您也可以应用于@Autowired字段,甚至可以将其与构造函数混合使用,如以下示例所示:

public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    private MovieCatalog movieCatalog;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
Make sure that your target components (for example, MovieCatalog or CustomerPreferenceDao) are consistently declared by the type that you use for your @Autowired-annotated injection points. Otherwise, injection may fail due to a "no type match found" error at runtime.For XML-defined beans or component classes found via classpath scanning, the container usually knows the concrete type up front. However, for @Bean factory methods, you need to make sure that the declared return type is sufficiently expressive. For components that implement several interfaces or for components potentially referred to by their implementation type, consider declaring the most specific return type on your factory method (at least as specific as required by the injection points referring to your bean).
确保您的目标组件(例如,MovieCatalogCustomerPreferenceDao)始终由您用于带@Autowired注释的注入点的类型声明。否则,注入可能会由于运行时出现“找不到类型匹配”错误而失败。 对于通过类路径扫描找到的 XML 定义的 bean 或组件类,容器通常预先知道具体类型。但是,对于@Bean工厂方法,您需要确保声明的返回类型具有足够的表现力。对于实现多个接口的组件或可能由其实现类型引用的组件,请考虑在您的工厂方法中声明最具体的返回类型(至少与引用您的 bean 的注入点所要求的一样具体)。

You can also instruct Spring to provide all beans of a particular type from the ApplicationContext by adding the @Autowired annotation to a field or method that expects an array of that type, as the following example shows:

ApplicationContext您还可以通过将@Autowired注释添加到需要该类型数组的字段或方法来指示 Spring 提供特定类型的所有 bean ,如以下示例所示:

public class MovieRecommender {
    @Autowired
    private MovieCatalog[] movieCatalogs;
    // ...
}

The same applies for typed collections, as the following example shows:

这同样适用于类型化集合,如以下示例所示:

public class MovieRecommender {
    private Set<MovieCatalog> movieCatalogs;
    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
    // ...
}
Your target beans can implement the org.springframework.core.Ordered interface or use the @Order or standard @Priority annotation if you want items in the array or list to be sorted in a specific order. Otherwise, their order follows the registration order of the corresponding target bean definitions in the container.You can declare the @Order annotation at the target class level and on @Bean methods, potentially for individual bean definitions (in case of multiple definitions that use the same bean class). @Order values may influence priorities at injection points, but be aware that they do not influence singleton startup order, which is an orthogonal concern determined by dependency relationships and @DependsOn declarations.Note that the standard javax.annotation.Priority annotation is not available at the @Bean level, since it cannot be declared on methods. Its semantics can be modeled through @Order values in combination with @Primary on a single bean for each type.
如果您希望数组或列表中的项目按特定顺序排序,您的目标 bean 可以实现org.springframework.core.Ordered接口或使用@Order标准注释。@Priority否则,它们的顺序遵循容器中相应目标 bean 定义的注册顺序。您可以@Order在目标类级别和@Bean方法上声明注释,可能针对单个 bean 定义(在使用相同 bean 类的多个定义的情况下)。@Order值可能会影响注入点的优先级,但请注意它们不会影响单例启动顺序,这是由依赖关系和@DependsOn声明确定的正交问题。请注意,标准javax.annotation.Priority注释在该 @Bean级别不可用,因为它不能在方法上声明。它的语义可以通过@Order结合@Primary每个类型的单个 bean 的值来建模。

Even typed Map instances can be autowired as long as the expected key type is String. The map values contain all beans of the expected type, and the keys contain the corresponding bean names, as the following example shows:

Map只要预期的键类型是 ,即使是类型化的实例也可以自动装配String。映射值包含预期类型的所有 bean,键包含相应的 bean 名称,如以下示例所示:

public class MovieRecommender {
    private Map<String, MovieCatalog> movieCatalogs;
    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }
    // ...
}

By default, autowiring fails when no matching candidate beans are available for a given injection point. In the case of a declared array, collection, or map, at least one matching element is expected.

默认情况下,当给定注入点没有匹配的候选 bean 时,自动装配会失败。在声明的数组、集合或映射的情况下,至少需要一个匹配元素。

The default behavior is to treat annotated methods and fields as indicating required dependencies. You can change this behavior as demonstrated in the following example, enabling the framework to skip a non-satisfiable injection point through marking it as non-required (i.e., by setting the required attribute in @Autowired to false):

默认行为是将带注释的方法和字段视为指示所需的依赖项。您可以按照以下示例所示更改此行为,使框架能够通过将其标记为非必需(即,通过将required属性设置@Autowiredfalse)来跳过不可满足的注入点:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Autowired(required = false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}

A non-required method will not be called at all if its dependency (or one of its dependencies, in case of multiple arguments) is not available. A non-required field will not get populated at all in such cases, leaving its default value in place.

如果非必需方法的依赖项(或其依赖项之一,如果有多个参数)不可用,则根本不会调用非必需方法。在这种情况下,根本不会填充非必填字段,而保留其默认值。

Injected constructor and factory method arguments are a special case since the required attribute in @Autowired has a somewhat different meaning due to Spring’s constructor resolution algorithm that may potentially deal with multiple constructors. Constructor and factory method arguments are effectively required by default but with a few special rules in a single-constructor scenario, such as multi-element injection points (arrays, collections, maps) resolving to empty instances if no matching beans are available. This allows for a common implementation pattern where all dependencies can be declared in a unique multi-argument constructor — for example, declared as a single public constructor without an @Autowired annotation.

注入的构造函数和工厂方法参数是一种特殊情况,因为Spring 的构造函数解析算法可能会处理多个构造函数,因此required in 属性的含义有些不同。@Autowired默认情况下,构造函数和工厂方法参数是有效的,但在单构造函数场景中有一些特殊规则,例如如果没有匹配的 bean 可用,多元素注入点(数组、集合、映射)解析为空实例。这允许一种通用的实现模式,其中所有依赖项都可以在唯一的多参数构造函数中声明——例如,声明为没有@Autowired注释的单个公共构造函数。

Only one constructor of any given bean class may declare @Autowired with the required attribute set to true, indicating the constructor to autowire when used as a Spring bean. As a consequence, if the required attribute is left at its default value true, only a single constructor may be annotated with @Autowired. If multiple constructors declare the annotation, they will all have to declare required=false in order to be considered as candidates for autowiring (analogous to autowire=constructor in XML). The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen. If none of the candidates can be satisfied, then a primary/default constructor (if present) will be used. Similarly, if a class declares multiple constructors but none of them is annotated with @Autowired, then a primary/default constructor (if present) will be used. If a class only declares a single constructor to begin with, it will always be used, even if not annotated. Note that an annotated constructor does not have to be public.The required attribute of @Autowired is recommended over the deprecated @Required annotation on setter methods. Setting the required attribute to false indicates that the property is not required for autowiring purposes, and the property is ignored if it cannot be autowired. @Required, on the other hand, is stronger in that it enforces the property to be set by any means supported by the container, and if no value is defined, a corresponding exception is raised.
任何给定 bean 类@Autowired构造函数只能声明其required 属性设置为true,指示构造函数在用作 Spring bean 时自动装配。因此,如果属性保留为默认值,则只有一个构造函数可以用 注释。如果多个构造函数声明了注解,它们都必须声明才能被视为自动装配的候选者(类似于required``true``@Autowired``required=false``autowire=constructor在 XML 中)。将选择在 Spring 容器中通过匹配 bean 可以满足的依赖项数量最多的构造函数。如果不能满足任何候选者,则将使用主/默认构造函数(如果存在)。类似地,如果一个类声明了多个构造函数但没有一个用 注释@Autowired,那么将使用主/默认构造函数(如果存在)。如果一个类只声明了一个构造函数,即使没有注释,它也会一直被使用。请注意,带注释的构造函数不必是公共的。 任何给定 bean 类@Autowired构造函数只能声明其required 属性设置为true,指示构造函数在用作 Spring bean 时自动装配。因此,如果属性保留为默认值,则只有一个构造函数可以用 注释。如果多个构造函数声明了注解,它们都必须声明才能被视为自动装配的候选者(类似于required``true``@Autowired``required=false``autowire=constructor在 XML 中)。将选择在 Spring 容器中通过匹配 bean 可以满足的依赖项数量最多的构造函数。如果不能满足任何候选者,则将使用主/默认构造函数(如果存在)。类似地,如果一个类声明了多个构造函数但没有一个用 注释@Autowired,那么将使用主/默认构造函数(如果存在)。如果一个类只声明了一个构造函数,即使没有注释,它也会一直被使用。请注意,带注释的构造函数不必是公共的。建议使用required属性 of@Autowired而不是 setter 方法上已弃用的@Required 注释。将required属性设置为false表示自动装配不需要该属性,如果不能自动装配,则忽略该属性。@Required另一方面,它更强大,因为它强制通过容器支持的任何方式设置属性,如果没有定义值,则会引发相应的异常。

Alternatively, you can express the non-required nature of a particular dependency through Java 8’s java.util.Optional, as the following example shows:

或者,您可以通过 Java 8 表达特定依赖项的非必需性质java.util.Optional,如以下示例所示:

public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
        ...
    }
}

As of Spring Framework 5.0, you can also use a @Nullable annotation (of any kind in any package — for example, javax.annotation.Nullable from JSR-305) or just leverage Kotlin builtin null-safety support:

从 Spring Framework 5.0 开始,您还可以使用@Nullable注释(任何包中的任何类型 - 例如,javax.annotation.Nullable来自 JSR-305)或仅利用 Kotlin 内置的空安全支持:

public class SimpleMovieLister {
    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}

You can also use @Autowired for interfaces that are well-known resolvable dependencies: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher, and MessageSource. These interfaces and their extended interfaces, such as ConfigurableApplicationContext or ResourcePatternResolver, are automatically resolved, with no special setup necessary. The following example autowires an ApplicationContext object:

您还可以@Autowired用于众所周知的可解析依赖项的接口:BeanFactoryApplicationContextEnvironmentResourceLoaderApplicationEventPublisherMessageSource. 这些接口及其扩展接口,例如ConfigurableApplicationContextor ResourcePatternResolver,会自动解析,无需特殊设置。以下示例自动装配一个ApplicationContext对象:

public class MovieRecommender {
    @Autowired
    private ApplicationContext context;
    public MovieRecommender() {
    }
    // ...
}
The @Autowired, @Inject, @Value, and @Resource annotations are handled by Spring BeanPostProcessor implementations. This means that you cannot apply these annotations within your own BeanPostProcessor or BeanFactoryPostProcessor types (if any). These types must be 'wired up' explicitly by using XML or a Spring @Bean method.
@Autowired、@Inject、@Value和@Resource注释由Spring BeanPostProcessor实现处理。这意味着您不能在自己的BeanPostProcessor或BeanFactoryPostProcessor类型(如果有)中应用这些注释。这些类型必须通过使用XML或Spring@Bean方法显式地“连接”。

1.9.3. Fine-tuning Annotation-based Autowiring with @Primary

微调基于注释的自动装配@Primary

Because autowiring by type may lead to multiple candidates, it is often necessary to have more control over the selection process. One way to accomplish this is with Spring’s @Primary annotation. @Primary indicates that a particular bean should be given preference when multiple beans are candidates to be autowired to a single-valued dependency. If exactly one primary bean exists among the candidates, it becomes the autowired value.

由于按类型自动装配可能会导致多个候选者,因此通常需要对选择过程进行更多控制。实现这一点的一种方法是使用 Spring 的 @Primary注释。@Primary指示当多个 bean 是自动装配到单值依赖项的候选对象时,应该优先考虑特定的 bean。如果候选中恰好存在一个主 bean,则它将成为自动装配的值。

Consider the following configuration that defines firstMovieCatalog as the primary MovieCatalog:

考虑以下定义firstMovieCatalog为主要的配置MovieCatalog

@Configuration
public class MovieConfiguration {
    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }
    @Bean
    public MovieCatalog secondMovieCatalog() { ... }
    // ...
}

With the preceding configuration, the following MovieRecommender is autowired with the firstMovieCatalog:

使用上述配置,以下MovieRecommender内容与 自动装配 firstMovieCatalog

public class MovieRecommender {
    @Autowired
    private MovieCatalog movieCatalog;
    // ...
}

The corresponding bean definitions follow:

对应的bean定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean class="example.SimpleMovieCatalog" primary="true">
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>

1.9.4. Fine-tuning Annotation-based Autowiring with Qualifiers

使用限定符微调基于注释的自动装配

@Primary is an effective way to use autowiring by type with several instances when one primary candidate can be determined. When you need more control over the selection process, you can use Spring’s @Qualifier annotation. You can associate qualifier values with specific arguments, narrowing the set of type matches so that a specific bean is chosen for each argument. In the simplest case, this can be a plain descriptive value, as shown in the following example:

@Primary当可以确定一个主要候选者时,是一种通过类型使用多个实例的自动装配的有效方法。当您需要对选择过程进行更多控制时,可以使用 Spring 的@Qualifier注解。您可以将限定符值与特定参数相关联,缩小类型匹配的范围,以便为每个参数选择特定的 bean。在最简单的情况下,这可以是一个简单的描述性值,如以下示例所示:

public class MovieRecommender {
    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;
    // ...
}

You can also specify the @Qualifier annotation on individual constructor arguments or method parameters, as shown in the following example:

您还可以@Qualifier在单个构造函数参数或方法参数上指定注释,如下例所示:

public class MovieRecommender {
    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}

The following example shows corresponding bean definitions.

以下示例显示了相应的 bean 定义。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean class="example.SimpleMovieCatalog">
        <qualifier value="main"/> 
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <qualifier value="action"/> 
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
The bean with the main qualifier value is wired with the constructor argument that is qualified with the same value.
具有限定符值的 bean 与main具有相同值限定的构造函数参数连接。
The bean with the action qualifier value is wired with the constructor argument that is qualified with the same value.
具有限定符值的 bean 与action具有相同值限定的构造函数参数连接。

For a fallback match, the bean name is considered a default qualifier value. Thus, you can define the bean with an id of main instead of the nested qualifier element, leading to the same matching result. However, although you can use this convention to refer to specific beans by name, @Autowired is fundamentally about type-driven injection with optional semantic qualifiers. This means that qualifier values, even with the bean name fallback, always have narrowing semantics within the set of type matches. They do not semantically express a reference to a unique bean id. Good qualifier values are main or EMEA or persistent, expressing characteristics of a specific component that are independent from the bean id, which may be auto-generated in case of an anonymous bean definition such as the one in the preceding example.

对于回退匹配,bean 名称被视为默认限定符值。id因此,您可以使用ofmain代替嵌套的限定符元素来定义 bean ,从而获得相同的匹配结果。但是,尽管您可以使用此约定按名称引用特定 bean,但从@Autowired根本上讲,它是关于带有可选语义限定符的类型驱动注入。这意味着限定符值,即使使用 bean 名称回退,也总是在类型匹配集中具有缩小的语义。它们不会在语义上表达对唯一 bean 的引用id。好的限定符值是main or EMEAor persistent,表示独立于 bean 的特定组件的特征id,在匿名 bean 定义(例如前面示例中的那个)的情况下,它可能会自动生成。

Qualifiers also apply to typed collections, as discussed earlier — for example, to Set<MovieCatalog>. In this case, all matching beans, according to the declared qualifiers, are injected as a collection. This implies that qualifiers do not have to be unique. Rather, they constitute filtering criteria. For example, you can define multiple MovieCatalog beans with the same qualifier value “action”, all of which are injected into a Set<MovieCatalog> annotated with @Qualifier("action").

如前所述,限定符也适用于类型化集合——例如,to Set<MovieCatalog>. 在这种情况下,根据声明的限定符,所有匹配的 bean 都作为集合注入。这意味着限定符不必是唯一的。相反,它们构成过滤标准。例如,您可以定义多个MovieCatalog具有相同限定符值“action”的 bean,所有这些 bean 都被注入到Set<MovieCatalog>带有@Qualifier("action").

Letting qualifier values select against target bean names, within the type-matching candidates, does not require a @Qualifier annotation at the injection point. If there is no other resolution indicator (such as a qualifier or a primary marker), for a non-unique dependency situation, Spring matches the injection point name (that is, the field name or parameter name) against the target bean names and chooses the same-named candidate, if any.
在类型匹配的候选对象中,让限定符值针对目标 bean 名称进行选择,不需要@Qualifier在注入点进行注释。如果没有其他解析指示符(例如限定符或主标记),对于非唯一依赖情况,Spring 将注入点名称(即字段名称或参数名称)与目标 bean 名称匹配并选择同名候选人(如有)。

That said, if you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if it is capable of selecting by bean name among type-matching candidates. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process. @Autowired has rather different semantics: After selecting candidate beans by type, the specified String qualifier value is considered within those type-selected candidates only (for example, matching an account qualifier against beans marked with the same qualifier label).

也就是说,如果您打算按名称表达注解驱动的注入,请不要主要使用@Autowired,即使它能够在类型匹配候选者中按 bean 名称进行选择。相反,使用 JSR-250@Resource注释,它在语义上定义为通过其唯一名称标识特定目标组件,声明的类型与匹配过程无关。@Autowired具有相当不同的语义:在按类型选择候选 bean 后,指定的String 限定符值仅在那些类型选择的候选者中考虑(例如,将account限定符与标记有相同限定符标签的 bean 匹配)。

For beans that are themselves defined as a collection, Map, or array type, @Resource is a fine solution, referring to the specific collection or array bean by unique name. That said, as of 4.3, you can match collection, Map, and array types through Spring’s @Autowired type matching algorithm as well, as long as the element type information is preserved in @Bean return type signatures or collection inheritance hierarchies. In this case, you can use qualifier values to select among same-typed collections, as outlined in the previous paragraph.

对于本身定义为集合Map或数组类型的 bean,这@Resource 是一个很好的解决方案,通过唯一名称引用特定的集合或数组 bean。也就是说,从 4.3 开始,您也可以Map通过 Spring 的类型匹配算法匹配集合、、和数组类型 @Autowired,只要元素类型信息保留在@Bean返回类型签名或集合继承层次结构中即可。在这种情况下,您可以使用限定符值在相同类型的集合中进行选择,如上一段所述。

As of 4.3, @Autowired also considers self references for injection (that is, references back to the bean that is currently injected). Note that self injection is a fallback. Regular dependencies on other components always have precedence. In that sense, self references do not participate in regular candidate selection and are therefore in particular never primary. On the contrary, they always end up as lowest precedence. In practice, you should use self references as a last resort only (for example, for calling other methods on the same instance through the bean’s transactional proxy). Consider factoring out the affected methods to a separate delegate bean in such a scenario. Alternatively, you can use @Resource, which may obtain a proxy back to the current bean by its unique name.

从 4.3 开始,@Autowired还考虑了注入的自引用(即,对当前注入的 bean 的引用)。请注意,自注入是一种后备。对其他组件的常规依赖始终具有优先权。从这个意义上说,自我参考不参与常规的候选人选择,因此尤其不是主要的。相反,它们总是以最低优先级结束。在实践中,您应该仅将自引用用作最后的手段(例如,通过 bean 的事务代理在同一实例上调用其他方法)。在这种情况下,考虑将受影响的方法分解为单独的委托 bean。或者,您可以使用@Resource,它可以通过其唯一名称获取返回到当前 bean 的代理。

Trying to inject the results from @Bean methods on the same configuration class is effectively a self-reference scenario as well. Either lazily resolve such references in the method signature where it is actually needed (as opposed to an autowired field in the configuration class) or declare the affected @Bean methods as static, decoupling them from the containing configuration class instance and its lifecycle. Otherwise, such beans are only considered in the fallback phase, with matching beans on other configuration classes selected as primary candidates instead (if available).
尝试从@Bean同一配置类上的方法注入结果实际上也是一种自引用场景。要么在实际需要的方法签名中延迟解析此类引用(与配置类中的自动装配字段相反),要么将受影响的@Bean方法声明为static,将它们与包含的配置类实例及其生命周期解耦。否则,仅在回退阶段考虑此类 bean,而将其他配置类上的匹配 bean 选为主要候选者(如果可用)。

@Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. In contrast, @Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, you should stick with qualifiers if your injection target is a constructor or a multi-argument method.

@Autowired适用于字段、构造函数和多参数方法,允许在参数级别通过限定符注释缩小范围。相反,@Resource 仅支持具有单个参数的字段和 bean 属性设置器方法。因此,如果您的注入目标是构造函数或多参数方法,您应该坚持使用限定符。

You can create your own custom qualifier annotations. To do so, define an annotation and provide the @Qualifier annotation within your definition, as the following example shows:

您可以创建自己的自定义限定符注释。为此,请定义注释并@Qualifier在定义中提供注释,如以下示例所示:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
    String value();
}

Then you can provide the custom qualifier on autowired fields and parameters, as the following example shows:

然后,您可以在自动装配的字段和参数上提供自定义限定符,如以下示例所示:

public class MovieRecommender {
    @Autowired
    @Genre("Action")
    private MovieCatalog actionCatalog;
    private MovieCatalog comedyCatalog;
    @Autowired
    public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
        this.comedyCatalog = comedyCatalog;
    }
    // ...
}

Next, you can provide the information for the candidate bean definitions. You can add <qualifier/> tags as sub-elements of the <bean/> tag and then specify the type and value to match your custom qualifier annotations. The type is matched against the fully-qualified class name of the annotation. Alternately, as a convenience if no risk of conflicting names exists, you can use the short class name. The following example demonstrates both approaches:

接下来,您可以提供候选 bean 定义的信息。您可以添加 <qualifier/>标签作为标签的子元素,<bean/>然后指定typeand value以匹配您的自定义限定符注释。该类型与注解的完全限定类名匹配。或者,如果不存在名称冲突的风险,为方便起见,您可以使用短类名。以下示例演示了这两种方法:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean class="example.SimpleMovieCatalog">
        <qualifier type="Genre" value="Action"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <qualifier type="example.Genre" value="Comedy"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>

In Classpath Scanning and Managed Components, you can see an annotation-based alternative to providing the qualifier metadata in XML. Specifically, see Providing Qualifier Metadata with Annotations.

Classpath Scanning and Managed Components中,您可以看到基于注释的替代方法,以在 XML 中提供限定符元数据。具体来说,请参阅提供带有注释的限定符元数据

In some cases, using an annotation without a value may suffice. This can be useful when the annotation serves a more generic purpose and can be applied across several different types of dependencies. For example, you may provide an offline catalog that can be searched when no Internet connection is available. First, define the simple annotation, as the following example shows:

在某些情况下,使用没有值的注释可能就足够了。当注释服务于更通用的目的并且可以应用于多种不同类型的依赖项时,这可能很有用。例如,您可以提供一个离线目录,当没有可用的 Internet 连接时可以搜索该目录。首先,定义简单的注解,如下例所示:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Offline {
}

Then add the annotation to the field or property to be autowired, as shown in the following example:

然后将注解添加到要自动装配的字段或属性中,如下例所示:

public class MovieRecommender {
    @Autowired
    @Offline 
    private MovieCatalog offlineCatalog;
    // ...
}
This line adds the @Offline annotation.
此行添加@Offline注释。

Now the bean definition only needs a qualifier type, as shown in the following example:

现在 bean 定义只需要一个 qualifier type,如下例所示:

<bean class="example.SimpleMovieCatalog">
    <qualifier type="Offline"/> 
    <!-- inject any dependencies required by this bean -->
</bean>
This element specifies the qualifier.
此元素指定限定符。

You can also define custom qualifier annotations that accept named attributes in addition to or instead of the simple value attribute. If multiple attribute values are then specified on a field or parameter to be autowired, a bean definition must match all such attribute values to be considered an autowire candidate. As an example, consider the following annotation definition:

除了或代替简单value属性,您还可以定义接受命名属性的自定义限定符注释。如果随后在要自动装配的字段或参数上指定多个属性值,则 bean 定义必须匹配所有此类属性值才能被视为自动装配候选者。例如,考虑以下注释定义:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {
    String genre();
    Format format();
}

In this case Format is an enum, defined as follows:

在这种情况下Format是一个枚举,定义如下:

public enum Format {
    VHS, DVD, BLURAY
}

The fields to be autowired are annotated with the custom qualifier and include values for both attributes: genre and format, as the following example shows:

要自动装配的字段使用自定义限定符进行注释,并包括两个属性的值:genreformat,如以下示例所示:

public class MovieRecommender {
    @Autowired
    @MovieQualifier(format=Format.VHS, genre="Action")
    private MovieCatalog actionVhsCatalog;
    @Autowired
    @MovieQualifier(format=Format.VHS, genre="Comedy")
    private MovieCatalog comedyVhsCatalog;
    @Autowired
    @MovieQualifier(format=Format.DVD, genre="Action")
    private MovieCatalog actionDvdCatalog;
    @Autowired
    @MovieQualifier(format=Format.BLURAY, genre="Comedy")
    private MovieCatalog comedyBluRayCatalog;
    // ...
}

Finally, the bean definitions should contain matching qualifier values. This example also demonstrates that you can use bean meta attributes instead of the <qualifier/> elements. If available, the <qualifier/> element and its attributes take precedence, but the autowiring mechanism falls back on the values provided within the <meta/> tags if no such qualifier is present, as in the last two bean definitions in the following example:

最后,bean 定义应该包含匹配的限定符值。此示例还演示了您可以使用 bean 元属性而不是 <qualifier/>元素。如果可用,则<qualifier/>元素及其属性优先,但 <meta/>如果不存在此类限定符,则自动装配机制将依赖标签中提供的值,如以下示例中的最后两个 bean 定义:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean class="example.SimpleMovieCatalog">
        <qualifier type="MovieQualifier">
            <attribute key="format" value="VHS"/>
            <attribute key="genre" value="Action"/>
        </qualifier>
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <qualifier type="MovieQualifier">
            <attribute key="format" value="VHS"/>
            <attribute key="genre" value="Comedy"/>
        </qualifier>
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <meta key="format" value="DVD"/>
        <meta key="genre" value="Action"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
    <bean class="example.SimpleMovieCatalog">
        <meta key="format" value="BLURAY"/>
        <meta key="genre" value="Comedy"/>
        <!-- inject any dependencies required by this bean -->
    </bean>
</beans>

1.9.5. Using Generics as Autowiring Qualifiers

使用泛型作为自动装配限定符

In addition to the @Qualifier annotation, you can use Java generic types as an implicit form of qualification. For example, suppose you have the following configuration:

除了@Qualifier注释之外,您还可以使用 Java 泛型类型作为限定的隐式形式。例如,假设您有以下配置:

@Configuration
public class MyConfiguration {
    @Bean
    public StringStore stringStore() {
        return new StringStore();
    }
    @Bean
    public IntegerStore integerStore() {
        return new IntegerStore();
    }
}

Assuming that the preceding beans implement a generic interface, (that is, Store<String> and Store<Integer>), you can @Autowire the Store interface and the generic is used as a qualifier, as the following example shows:

假设前面的 bean 实现了一个泛型接口,(即Store<String>Store<Integer>),您可以@AutowireStore接口和泛型用作限定符,如以下示例所示:

@Autowired
private Store<String> s1; // <String> qualifier, injects the stringStore bean
@Autowired
private Store<Integer> s2; // <Integer> qualifier, injects the integerStore bean

Generic qualifiers also apply when autowiring lists, Map instances and arrays. The following example autowires a generic List:

通用限定符也适用于自动装配列表、Map实例和数组。以下示例自动装配一个泛型List

// Inject all Store beans as long as they have an <Integer> generic
// Store<String> beans will not appear in this list
@Autowired
private List<Store<Integer>> s;

1.9.6. Using CustomAutowireConfigurer

使用CustomAutowireConfigurer

CustomAutowireConfigurer is a BeanFactoryPostProcessor that lets you register your own custom qualifier annotation types, even if they are not annotated with Spring’s @Qualifier annotation. The following example shows how to use CustomAutowireConfigurer:

CustomAutowireConfigurer 是一个BeanFactoryPostProcessor允许您注册自己的自定义限定符注解类型,即使它们没有使用 Spring 的注解进行@Qualifier注解。下面的例子展示了如何使用CustomAutowireConfigurer

<bean id="customAutowireConfigurer"
        class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>example.CustomQualifier</value>
        </set>
    </property>
</bean>

The AutowireCandidateResolver determines autowire candidates by:

通过以下AutowireCandidateResolver方式确定自动接线候选者:

  • The autowire-candidate value of each bean definition

    autowire-candidate每个bean定义的值

  • Any default-autowire-candidates patterns available on the <beans/> element

    元素default-autowire-candidates上可用的任何模式<beans/>

  • The presence of @Qualifier annotations and any custom annotations registered with the CustomAutowireConfigurer

    注释的存在@Qualifier和任何注册的自定义注释CustomAutowireConfigurer

When multiple beans qualify as autowire candidates, the determination of a “primary” is as follows: If exactly one bean definition among the candidates has a primary attribute set to true, it is selected.

当多个 bean 有资格成为自动装配候选者时,“主要”的确定如下:如果候选者中恰好一个 bean 定义的primary 属性设置为true,则选择它。

1.9.7. Injection with @Resource

注射用@Resource

Spring also supports injection by using the JSR-250 @Resource annotation (javax.annotation.Resource) on fields or bean property setter methods. This is a common pattern in Java EE: for example, in JSF-managed beans and JAX-WS endpoints. Spring supports this pattern for Spring-managed objects as well.

Spring 还通过在字段或 bean 属性设置器方法上使用 JSR-250@Resource注释 ( )来支持注入。javax.annotation.Resource这是 Java EE 中的常见模式:例如,在 JSF 管理的 bean 和 JAX-WS 端点中。Spring 也支持 Spring 管理的对象的这种模式。

@Resource takes a name attribute. By default, Spring interprets that value as the bean name to be injected. In other words, it follows by-name semantics, as demonstrated in the following example:

@Resource采用名称属性。默认情况下,Spring 将该值解释为要注入的 bean 名称。换句话说,它遵循按名称语义,如以下示例所示:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Resource(name="myMovieFinder") 
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
This line injects a @Resource.
此行注入一个@Resource.

If no name is explicitly specified, the default name is derived from the field name or setter method. In case of a field, it takes the field name. In case of a setter method, it takes the bean property name. The following example is going to have the bean named movieFinder injected into its setter method:

如果没有明确指定名称,则默认名称派生自字段名称或 setter 方法。如果是字段,则采用字段名称。对于 setter 方法,它采用 bean 属性名称。以下示例将把名为 bean 的 beanmovieFinder注入到它的 setter 方法中:

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Resource
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
The name provided with the annotation is resolved as a bean name by the ApplicationContext of which the CommonAnnotationBeanPostProcessor is aware. The names can be resolved through JNDI if you configure Spring’s SimpleJndiBeanFactory explicitly. However, we recommend that you rely on the default behavior and use Spring’s JNDI lookup capabilities to preserve the level of indirection.
随注解提供的名称被解析为 bean 名称,由 bean ApplicationContext知道CommonAnnotationBeanPostProcessor。如果显式配置 Spring,则可以通过 JNDI 解析名称 SimpleJndiBeanFactory 。但是,我们建议您依赖默认行为并使用 Spring 的 JNDI 查找功能来保留间接级别。

In the exclusive case of @Resource usage with no explicit name specified, and similar to @Autowired, @Resource finds a primary type match instead of a specific named bean and resolves well known resolvable dependencies: the BeanFactory, ApplicationContext, ResourceLoader, ApplicationEventPublisher, and MessageSource interfaces.

在未指定显式名称的排他性@Resource使用情况下,类似于@Autowired@Resource查找主类型匹配而不是特定的命名 bean 并解析众所周知的可解析依赖项:BeanFactoryApplicationContextResourceLoaderApplicationEventPublisherMessageSource 接口。

Thus, in the following example, the customerPreferenceDao field first looks for a bean named "customerPreferenceDao" and then falls back to a primary type match for the type CustomerPreferenceDao:

因此,在以下示例中,该customerPreferenceDao字段首先查找名为“customerPreferenceDao”的 bean,然后回退到 type 的主要类型匹配 CustomerPreferenceDao

public class MovieRecommender {
    @Resource
    private CustomerPreferenceDao customerPreferenceDao;
    @Resource
    private ApplicationContext context; 
    public MovieRecommender() {
    }
    // ...
}
The context field is injected based on the known resolvable dependency type: ApplicationContext.
context字段是根据已知的可解析依赖类型注入的: ApplicationContext.

1.9.8. Using @Value

使用@Value

@Value is typically used to inject externalized properties:

@Value通常用于注入外部属性:

@Component
public class MovieRecommender {
    private final String catalog;
    public MovieRecommender(@Value("${catalog.name}") String catalog) {
        this.catalog = catalog;
    }
}

With the following configuration:

使用以下配置:

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }

And the following application.properties file:

以及以下application.properties文件:

catalog.name=MovieCatalog

In that case, the catalog parameter and field will be equal to the MovieCatalog value.

在这种情况下,catalog参数和字段将等于该MovieCatalog值。

A default lenient embedded value resolver is provided by Spring. It will try to resolve the property value and if it cannot be resolved, the property name (for example ${catalog.name}) will be injected as the value. If you want to maintain strict control over nonexistent values, you should declare a PropertySourcesPlaceholderConfigurer bean, as the following example shows:

Spring 提供了一个默认的宽松嵌入式值解析器。它将尝试解析属性值,如果无法解析,属性名称(例如${catalog.name})将作为值注入。如果要严格控制不存在的值,则应声明一个PropertySourcesPlaceholderConfigurerbean,如以下示例所示:

@Configuration
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}
When configuring a PropertySourcesPlaceholderConfigurer using JavaConfig, the @Bean method must be static.
配置PropertySourcesPlaceholderConfigurer使用 JavaConfig 时, @Bean方法必须是static.

Using the above configuration ensures Spring initialization failure if any ${} placeholder could not be resolved. It is also possible to use methods like setPlaceholderPrefix, setPlaceholderSuffix, or setValueSeparator to customize placeholders.

${} 如果无法解析任何占位符,使用上述配置可确保 Spring 初始化失败。也可以使用 setPlaceholderPrefix, setPlaceholderSuffix, 或setValueSeparator自定义占位符等方法。

Spring Boot configures by default a PropertySourcesPlaceholderConfigurer bean that will get properties from application.properties and application.yml files.
Spring Boot 默认配置一个PropertySourcesPlaceholderConfigurerbean,该 bean 将从application.propertiesapplication.yml文件中获取属性。

Built-in converter support provided by Spring allows simple type conversion (to Integer or int for example) to be automatically handled. Multiple comma-separated values can be automatically converted to String array without extra effort.

Spring 提供的内置转换器支持允许自动处理简单的类型转换(toInteger 或example)。int多个逗号分隔的值可以自动转换为String数组,无需额外的努力。

It is possible to provide a default value as following:

可以提供如下默认值:

@Component
public class MovieRecommender {
    private final String catalog;
    public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
        this.catalog = catalog;
    }
}

A Spring BeanPostProcessor uses a ConversionService behind the scenes to handle the process for converting the String value in @Value to the target type. If you want to provide conversion support for your own custom type, you can provide your own ConversionService bean instance as the following example shows:

Spring BeanPostProcessor在后台使用ConversionService来处理将@value中的字符串值转换为目标类型的过程。如果您想为自己的自定义类型提供转换支持,可以提供自己的ConversionService bean实例,如下例所示:

@Configuration
public class AppConfig {
    @Bean
    public ConversionService conversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        conversionService.addConverter(new MyCustomConverter());
        return conversionService;
    }
}

When @Value contains a SpEL expression the value will be dynamically computed at runtime as the following example shows:

@Value包含SpEL表达式时,该值将在运行时动态计算,如以下示例所示:

@Component
public class MovieRecommender {
    private final String catalog;
    public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
        this.catalog = catalog;
    }
}

SpEL also enables the use of more complex data structures:

SpEL 还支持使用更复杂的数据结构:

@Component
public class MovieRecommender {
    private final Map<String, Integer> countOfMoviesPerCatalog;
    public MovieRecommender(
            @Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
        this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
    }
}

1.9.9. Using @PostConstruct and @PreDestroy

使用@PostConstruct@PreDestroy

The CommonAnnotationBeanPostProcessor not only recognizes the @Resource annotation but also the JSR-250 lifecycle annotations: javax.annotation.PostConstruct and javax.annotation.PreDestroy. Introduced in Spring 2.5, the support for these annotations offers an alternative to the lifecycle callback mechanism described in initialization callbacks and destruction callbacks. Provided that the CommonAnnotationBeanPostProcessor is registered within the Spring ApplicationContext, a method carrying one of these annotations is invoked at the same point in the lifecycle as the corresponding Spring lifecycle interface method or explicitly declared callback method. In the following example, the cache is pre-populated upon initialization and cleared upon destruction:

CommonAnnotationBeanPostProcessor不仅可以识别注解,@Resource还可以识别 JSR-250 生命周期注解:javax.annotation.PostConstructjavax.annotation.PreDestroy. 在 Spring 2.5 中引入,对这些注解的支持提供了初始化回调销毁回调中描述的生命周期回调机制的替代方案 。如果 CommonAnnotationBeanPostProcessor在 Spring 中注册了ApplicationContext,则在生命周期中与对应的 Spring 生命周期接口方法或显式声明的回调方法相同的点调用带有这些注释之一的方法。在以下示例中,缓存在初始化时预先填充并在销毁时清除:

public class CachingMovieLister {
    @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }
    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }
}

For details about the effects of combining various lifecycle mechanisms, see Combining Lifecycle Mechanisms.

组合各种生命周期机制的效果的详细信息,请参见 组合生命周期机制

Like @Resource, the @PostConstruct and @PreDestroy annotation types were a part of the standard Java libraries from JDK 6 to 8. However, the entire javax.annotation package got separated from the core Java modules in JDK 9 and eventually removed in JDK 11. If needed, the javax.annotation-api artifact needs to be obtained via Maven Central now, simply to be added to the application’s classpath like any other library.
就像@Resource@PostConstruct@PreDestroy注解类型是从 JDK 6 到 8 的标准 Java 库的一部分。但是,整个javax.annotation 包在 JDK 9 中与核心 Java 模块分离,并最终在 JDK 11 中被删除。如果需要,javax.annotation-api工件需要现在通过 Maven Central 获得,只需像任何其他库一样添加到应用程序的类路径中。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值