Spring 依赖注入

177 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

IoC 和 DI 是 Spring 中最重要的两个概念,其中 IoC(Inversion of Control)为控制反转的思想,而 DI(Dependency Injection)依赖注入为其(IoC)具体实现。

简介

在Spring 中实现依赖注入的常见方式有三种:

  1. 属性注入
  2. Setter 注入
  3. 构造方法注入

属性输入

常用方法,用注解 @Autowired 或者 @Resource 实现

代码示例

public class PorpertyBasicsService {
    @Autowired
    PropertyBasicsDao propertyBasicsDao;
    @Resource
    PropertyBasicsMapper basicsMapper;
    
   }

优点

实现简单、使用简单,只需要给变量上添加注解,就可以在不 new 对象的情况下直接获得注入的对象。

缺点

  1. 无法注入一个 final 对象 - 功能性问题
  2. 只能适用于 IoC 容器 - 通用性问题
  3. 容易违背单一设计原则 - 设计原则问题

功能性问题

在 Java 中 final 对象(不可变)要么直接赋值,要么在构造方法中赋值,所以当使用属性注入 final 对象时,它不符合 Java 中 final 的使用规范,所以就不能注入成功了。

ps:如果要注入一个不可变对象,使用构造方法注入就行

通用性问题

使用属性注入的方式只适用于 IoC 框架(容器) ,如果将属性注入的代码移植到其他非 IoC 的框架中,那么代码就无效了,所以属性注入的通用性不是很好。

设计原则问题

注入实现越简单,那么滥用它的概率也越大,所以出现违背单一职责原则的概率也越大

Setter 注入

代码示例

@RestController
public class UserController {
    // Setter 注入
    private UserService userService;
​
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
​
    @RequestMapping("/add")
    public UserInfo add(UserInfo userinfo) {
        return userService.add(userinfo);
    }
}

优点

完全符合单一职责的设计原则,每一个Setter只针对一个对象。

缺点

  1. 不能注入 final 对象
  2. 注入的对象可以被修改

第一点不能注入final对象和上面 一个问题差不多,final 对象会报错

第二点就是任何地方都可以调用他的 set 方法来改变注入对象,意味被注入的对象随时会被修改

构造方法注入

代码示例

@RestController
public class UserController {
    // 构造方法 注入
    private UserService userService;
​
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
​
    @RequestMapping("/add")
    public UserInfo add(UserInfo userinfo) {
        return userService.add(userinfo);
    }
}

如果当前的类中只有一个构造方法,那么@Autowired 也可以省略。

使用 lombok 的 @AllArgsConstructor 注解 可以免去构造方法

优点

可以注入 final 对象

@Service
@AllArgsConstructor
public class PropertyBasicsServiceImpl{
    private PropertyBasicsMapper propertyBasicsMapper;
}

注入对象不会被修改

构造方法在对象创建时只会执行一次,因此它不存在注入对象被随时(调用)修改的情况。

完全初始化

因为依赖对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,会被完全初始化,这也是构造方法注入的优点之一。

通用性更好

构造方法和属性注入不同,构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架,构造方法注入的代码都是通用的,所以它的通用性更好。