《Spring攻略(第2版)》——1.12 用@Autowired和@Resource自动装配Bean

    xiaoxiao2024-05-07  8

    本节书摘来自异步社区《Spring攻略(第2版)》一书中的第1章,第1.12节,作者: 【美】Gary Mak , Josh Long , Daniel Rubio著,更多章节内容可以访问云栖社区“异步社区”公众号查看

    1.12 用@Autowired和@Resource自动装配Bean

    1.12.1 问题在Bean配置文件中设置autowire属性进行的自动装配将装配一个Bean的所有属性。这样的灵活性不足以仅仅装配特定的属性。而且,你只能通过类型或者名称自动装配Bean。如果这两种策略都不能满足你的需求,就必须明确地装配Bean。

    1.12.2 解决方案从Spring 2.5起,自动装配功能进行了多处改进。你可以通过用@Autowired或者@Resource(在JSR-250:Java平台常见注解中定义)注解一个设值方法、构造程序、字段甚至任意方法自动装配特定的属性。这意味着你除了设置autowire属性之外,还有一个能够满足需求的选择。但是,这种基于注解的选项要求你使用Java 1.5或者更高版本。

    1.12.3 工作原理为了要求Spring自动装配具有@Autowired或者@Resource注解的属性,你必须在IoC容器中注册一个AutowiredAnnotationBeanPostProcessor实例。如果你使用一个Bean工厂,就必须通过API注册这个Bean后处理器,否则,你只能在你的应用上下文里声明一个实例。

    <bean class="org.springframework.beans.factory.annotation.    AutowiredAnnotationBeanPostProcessor" />

    你也可以简单地在Bean配置文件中包含元素,这将自动注册一个AutowiredAnnotationBeanPostProcessor实例。

    <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      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd      http://www.springframework.org/schema/context      http://www.springframework.org/schema/context/spring-context-3.0.xsd">    <context:annotation-config />    ... </beans>

    自动装配一个兼容类型的Bean@Autowired可以应用到一个特定的需要Spring自动装配的属性。例如,你可以用@Autowired注解prefixGenerator属性的设值方法。然后,Spring将试图装配一个类型与prefixGenerator兼容的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    ...    @Autowired    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {      this.prefixGenerator = prefixGenerator;    } }

    如果你在IoC容器中定义了一个与PrefixGenerator类型兼容的Bean,它将自动地设置到PrefixGenerator属性上。

    <beans ...>    ...    <bean id="sequenceGenerator"      class="com.apress.springrecipes.sequence.SequenceGenerator">      <property name="initial" value="100000" />      <property name="suffix" value="A" />    </bean>    <bean id="datePrefixGenerator"      class="com.apress.springrecipes.sequence.DatePrefixGenerator">      <property name="pattern" value="yyyyMMdd" />    </bean> </beans>

    默认情况下,所有带有@Autowired的属性都是必需的。当Spring不能找到匹配的Bean进行装配时,将会抛出一个异常。如果你希望某个属性是可选的,将@Autowired的required属性设置为false。之后,当Spring找不到匹配的Bean,将不设置该属性。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    ...    @Autowired(required = false)    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {      this.prefixGenerator = prefixGenerator;    } }

    除了设值方法之外,@Autowired注解还可以应用到构造程序,Spring将为每个构造程序参数寻找一个具有兼容类型的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    ...    @Autowired    public SequenceGenerator(PrefixGenerator prefixGenerator) {      this.prefixGenerator = prefixGenerator;    } }

    @Autowired注解还可以应用到一个字段,即使这个字段没有声明为Public。这样,你不能省略这个字段的设值方法或者构造程序的声明。Spring将通过反射把匹配的Bean注入这个字段。但是,用@Autowired注解非公开的字段将降低代码的可测试性,因为代码将很难进行单元测试(黑盒测试法无法使用模拟对象之类的方式操纵这一状态)。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    @Autowired    private PrefixGenerator prefixGenerator;    ... }

    你甚至可以将@Autowired注解应用到具有任意名称和任意数量参数的方法上,在这种情况下,Spring将试图为每个方法参数装配一个类型兼容的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    ...    @Autowired    public void inject(PrefixGenerator prefixGenerator) {      this.prefixGenerator = prefixGenerator;    } }

    自动装配所有兼容类型的Bean@Autowired注解还可以应用到一个数组类型的属性上,让Spring自动装配所有匹配的Bean。例如,你可以用@Autowired注解一个PrefixGenerator[]属性。然后,Spring将一次性自动装配所有类型与PrefixGenerator兼容的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    @Autowired    private PrefixGenerator[] prefixGenerators;    ... }

    如果你在IoC容器中有多个类型与PrefixGenerator兼容类型的Bean,它们将自动被添加到PrefixGenerators数组中。

    <beans ...>    ...    <bean id="datePrefixGenerator"      class="com.apress.springrecipes.sequence.DatePrefixGenerator">      <property name="pattern" value="yyyyMMdd" />    </bean>    <bean id="yearPrefixGenerator"      class="com.apress.springrecipes.sequence.DatePrefixGenerator">      <property name="pattern" value="yyyy" />    </bean> </beans>

    相似地,你可以将@Autowired注解应用类型安全的集合。Spring能够读取这个集合的类型信息,自动装配所有类型兼容的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    @Autowired    private List<PrefixGenerator> prefixGenerators;    ... }

    如果Spring注意到@Autowired注解应用到了一个关键字为字符串的类型安全java.util.Map,它将在这个Map中添加所有Bean名称与关键字相同的兼容类型Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    @Autowired    private Map<String, PrefixGenerator> prefixGenerators;    ... }

    使用限定符的按类型自动装配默认情况下,按照类型的自动装配在IoC容器中有超过一个类型兼容的Bean时无效。但是,Spring允许你指定一个候选Bean,这个Bean的名称在@Qualifier注解中提供。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; public class SequenceGenerator {    @Autowired    @Qualifier("datePrefixGenerator")    private PrefixGenerator prefixGenerator;    ... }

    完成了这项工作,Spring将会试图在IoC容器中查找一个具有这个名称的Bean,将其装配到这个属性中。

    <bean id="datePrefixGenerator" class="com.apress.springrecipes.sequence.DatePrefixGenerator">    <property name="pattern" value="yyyyMMdd" /> </bean> @Qualifier注解也可以应用到方法参数中进行自动装配。 package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; public class SequenceGenerator {    ...    @Autowired    public void inject(         @Qualifier("datePrefixGenerator") PrefixGenerator prefixGenerator) {      this.prefixGenerator = prefixGenerator;    } }

    你可以为自动装配创建一个自定义的限定符注解类型。这种注解类型必须用@Qualifier注解。如果你希望一种特殊的Bean和配置在注解装饰字段或者设值方法时注入,那么就可以使用这种注解类型。

    package com.apress.springrecipes.sequence; import java.lang.annotation.Target; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy;import org.springframework.beans.factory.annotation.Qualifier; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER }) @Qualifier public @interface Generator {    String value(); }

    之后,你可以将这个注解应用到@Autowired bean属性。这将要求Spring自动装配带有这个限定符注解和特定值的Bean。

    package com.apress.springrecipes.sequence; import org.springframework.beans.factory.annotation.Autowired; public class SequenceGenerator {    @Autowired    @Generator("prefix")    private PrefixGenerator prefixGenerator;    ... }

    你必须向希望自动装配到前述的属性中的目标Bean提供这个限定符。限定符由带有type属性的元素添加。限定符值在value属性中指定。Value属性映射到注解的String value()属性。

    <bean id="datePrefixGenerator"    class="com.apress.springrecipes.sequence.DatePrefixGenerator">    <qualifier type="Generator" value="prefix" />    <property name="pattern" value="yyyyMMdd" /> </bean>

    按照名称自动装配如果你希望按照名称自动装配Bean属性,可以用JSR-250 @Resource注解为一个设值方法、构造程序或者字段加上注解。默认情况下,Spring将试图找到一个与属性同名的Bean。但是你可以显式地在name属性中指定Bean名称。

    注:

    为了使用JSR-250注解,你必须包含JSR 250依赖。如果你使用Maven,添加以下内容:

    <dependency> <groupId>javax.annotation</groupId> <artifactId>jsr250-api</artifactId> <version>1.0</version> </dependency> package com.apress.springrecipes.sequence; import javax.annotation.Resource; public class SequenceGenerator {    @Resource(name = "datePrefixGenerator")    private PrefixGenerator prefixGenerator;    ... } 相关资源:敏捷开发V1.0.pptx
    最新回复(0)