zoukankan      html  css  js  c++  java
  • Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.9.4 使用@Qualifier微调基于注解的自动装配

    6.9.4 使用@Qualifier微调基于注解的自动装配

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

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

    @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;
        }
    
        // ...
    
    }

    相应的bean定义如下所示。具有限定符值“main”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
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://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>

    对于回匹配,bean名称被视为默认限定符值。因此,您可以使用id“main”而不是嵌套的限定符元素来定义bean,从而得到相同的匹配结果。但是,虽然您可以使用此约定来按名称引用特定bean,但@Autowired基本上是关于具有可选语义限定符的类型驱动注入。这意味着即使使用bean名称回调,限定符值在类型匹配集合中也总是具有缩小范围的语义; 它们在语义上不表示对唯一bean id的引用。好的限定符值是“main”“EMEA”“persistent”,表示独立于bean id的特定组件的特征,在匿名bean定义的情况下可以自动生成,如上例中的那个。

    限定符也适用于类型化集合,如上所述,例如,Set <MovieCatalog>。在这种情况下,根据声明的限定符的所有匹配bean都作为集合注入。这意味着限定符不必是唯一的; 它们只是简单地成过滤条件。例如,您可以使用相同的限定符值“action”定义多个MovieCatalog bean,所有这些bean都将注入到使用@Qualifier(“action”)Set <MovieCatalog>中。

    如果您打算按名称驱动的注入,尽管技术上能够通过@Qualifier值引用bean名称;也不要大量使用@Autowired反而可以使用JSR-250 @Resource,在语义上该注定义为通过其唯一名称标识一个指目标组件,并且声明的类型与匹配过程无关。

    作为该语义差异的明确结果,本身定义为集合或映射类型的bean是无法通过@Autowired注入,因为类型匹配不适用于它们。 对这样的bean使用@Resource通过唯一名称引用定的集合或映射bean

    @Autowired适用于字段,构造函数和多参数方法,允许限定符注在参数级别缩小范围。相比之下,@ Resource仅支持具有单个参数的字段和bean属性的setter方法。因此,如果您的注目标是构造函数或多参数方法,请坚持使用限定符。

    您可以创建自己的自定义限定符注。只需定义一个在定义中提供@Qualifier

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

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

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

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

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

    6.10类路径扫描和受管理的组件中,您将看到基于注的替代方法,用于在XML中提供限定符元数据。具体来说,请参见6.10.8使用注提供限定符元数据

    在某些情况下,使用没有值的注可能就足够了。当注用于更通用的目的并且可以跨多种不同类型的依赖项应用时,这可能很有用。例如,在没有Internet连接时您可以提供将搜索的offline目录。首先定义简单注

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

    然后将注添加到要自动装配的字段或属性中:

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

    现在bean定义只需要一个限定符类型:

    <bean class="example.SimpleMovieCatalog">
        <qualifier type="Offline"/>
    <!-- inject any dependencies required by this bean -->
    </bean>

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

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

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

    public enum Format {
        VHS, DVD, BLURAY
    }

    要自动装配的字段使用自定义限定符进行注,并包含两个属性的值: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;
    
        // ...
    
    }

    最后,bean定义应包含匹配的限定符值。此示例还演示了可以使用bean meta属性来替代<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
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://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>

  • 相关阅读:
    轻松Ajax.net实例教程12_TabContainer和TabPanel(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程9_HoverMenuExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程11_PopupControlExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程7_DropDownExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程4_CalendarExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程3_AutoCompleteExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程8_DynamicPopulateExtender(按AjaxControlToolkit字母排序)
    轻松Ajax.net实例教程5_CascadingDropDown(按AjaxControlToolkit字母排序)
    [SHOI2014]概率充电器
    [HAOI2012]高速公路
  • 原文地址:https://www.cnblogs.com/springmorning/p/10397394.html
Copyright © 2011-2022 走看看