• 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的问题。

  • 相关阅读:
    用Python实现多核心并行计算
    Sublime Text 中文乱码
    Python_pickle
    New blog
    git Bash常用命令
    用TTS实现文本转语音
    bc#54 div2
    用Python制作新浪微博爬虫
    hdu5000 背包dp
    mac下配置Qt for Android+iOS
  • 原文地址:https://www.cnblogs.com/lvjianwei/p/7490547.html
Copyright © 2020-2023  润新知