SpringDI
- 软件开发
- 2025-08-25 18:09:03

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