• @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
  • 相关阅读:
    『开源资讯』JimuReport 积木报表 v1.6.5 版本发布 — 免费报表工具
    数据仓库模式之详解 Inmon 和 Kimball
    Java中,对象一定在堆中分配吗?
    JSP ssm 特殊人群防走失系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
    股票交易查询接口api新增哪些了特点?
    【JavaWeb】第二章 CSS
    MT8735/MTK8735安卓核心板规格参数介绍
    组件安全漏洞
    用代码实现全自动化批量下单官网的 iPhone-14-Pro 集成智能下单购物系统,附源码可直接运行
    Mysql-库的操作
  • 原文地址:https://blog.csdn.net/dulinanaaa/article/details/126026814