zoukankan      html  css  js  c++  java
  • Spring 实战-第三章-处理自动装配的歧义性

    profile解决了不同环境配置切换的问题,但是对于同一个接口,当有多个实现的时候,Spring无法判断应该使用何种实现,这个可以通过@Primary和@Qualifier注解解决。

    @Primary注解标示首选使用的bean,但是当存在多个有@Primary注解bean时,依然有无法判断的问题;

    @Qualifier注解,可以通过自定义、组合的方式标示使用哪个bean。

    1.接口

    package main.java.soundsystem;
    public interface CompactDisc {
        void play();
    }

    2.声明2个bean

    package main.java.soundsystem;
    
            import org.springframework.context.annotation.Condition;
            import org.springframework.context.annotation.ConditionContext;
            import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class SgtPepperCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return true;
        }
    }
    package main.java.soundsystem;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class YellowSubmarine implements CompactDisc{
        private String title ="Yellow Submarine";
        private String artist="The Beatles";
        @Override
        public void play() {
            System.out.println("Playing "+ title +" by "+artist);
        }{
        }
    }

    3.配置文件

    package main.java.soundsystem;
    import org.springframework.context.annotation.*;
    
    @Configuration
    public class CDPlayerConfig {
    
        @Bean
        @Primary
        public CompactDisc sgtPeppers() {
            return new SgtPepper();
        }
    
        @Bean
        public CompactDisc yellowSubmarine(){
            return new YellowSubmarine();
        }
    
    }

    4.测试

    package main.java.soundsystem;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {CDPlayerConfig.class})
    public class CDPlayerTest {
        @Autowired
        private CompactDisc cd;
    
        @Test
        public void cdShouldNotBeNull() {
            assertNotNull(cd);
            cd.play();
        }
    }

    在配置文件中,sgtPeppers上增加了@Primary注解,标示这是首选bean,若没有增加这个注解,编译时不会报错,但是运行是会有如下异常

    org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
      No qualifying bean of type 'main.java.soundsystem.CompactDisc' available:
        expected single matching bean but found 2: sgtPeppers,yellowSubmarine

    若不使用@Primary注解,可以使用@Qualifier注解

    将3.配置文件中的SgtPeppers上增加@Qualifier注解

    package main.java.soundsystem;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.*;
    
    @Configuration
    public class CDPlayerConfig {
    
        @Bean
        @Qualifier("peppers")
        public CompactDisc sgtPeppers() {
            return new SgtPepper();
        }
    
        @Bean
        public CompactDisc yellowSubmarine(){
            return new YellowSubmarine();
        }
    
    }

    在4.测试中,CompactDisc上增加相同的@Qualifier注解

    package main.java.soundsystem;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {CDPlayerConfig.class})
    public class CDPlayerTest {
        @Autowired
        @Qualifier("peppers")
        private CompactDisc cd;
    
        @Test
        public void cdShouldNotBeNull() {
            assertNotNull(cd);
            cd.play();
        }
    }

    在初始化cd的时候,会自动寻找带有相同@Qualifier注解的bean,不过如果相同有多个,还是会异常。

    为了更好的找到bean,可以创建自定义的限定符注解,借助这样的注解来表达bean所希望限定的特性。

    自定义限定符

    package main.java.soundsystem;
    
    
    import org.springframework.beans.factory.annotation.Qualifier;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.CONSTRUCTOR,ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Qualifier
    public @interface  ManualQualifier {
    }

    配置文件使用自定限定符

    package main.java.soundsystem;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.*;
    
    @Configuration
    public class CDPlayerConfig {
    
        @Bean
        @ManualQualifier
        public CompactDisc sgtPeppers() {
            return new SgtPepper();
        }
    
        @Bean
        public CompactDisc yellowSubmarine(){
            return new YellowSubmarine();
        }
    
    }

    使用自定义限定符

    package main.java.soundsystem;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {CDPlayerConfig.class})
    public class CDPlayerTest {
        @Autowired
        @ManualQualifier
        private CompactDisc cd;
    
        @Test
        public void cdShouldNotBeNull() {
            assertNotNull(cd);
            cd.play();
        }
    }

    对于限定符,是可以使用多个的,通过不同的组合,从根本上解决了使用哪个bean的问题。

  • 相关阅读:
    HDU 2116 Has the sum exceeded
    HDU 1233 还是畅通工程
    HDU 1234 开门人和关门人
    HDU 1283 最简单的计算机
    HDU 2552 三足鼎立
    HDU 1202 The calculation of GPA
    HDU 1248 寒冰王座
    HDU 1863 畅通工程
    HDU 1879 继续畅通工程
    颜色对话框CColorDialog,字体对话框CFontDialog使用实例
  • 原文地址:https://www.cnblogs.com/lvjianwei/p/7490547.html
Copyright © 2011-2022 走看看