zoukankan      html  css  js  c++  java
  • spring学习总结——高级装配学习二(处理自动装配的歧义性)

      我们已经看到如何使用自动装配让Spring完全负责将bean引用注入到构造参数和属性中。自动装配能够提供很大的帮助。不过,spring容器中仅有一个bean匹配所需的结果时,自动装配才是有效的。如果不仅有一个bean能够匹配结果的话,Spring此时别无他法,只好宣告失败并抛出异常。更精确地讲,Spring会抛出NoUniqueBeanDefinitionException。

      当确实发生歧义性时,Spring提供了多种可选方案来解决这样的问题。你可以将可选bean中的某一个设为首选(primary)的bean,或者使用限定符(qualifier)来帮助Spring将可选的bean的范围缩小到只有一个bean。

    例子:

    需要注入的bean:

      

    在本例中,Dessert是一个接口,并且有三个类实现了这个接口,分别为Cake、Cookies和IceCream:

       

    这三个实现均使用了@Component注解,在组件扫描的时候,能够发现它们并将其创建为Spring应用上下文里面的bean。然后,当Spring试图自动装配setDessert()中的Dessert参数时,它并没有唯一、无歧义的可选值。

    Spring提供了多种可选方案来解决这样的问题。你可以将可选bean中的某一个设为首选(primary)的bean,或者使用限定符(qualifier)来帮助Spring将可选的bean的范围缩小到只有一个bean。

    一、标示首选的bean(@Primary)

    1、隐式(@Component)

      

    2、显式(@Bean)

      

    3、xml模式:

      

      在声明bean的时候,通过将其中一个可选的bean设置为首选(primary)bean能够避免自动装配时的歧义性。当遇到歧义性的时候,Spring将会使用首选的bean,而不是其他可选的bean。实际上,你所声明就是“最喜欢”的bean。

    二、@Qualifier限定符

      如果有两个继承相同接口的类同时设置primary,则仍然会有歧义,因此引入Qualifier。Qualifier注解是使用限定符的主要方式,它可以与@AutoWired和@Inject协同使用,在注入的时候指定想要注入进去的是哪个bean。

    1、基于默认的bean ID作为限定符

    例如,我们想要确保要将IceCream注入到setDessert()之中:

       

      为@Qualifier注解所设置的参数就是想要注入的bean的ID。所有使用@Component注解声明的类都会创建为bean,并且bean的ID为首字母变为小写的类名,并且如果没有指定其他的限定符的话,所有的bean都会给定一个默认的限定符,这个限定符与bean的ID相同。因此,@Qualifier("iceCream")指向的是组件扫描时所创建的bean,并且这个bean是IceCream类的实例。

       基于默认的bean ID作为限定符是非常简单的,但这有可能会引入一些问题。如果你重构了IceCream类,将其重命名为Gelato的话,那此时会发生什么情况呢?如果这样的话,bean的ID和默认的限定符会变为gelato,这就无法匹配setDessert()方法中的限定符。自动装配会失败。

    2、创建自定义的限定符

    为bean设置自己的限定符,而不是依赖于将bean ID作为限定符。在bean声明上添加@Qualifier注解。

       

    在这种情况下,cold限定符分配给了IceCreambean。因为它没有耦合类名,因此你可以随意重构IceCream的类名,而不必担心会破坏自动装配。在注入的地方,只要引用cold限定符就可以了:

      

    在显式模式中:

      

    3、使用自定义的限定符注解

    错误示范:多个bean都具备相同特性的话,这种做法也会出现问题。可能想到的解决方案就是在注入点和bean定义的地方同时再添加另外一个@Qualifier注解

      

    ——————————————————————————

      

    可是,如果有另外一个bean也同样使用了cold限定符呢,还是会出现歧义,而java不允许同一个条目上重复出现相同类型的多个注解,否则编译器会报错,所以我们需要创建自定义的限定符注解,借助这样的注解来表达bean所希望限定的特性。

    当你不想用@Qualifier注解的时候,可以类似地创建@Soft、@Crispy和@Fruity。通过在定义时添加@Qualifier注解,它们就具有了@Qualifier注解的特性。它们本身实际上就成为了限定符注解。

    @Qualifier("cold")被代替:

      

    @Qualifier("creamy")被代替:

      

    使用例子:

     注解声明bean:

    IceCream类可以添加@Cold和@Creamy注解:

      

    Popsicle类可以添加@Cold和@Fruity注解:

      

     注入bean:

       

    通过声明自定义的限定符注解,我们可以同时使用多个限定符,不会再有Java编译器的限制或错误。与此同时,相对于使用原始的@Qualifier并借助String类型来指定限定符,自定义的注解也更为类型安全。

  • 相关阅读:
    java基础>包、访问权限、命名规范
    jsp>Session
    java基础>String类
    jsp>包含指令和forward指令
    jsp>response
    word不能输入中文
    java基础>正则表达式
    EJB>一对多及多对一映射
    Struts2>运行机制
    EJB>调用存储过程
  • 原文地址:https://www.cnblogs.com/TvvT-kevin/p/10004502.html
Copyright © 2011-2022 走看看