Spring文档2.9

2.9 Annotation-based Container Configuration 基于注解的容器配置

Are annotations better than XML for configuring Spring?

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.

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.

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

无论选择什么,Spring都可以同时容纳两种风格,甚至将它们混合在一起。值得指出的是,通过它的JavaConfig选项,Spring允许以一种非侵入性的方式使用注释,而不涉及目标组件源代码,并且,在工具方面,所有的配置风格都得到了Eclipse的Spring工具的支持。

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 RequiredAnnotationBeanPostProcessor, 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连接,而是通过使用相关类、方法或字段声明上的注释将配置移动到组件类本身。如示例中所述:RequiredAnnotationBeanPostProcessor,将BeanPostProcessor与注释结合使用是扩展Spring IoC容器的一种常见方法。例如,Spring 2.0引入了使用@Required注释强制执行所需属性的可能性。Spring 2.5使得采用相同的通用方法来驱动Spring的依赖项注入成为可能。本质上,@Autowired注解提供了与Autowiring合作者描述的相同的功能,但是更细粒度的控制和更广泛的适用性。Spring 2.5还增加了对JSR-250注释的支持,比如@PostConstruct和@PreDestroy。Spring 3.0增加了对javax中包含的JSR-330 (Java依赖注入)注释的支持。注入包,如@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 them 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配置中包含以下标记来隐式注册它们(请注意上下文名称空间的包含):

<?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 implicitly registered post-processors include AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, and the aforementioned RequiredAnnotationBeanPostProcessor.)

(隐式注册的后处理器包括AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor和前面提到的RequiredAnnotationBeanPostProcessor。)

  • <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/放在一个DispatcherServlet的WebApplicationContext中,它只会检查你的控制器中的@Autowired bean,而不会检查你的服务。有关更多信息,请参见DispatcherServlet。

2.9.1. @Required

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

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 @Required annotation is formally deprecated as of Spring Framework 5.1, in favor of using constructor injection for required settings (or a custom implementation of InitializingBean.afterPropertiesSet() along with bean property setter methods).

  • 从Spring Framework 5.1开始,@Required注释被正式弃用,支持为所需的设置使用构造函数注入(或InitializingBean.afterPropertiesSet()的自定义实现以及bean属性设置器方法)。

2.9.2 Using @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.

  • 在本节包含的示例中,JSR 330的@Inject注释可以代替Spring的@Autowired注释。详情请看这里。

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

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, at least one must be annotated with @Autowired in order to instruct the container which one to use.
  • 从Spring Framework 4.3开始,如果目标bean只定义一个构造函数,那么就不再需要在这样的构造函数上使用@Autowired注解。但是,如果有多个构造函数可用,那么必须至少有一个用@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).

确保您的目标组件(例如MovieCatalog或CustomerPreferenceDao)是由用于@ autowire注释的注入点的类型一致声明的。否则,注入可能会由于运行时错误“没有找到类型匹配”而失败。

对于通过类路径扫描找到的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:

您还可以指示Spring通过向需要该类型数组的字段或方法添加@Autowired注释来从ApplicationContext中提供特定类型的所有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.springframe .core。如果希望数组或列表中的项按特定顺序排序,可以使用@Order或标准的@Priority注释。否则,它们的顺序将遵循容器中相应的目标bean定义的注册顺序。

您可以在目标类级别和@Bean方法上声明@Order注释,可能是针对单个bean定义(如果多个定义使用相同的bean类)。@Order值可能会影响注入点的优先级,但是要注意它们不会影响单例启动顺序,这是一个由依赖关系和@DependsOn声明决定的正交关系。

注意,标准的javax.annotation。在@Bean级别上不能使用Priority注释,因为它不能在方法上声明。它的语义可以通过@Order值与针对每种类型的单个bean上的@Primary组合来建模。

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 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值