当前位置: 首页 > news >正文

Spring DI

介绍

Spring DI 是 依赖注入,上一章我们学习到的 IoC 是控制反转,也就说将对象交由 Spring 来管理,也可以看作是一个存储的过程。而 Spring DI 就是从Spring 容器中获取对象的过程,也就说将对象赋值【注入】给某个引用

注入方式

Spring DI 注入的方式一共有三种:分别为 属性注入、构造方法注入、Setter 注入

我们以下面的 User 来举例

@AllArgsConstructor
@Data
public class User {
    private String name;
    private Integer age;
}
@Repository
public class Test {

    @Bean
    public User u1() {
        return new User("zhangsan", 14);
    }
}

我们将 u1 这个对象交给Spring 管理

属性注入

属性注入方式就是在属性上面添加 @Autowired 注解,注意 一个 @Autowired 注解只能对应一个 属性

@Controller
public class TestDI {
    @Autowired
    private User user;

    public void print() {
        System.out.println(user);
    }
}

构造方法注入

构造方法注入在某些情况下可以省略 @Autowired 注解

    private User user;

    public TestDI(User user) {
        this.user = user;
        System.out.println(user);
    }

依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法:

在这里插入图片描述


如果出现多个构造方法的话,默认的构造方法注入是 无参的构造方法:

@Controller
public class TestDI {
	
    private User user;

    public TestDI() {}

    public TestDI(User user) {
        this.user = user;
    }

    public void print() {
        System.out.println(user);
    }
}

在这里插入图片描述
最后发现 user 根本没有注入进去

如果你想要指定构造方法注入,可以在构造方法上加上 @Autowired 注解

    @Autowired
    public TestDI(User user) {
        this.user = user;
    }

在这里插入图片描述


如果只有一个构造方法那么 @Autowired 就可以省略
如果存在多个构造方法,可以通过 @Autowired 来指定默认 的构造方法

Setter 注入

Setter 注入需要在上面加上 @Autowired 注解

    private User user;

    @Autowired
    public void setUser(User user) {
        this.user = user;
    }

优缺点总结

属性注入:
优点:简洁方便
缺点:只能使用于IoC 容器中,不能注入一个 final 修饰的属性

构造方法注入:
优点:可以注入final 修饰的属性,注入的对象不会被修改
依赖对象在使用前一定会被完全初始化,因为依赖是在构造方法中执行的,而构造方法是在类加载阶段就会执行的方法
通用性好,构造方法是JDK 支持的,因此可以更换任何框架

缺点:注入多个对象的时候,代码会比较繁琐

setter 注入:
优点:方便在类实例之后,重新对该对象进行配置或者注入
缺点:不能注入一个 final 修饰的属性
注入对象可能会被改变,因为 setter 方法可能被多次调用,就会有被修改的风险

多个对象的注入

在上面我们粗略感受三大注入方式,但是 一个 @Autowired 只能对应一个对象,如果一个类型有多个对象的话,我们需要指定对应的对象来进行依赖注入:

@Repository
public class Test {

    @Bean
    public User u1() {
        return new User("zhangsan", 14);
    }
    
    @Bean
    public User u2() {
        return new User("lisi",15);
    }
}

如果我们还是使用下面的方式进行依赖注入的话,就会失败

    @Autowired
    private User user;

在这里插入图片描述
上面的信息是指依赖注入需要 TestDI 的单例 bean ,但是找到了两个 bean

也就说如果一个类型创建了对应的多个 bean 的话,只是使用 @Autowired 是无法完成注入工作的,因为 Spring 不知道要使用哪个对象来进行注入

下面的 Action 给了我们两个解决方案,使用 @Primary 或者 @Qualifier 注解,下面我们就来讲解一下

@Primary

@Primary 指定默认的依赖对象注入

在 u1 再加上 @Primary 注解:

@Repository
public class Test {

    @Primary
    @Bean
    public User u1() {
        return new User("zhangsan", 14);
    }

    @Bean
    public User u2() {
        return new User("lisi",15);
    }
}

那么下面的 user 就会被注入 zhangsan 这个对象

@Controller
public class TestDI {
    @Autowired
    private User user;

    public void print() {
        System.out.println(user);
    }
}

在这里插入图片描述


如果是在 lisi 上面加上 @Primary 注解,那就是 默认 lisi 为默认注入对象

@Repository
public class Test {
    @Bean
    public User u1() {
        return new User("zhangsan", 14);
    }

    @Primary
    @Bean
    public User u2() {
        return new User("lisi",15);
    }
}

在这里插入图片描述

@Qualifier

@Qualifier 是在 @Autowired 上面添加的,用来指定要注入的对象的名称

    @Qualifier("u1")
    @Autowired
    private User user;

    public void print() {
        System.out.println(user);
    }

在这里插入图片描述


在这里插入图片描述

通过查看源码,不仅可以得知 @Qualifier 可以使用在方法上,也可以使用在参数上:

@Repository
public class Test {
    @Bean
    public User u1() {
        return new User("zhangsan", 14);
    }

    @Bean
    public User u2() {
        return new User("lisi",15);
    }
}
    @Autowired
    public void setUser(@Qualifier("u2") User u1) {
        this.user = u1;
    }

在这里插入图片描述

@Resource

通过 name 属性来指定 对应 的 bean

    @Resource(name = "u1")
    private User user;

@Autowired 和 @Resource 的区别:
@Autowired 是 Spring 框架提供的注解,而 @Resource 是 JDK 提供的注解
@Autowired 是默认按照类型注入的,而 @Resource 是按照名称注入的,相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 的设置,根据 名称来获取 Bean

注入流程

在这里插入图片描述

只找到一个? 这种情况要么就是只有一个 bean 对象,要么就是使用了 @Primary 来指定默认的 bean 对象。

相关文章:

  • React组件化开发详解
  • 责任链模式原理详解和源码实例以及Spring AOP拦截器链的执行源码如何使用责任链模式?
  • 【Javascript Day20】
  • MariaDB10创建用户并授权
  • Git LFS介绍(Large File Storage)大文件扩展,将大文件存储在外部存储,仓库中只记录文件的元数据(大文件的指针,类似一个小的占位符文件)
  • 深入了解XML:初学者的全面指南
  • 计算机网络:应用层 —— 动态主机配置协议 DHCP
  • 基于腾讯云大模型知识引擎×DeepSeek构建八字、六爻赛博算卦娱乐应用
  • 进程控制(靠原语实现)
  • 关于房间传感器监测数据集的探索
  • 3-知识图谱-知识图谱的存储与查询
  • [DeepSeek]二、大模型
  • 元脑服务器可用于DeepSeek部署
  • Java——多态
  • 【Leetcode 每日一题】2595. 奇偶位数
  • 阿里云ECS命名规则解析与规格选型实战指南
  • MySQL中 undolog和redolog区别
  • 《跟李沐学 AI》AlexNet论文逐段精读学习心得 | PyTorch 深度学习实战
  • RabbitMQ 消息队列
  • 蓝桥杯(B组)-每日一题(1093字符逆序)
  • “乐购浦东”消费券明起发放,多个商家同期推出折扣促销活动
  • 国务院安委会对辽宁辽阳一饭店重大火灾事故查处挂牌督办
  • 美财长称关税战升级的责任在中方,外交部:关税战、贸易战没有赢家
  • 连演三场,歌剧《义勇军进行曲》在上海西岸大剧院上演
  • 加拿大驾车撞人事件遇难人数升到11人
  • 旧衣服旧纸箱不舍得扔?可能是因为“囤物障碍”