Spring 依赖注入(Dependency Injection)

先说结论: 实际开发时尽量选择 构造器注入 而不是 字段注入。 设值注入 和 方法注入 适用的场景较少,较特殊。

原因:

● 官方推荐使用!

● 代码更简洁:配合 Lombok 的 @RequiredArgsConstructor,可以自动生成包含所有 final 字段的构造函数。

● 更安全:构造器注入确保所有必需的依赖在对象创建时就已经注入,避免了在运行时忘记注入某个依赖导致 NullPointerException 的问题。

● 更易于测试:使用构造器注入时,可以直接通过构造器传递依赖进行单元测试,而不需要模拟框架的注入机制。
至于 @Resource它是 Java 的 javax.annotation.Resource 注解,个人建议在Spring项目中就不要用了。

两者区别如下:

@Autowired

● Spring 提供的注解:@Autowired 是 Spring 容器提供的注解,专门用于依赖注入。

● 默认按类型注入:@Autowired 默认按照类型(type)进行注入。

● 可指定按名称注入:可以通过 @Qualifier 注解指定按名称注入。

@Resource

● J2EE 标准注解:@Resource 是 J2EE 标准的一部分,通常用于 EJB 和其他 J2EE 资源的注入。

● 默认按名称注入:@Resource 默认按照名称(name)进行注入,如果找不到匹配的名称,则按类型(type)注入。

● 不需要 @Qualifier:@Resource 可以通过 name 属性指定名称,而不需要额外的 @Qualifier 注解。

一、构造器注入(Constructor Injection)

构造器注入通过类的构造方法来传递依赖。

举个例子:

java 复制代码
@RestController
@RequiredArgsConstructor
public class WarningTaskController {
    // 注意使用 final 标记不可变
    private final WarningTaskService taskService;
    // 多个依赖可以
}

二、设值注入(Setter Injection)

设值注入通过 setter 方法来注入依赖。

举个例子:

使用 Spring Security ,默认内存用户认证的信息可以配置spring.security.user.name=customUserName就是通过 Setter 注入。源码如下:

java 复制代码
@ConfigurationProperties(prefix = "spring.security")
public class SecurityProperties {
    // 省略一些非必要的代码
	
	private final User user = new User();

	public User getUser() {
		return this.user;
	}


	public static class User {

		private String name = "user";
		private String password = UUID.randomUUID().toString();
		private List<String> roles = new ArrayList<>();

		private boolean passwordGenerated = true;

		public String getName() {
			return this.name;
		}

		public void setName(String name) {
			this.name = name;
		}

		// 省略其他 getter/setter
	}

}

三、字段注入(Field Injection)

字段注入直接通过字段来注入依赖。

举个例子:

java 复制代码
@RestController
public class WarningTaskController {

    // 不推荐使用
    // 如果依赖非常多,代码会很臃肿
    @Autowired
    private final WarningTaskService taskService;

}

四、方法注入(Method Injection)

方法注入通过方法参数来注入依赖。

举个例子:

java 复制代码
@RestController
public class WarningTaskController {
    private WarningTaskService taskService;

    // 不推荐 如果对象是可变的
    @Autowired
    public void configure(WarningTaskService taskService) {
        this.taskService = taskService;
    }

    // 其他业务逻辑...
}
相关推荐
zy happy13 分钟前
VMware虚拟机添加新的硬盘
java·linux·jvm·docker
AI人工智能+电脑小能手30 分钟前
【大白话说Java面试题 第192题】【08_Kafka篇】第8题:死信队列是什么?延时队列是什么?
java·kafka·消息队列·死信队列·延时队列
meng半颗糖31 分钟前
3.Java流程控制语句
java·开发语言·intellij-idea
大模型码小白1 小时前
企业级检索增强后端集成:Java 服务如何管理知识库版本
java·服务器·开发语言·人工智能·python·microsoft
用户6169182299931 小时前
记录一次死锁检测
java
jvmind_dev1 小时前
1c1g 容器莫名 OOM Killed?排查 Metaspace 持续增长与脚本引擎的坑
java·后端
AI多Agent协作实战派1 小时前
AI多Agent协作系统实战(二十二):从6列到12列——任务监控报告的进化之路
java·人工智能·uni-app·bug
用户3126874877201 小时前
@Transactional 注了等于没用?Spring 事务失效的 7 种场景,你踩过几个
java
千桐科技1 小时前
DataX 执行引擎正式加入:qData 开源版 v1.6.0 新增 Quartz + DataX 轻量运行模式!
java·大数据·开源·数据治理·数据中台·qdata
Irene19912 小时前
Oracle PL/SQL Developer 版本差异(11g、14)实战总结
java·开发语言