• @Autowired 多个相同类型Bean的自动注入


    背景

    参考代码尝试:
    https://github.com/LinkedBear/spring-framework-learning-code/tree/master/spring-01-ioc/src/main/java/com/linkedbear/spring/basic_di/d_autowired

    1. 我们可以通过声明@Configuration,并在里面定义@Bean来声明bean。这种方式适用于引用第三方jar包的类

    示例如下:

    @Configuration
    public class QuickstartConfiguration {
    	@Bean
    	public Person person() {
        	return new Person();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    默认bean的id就是方法名,如上面Person类的id就叫‘person’。如果想更改id值,直接修改方法名即可

    1. 另一种bean的声明,直接用@Component注解,这种适用于我们项目中自定义的类
    @Component
    public class Person {
        
    }
    
    • 1
    • 2
    • 3
    • 4

    默认的bean的id就是类名(首字母替小写),如上面的Person类的id就叫‘person’,如果想更改id值,直接在注解中指定就行,如@Component(“aaa”),Person类的id就改成了’aaa’

    具体spring注册了哪些bean,可以通过如下来验证

    ApplicationContext ctx = new AnnotationConfigApplicationContext(AutowiredConfiguration.class);
    String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
    Stream.of(beanDefinitionNames).forEach(System.out::println);
    
    // *****像上面,如果两种的id改成相同值,也不会报错。但是通过id来获取bean时,也不报错,获取到的是用@Bean声明的那个bean。是不是@Bean的优先级更高些???
    Object person = ctx.getBean("person");
    System.out.println(person);
    
    // *****但如果是按类型来获取bean,因为都是Person类型,和通过id获取的一样,id相同就取@Bean声明的那个bean,有唯一的就取唯一的,一个都取不到就直接报错,这个直接用@Autowired注入的一样
    Person bean = ctx.getBean(Person.class);
    System.out.println(bean);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    问题

    参考@Autowired代码

    // Dog类直接声明成了bean,属性注入了Person类
    @Component
    public class Dog {
        
        @Value("dogdog")
        private String name;
        
        @Autowired
        //@Qualifier("administrator")
        private Person person;
        
        @Autowired
        private List<Person> persons;
        
        @Override
        public String toString() {
            return "Dog{" + "name='" + name + '\'' + ", person=" + person + ", persons=" + persons + '}';
        }
    }
    
    // Cat类是一个普通java类,有Person属性,通过@bean的方式声明
    @Bean
    @Autowired // 高版本可不标注
    public Cat cat(Person person) {
        Cat cat = new Cat();
        cat.setName("mimi");
        cat.setPerson(person);
        return cat;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    @Autowired默认是按照类型来匹配的,如果id相同,默认取的是@Bean声明的那个bean?(这块为了代码的可维护性,建议不要重名吧);如果id唯一就取唯一的;如果一个都取不到,就报错。

    重点就不类名相同,没有匹配的id的情况,有3种解决方式:

    1. 注入时直接修改名称
    // 对于属性注入的方式,把person修改成person1、person2之类的
    @Autowired
    private Person person1;
    
    // 对于构造器的方式,参数上修改成person1、person2之类的.这样声明Cat的bean时,就会找bean的id为‘person1’的类,注入到cat的person属性上
    @Bean
    //@Autowired
    public Cat cat(Person person1) {
        Cat cat = new Cat();
        cat.setName("mimi");
        cat.setPerson(administrator);
        return cat;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. @Qualifier的使用
      这个用得最多,在Qualifier中重新命名
    // 属性上
    @Autowired
    @Qualifier("person1")
    private Person person;
    
    // 构造器上
    @Bean
    //@Autowired
    public Cat cat(@Qualifier("person1") Person person) {
        Cat cat = new Cat();
        cat.setName("mimi");
        cat.setPerson(person);
        return cat;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 声明@Primary
    // 声明在@Bean上的
    @Bean
    @Primary
    public Person person1() {
        Person master = new Person();
        master.setName("master");
        return master;
    }
    
    // 声明在@Component上
    @Component("administrator")
    @Primary
    public class Person {
        
        private String name = "administrator";
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    补充 多个相同类型Bean的全部注入

    上面都是注入一个 Bean 的方式,通过两种不同的办法来保证注入的唯一性。但如果需要一下子把所有指定类型的 Bean 都注入进去应该怎么办呢?其实答案也挺简单的,注入一个用单个对象接收,注入一组对象就用集合来接收:

    @Component
    public class Dog {
        // ......
        
        @Autowired
        private List<Person> persons;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出时就可以看到注入了所有Person类型的类

    Dog{name='dogdog', person=Person{name='administrator'}, persons=[Person{name='administrator'}, Person{name='master'}]}
    
    • 1
  • 相关阅读:
    天天写 SQL,这些神奇的特性你知道吗?
    基于黄金正弦算法优化概率神经网络PNN的分类预测 - 附代码
    什么是MDD,DDD,TDD?
    PyCharm中 python 类型文件被识别为Text文本类型
    服务部署:使用docker部署开源Xxl-Job任务调度平台项目
    Android开发学习——3.平台版本、SDK版本、API级别
    考研专业课之C语言(郝斌)
    测试人生 | 从功能到外企测开,工作1年半拿下年薪30万的测开 offer,这个95后小姐姐未来可期~
    【Vue3】Axios简易二次封装+token+跨域问题+接口同步调用使用。
    AI_Neural Network_Note(一)
  • 原文地址:https://blog.csdn.net/dulinanaaa/article/details/126026814