IOC - DI/依赖注入

属性注入

  1. 如果 Person 类型的 bean 只有一个,直接注入,名字无所谓

    注册 bean(容器中 Person 类型的 bean 只有这一个,bean 名称是 person)

    @Bean
    public Person person(){
        return new Person();
    }
    

    注入 bean

    // 可以注入
    @Autowired
    private Person person;
    
    // 也可以注入,名字无所谓
    @Autowired
    private Person asdf;
    
  2. 如果 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;
    
  3. @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;
    

构造注入

  1. 必须是有参构造
  2. 不用 @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

  1. @Resource 也能属性注入(且只能属性注入)这是 java 自己的注解,更具有通用性
  2. 默认优先根据名称找,找不到再根据类型找,都找不到就报错
  3. 可以指定名称和类型 @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

  1. 一个是 javaEE 的,一个是 spring 的。@Resource 更通用,但是 web 方便 spring 一家独大
  2. 默认情况下 @Resource 优先根据名称找,找不到再根据类型找;@Autowired 优先根据类型找,找到多个根据名称过滤
    • @Resource 优先根据名称找,不会找到多个,spring 注入 bean 时名称是唯一的
    • @Autowired 优先根据类型找
      • 如果找到多个,根据名称再匹配一次
      • 如果找到一个,直接注入
      • 如果找不到,直接报错,类型都找不到,就算格局名称能找到,转型也不一定能成功
  3. 都可以指定名称
    • @Resource 指定了名称就精准匹配,找不到就报错
    • @Autowired 因为可能根据类型找到多个,指定名称是用来筛选的
  4. @Resource 可以指定类型,需要注意类型是否能转型成功,@Autowired 不能指定类型
  5. @Resource 只能属性注入,@Autowired 可以属性和 setter 两种方式注入(构造注入没 @Autowired 的事儿)
  6. @Resource 必须要找到,找不到报错;@Autowired 可以配置 require = false,找不到不报错
posted @   CyrusHuang  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示