IOC - DI/依赖注入
属性注入
-
如果 Person 类型的 bean 只有一个,直接注入,名字无所谓
注册 bean(容器中 Person 类型的 bean 只有这一个,bean 名称是 person)
@Bean public Person person(){ return new Person(); }
注入 bean
// 可以注入 @Autowired private Person person; // 也可以注入,名字无所谓 @Autowired private Person asdf;
-
如果 Person 类型的 bean 有多个,再按照名称去找,如果找到了就注入,如果找不到就报错
注册 bean(容器中有两个 Person 类型的 bean,分别是 marry 和 bob)
@Bean public Person marry(){ return new Person(); } @Bean public Person bob(){ return new Person(); }
注入 bean
// 根据 Person 找到多个,找不到名称是 asdf,报错 @Autowired private Person asdf; // 注入名称是 marry 的 bean @Autowired private Person marry; // 注入名称是 bob 的 bean @Autowired private Person bob; // 把所有 Person 类型的 bean 注入到一个 list,名字无所谓 @Autowired private List<Person> personList; // 把所有 Person 类型的 bean 注入到一个 map,名字无所谓(map 的 key 是 bean名称,value 是 bean对象) @Autowired private Map<String, Person> personMap; // ICO 容器也能注入 @Autowired private ApplicationContext applicationContext;
-
@Primary
和@Qualifier
当根据类型找到多个 bean 的时候可以更改属性名,spring 会自动根据属性名过滤一次 bean
如果不想改属性名可以使用
@Qualifier
或@Primary
// 容器中有两个 Person 类型的 bean,分别是 marry 和 bob,这种会报错 @Autowired private Person asdf; // 解决方案1:属性名写成正确的 bean 的名称 @Autowired private Person marry; // 解决方案2:使用 @Qualifier 标注 bean 名称 @Qualifier("marry") @Autowired private Person asdf; // 解决方案3:给其中的一个 bean 使用 @Primary 标注 // 给 marry 这个 bean 加 @Primary @Primary @Bean public Person marry(){ return new Person(); } // 这时注入的就是 marry @Autowired private Person asdf;
构造注入
- 必须是有参构造
- 不用
@Autowired
注解
@Component
public class Test {
private Person person;
// 容器在创建 Test 这个 bean 的时候会反射调用这个构造方法,回到容器找参数类型的 bean 来注入
public Test(Person person) {
this.person = person;
}
}
setter 注入
@Autowired
标在 setter 上
@Component
public class Test {
// 属性名无所谓,真正注入的是 Person 类型的 bean
private Person asdfasdf;
// 如果 Person 的 bean 是多个,也能使用 @Qualifier 指定 bean 名称,或者给一个 bean 加 @Primary 注解
@Autowired
public void setPerson(@Qualifier("marry") Person person) {
this.asdfasdf = person;
}
}
@Resource
@Resource
也能属性注入(且只能属性注入)这是 java 自己的注解,更具有通用性- 默认优先根据名称找,找不到再根据类型找,都找不到就报错
- 可以指定名称和类型
@Resource(name = "xx", type = Class)
- 如果指定名称
@Resource(name = "xx")
,只根据名称找,不到就报错,不会再根据类型找 - 如果指定类型
@Resource(type = Class)
,找到的 bean 必须能转成属性的类型,不然报错
- 如果指定名称
两个 java 类
public class Dog {
private String name;
private int age;
// getter setter
}
public class Hashiqi extends Dog {
}
注册 bean
@Bean
public Dog dog() {
Dog dog = new Dog();
dog.setAge(2);
dog.setName("狗子");
return dog;
}
@Bean("erha")
public Hashiqi hashiqi() {
Hashiqi hashiqi = new Hashiqi();
hashiqi.setAge(2);
hashiqi.setName("哈士奇");
return hashiqi;
}
注入 bean
@Component
public class Person {
// 根据 dog 能找到 bean。注入成功
@Resource
private Dog dog;
// 没有 hashiqi 的 bean,但是有 Hashiqi 类型的 bean。注入成功
@Resource
private Hashiqi hashiqi;
// 指定 name 就只根据名称找,不会根据类型找。注入失败
@Resource(name = "hashiqi")
private Hashiqi hashiqi;
// 根据 name 能找到,type 也符合,找到的 bean 是 Dog 的子类。注入成功
@Resource(name = "erha", type = Hashiqi.class)
private Dog erha;
// 根据 name 能找到,找到的 bean 是 Dog 的子类。注入成功
@Resource(name = "erha", type = Dog.class)
private Hashiqi erha;
// 根据 dog 找到的 bean 是 Dog 类型,type 指定的是 Hashiqi 类型(父类不能转成子类)。注入失败
@Resource(type = Hashiqi.class)
private Dog dog;
}
@Resource VS @Autowired
- 一个是 javaEE 的,一个是 spring 的。@Resource 更通用,但是 web 方便 spring 一家独大
- 默认情况下 @Resource 优先根据名称找,找不到再根据类型找;@Autowired 优先根据类型找,找到多个根据名称过滤
- @Resource 优先根据名称找,不会找到多个,spring 注入 bean 时名称是唯一的
- @Autowired 优先根据类型找
- 如果找到多个,根据名称再匹配一次
- 如果找到一个,直接注入
- 如果找不到,直接报错,类型都找不到,就算格局名称能找到,转型也不一定能成功
- 都可以指定名称
- @Resource 指定了名称就精准匹配,找不到就报错
- @Autowired 因为可能根据类型找到多个,指定名称是用来筛选的
- @Resource 可以指定类型,需要注意类型是否能转型成功,@Autowired 不能指定类型
- @Resource 只能属性注入,@Autowired 可以属性和 setter 两种方式注入(构造注入没 @Autowired 的事儿)
- @Resource 必须要找到,找不到报错;@Autowired 可以配置 require = false,找不到不报错
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具