@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();
	}
}

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

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

默认的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);

问题

参考@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;
}

@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. @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. 声明@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";
    ...
}

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

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

@Component
public class Dog {
    // ......
    
    @Autowired
    private List<Person> persons;

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

Dog{name='dogdog', person=Person{name='administrator'}, persons=[Person{name='administrator'}, Person{name='master'}]}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值