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

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 对象。


http://www.kler.cn/a/554325.html

相关文章:

  • 【AB-01】 AUTOSAR Builder软件安装
  • Debezium 报错:“The db history topic is missing” 的处理方法
  • 知识库-知识收藏、取消收藏接口
  • Hutool - DB:基于 ActiveRecord 思想的 JDBC 封装数据操作工具
  • 爱普生 SG-8101CE 可编程晶振在笔记本电脑的应用
  • LabVIEW开发中的电机控制与相机像素差
  • 智能检测摄像头模块在客流统计中的应用
  • Mongoose 搜索注入漏洞分析
  • Elasticsearch7.1.1 配置密码和SSL证书
  • Kafka中commitAsync的使用与实例解析
  • 前端利器:DateUtils 日期时间工具深度剖析
  • 如何在 PDF 文件中嵌入自定义数据
  • 基于大数据的国内高校排名可视化分析及推荐系统
  • 【大语言模型_3】ollama本地加载deepseek模型后回答混乱问题解决
  • 电容五大基本作用详解
  • 【Leetcode 每日一题】2080. 区间内查询数字的频率
  • 【Dubbo+Zookeeper】——SpringBoot+Dubbo+Zookeeper知识整合
  • VSCode AI提效工具,通义灵码前端开发体验
  • GUI编程(window系统→Linux系统)
  • 【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter18-动画与 Canvas 图形