Spring注解之依赖注入@Autowired和@Resource
Spring常见的DI方式
字段注入(Field Injection)
在字段上使用@Autowired/Resource注解
字段注入是日常开发中使用最多的一种注入方式,它的实现代码如下:
@Autowired
private UserService userService;
优点
属性注入最大的优点就是实现简单、使用简单,只需要给变量上添加一个注解 @Autowired,就可以在不 new 对象的情况下,直接获得注入的对象了(这就是 DI 的功能和魅力所在),所以它的优点就是使用简单。
缺点
属性注入虽然使用简单,但也存在着很多问题,甚至编译器 Idea 都会提醒 “不建议使用此注入方式”
1、功能性问题:无法注入一个不可变的对象(final 修饰的对象)
2、通用性问题:只能适应于 IoC 容器
3、设计原则问题:更容易违背单一设计原则
Setter注入(Setter Injection)
调用Setter的方法注入依赖
实现代码如下:
// Setter 注入
private UserService userService; @Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
从上面代码可以看出,Setter 注入比属性注入要麻烦很多。
要说 Setter 注入有什么优点的话,那么首当其冲的就是它完全符合单一职责的设计原则,因为每一个 Setter 只针对一个对象。
但它的缺点也很明显,它的缺点主要体现在以下 2 点:1、不能注入不可变对象(final 修饰的对象);
2、注入的对象可被修改。- Setter 注入提供了 setXXX 的方法,意味着你可以在任何时候、在任何地方,通过调用 setXXX 的方法来改变注入对象,所以 Setter 注入的问题是,被注入的对象可能随时被修改。
构造器注入(Constructor Injection)
利用构造方法的参数注入依赖
构造方法注入是 Spring 官方从 4.x 之后推荐的注入方式,它的实现代码如下:
// 构造方法注入
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
如果当前的类中只有一个构造方法,那么 @Autowired 也可以省略
优点
构造方法注入相比于前两种注入方法,它可以注入不可变对象,并且它只会执行一次,也不存在像 Setter 注入那样,被注入的对象随时被修改的情况,它的优点有以下 4 个:
1、可注入不可变对象(final 修饰的对象)
2、注入对象不会被修改- 构造方法注入不会像 Setter 注入那样,构造方法在对象创建时只会执行一次,因此它不存在注入对象被随时(调用)修改的情况。
3、注入对象会被完全初始化
- 因为依赖对象是在构造方法中执行的,而构造方法是在对象创建之初执行的,因此被注入的对象在使用之前,会被完全初始化,这也是构造方法注入的优点之一。
4、通用性更好
- 构造方法和属性注入不同,构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架,构造方法注入的代码都是通用的,所以它的通用性更好。
常用注入方式总结
依赖注入的常见实现方式有 3 种:属性注入、Setter 注入和构造方法注入。
- 其中属性注入的写法最简单,所以日常项目中使用的频率最高,但它的通用性不好;
- 而 Spring 官方推荐的是构造方法注入,它可以注入不可变对象,其通用性也更好;
- 如果是注入可变对象,那么可以考虑使用 Setter 注入。
三种注入方式的优缺点
- 构造器注入:强依赖性(即必须使用此依赖),不变性(各依赖不会经常变动)
- Setter注入:可选(没有此依赖也可以工作),可变(依赖会经常变动)
- Field注入:大多数情况下尽量少使用字段注入,一定要使用的话, @Resource相对@Autowired对IoC容器的耦合更低
@Autowired 和 @Resource 有什么区别
@Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同。
来源不同:来自不同的“父类”,@Autowired是Spring提供的,@Resource是JSR-250提供的
依赖查找顺序不同
依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。
@Autowired 查找顺序: 是先根据类型(byType)查找,如果存在多个(Bean)再根据名称(byName)进行查找
@Resource 查找顺序: 是先根据名称(byName)查找,如果(根据名称)查找不到,再根据类型(byType)进行查找支持的参数不同:@Autowired 只支持设置一个 required 的参数,而 @Resource 支持 7 个参数
适用对象不同:@Autowired可以对构造器、方法、参数、字段使用,@Resource只能对方法、字段使用
依赖注入的支持不同:@Autowired 支持属性注入、构造方法注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入
为什么IDEA只对@Autowired警告
在使用IDEA开发的时候有没有注意到过一个提示,在字段上使用Spring的依赖注入注解@Autowired后会出现如下警告:
Field injection is not recommended (字段注入是不被推荐的)
但是使用@Resource却不会出现此提示
@Autowired是Spring提供的,它是特定IoC提供的特定注解,这就导致了应用与框架的强绑定,一旦换用了其他的IoC框架,是不能够支持注入的。
而 @Resource是JSR-250提供的,它是Java标准,我们使用的IoC容器应当去兼容它,这样即使更换容器,也可以正常工作。
用@RequiredArgsConstructor代替@Autowired
我们都知道注入一个bean有三种方式(set注入, 构造器注入, 注解注入),spring推荐我们使用构造器的方式注入Bean。
@RequiredArgsConstructor注解,生成带有必需参数的构造函数。必需的参数是最终字段和具有约束的字段,例如@NonNull。
这个注解是基于lombok的使用时必须导入lombok包。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
同时注意几点:
声明的变量必须为final
根据构造器注入的,相当于当容器调用带有一组参数的类构造函数时,基于构造函数的 DI 就完成了,其中每个参数代表一个对其他类的依赖。基于构造方法为属性赋值,容器通过调用类的构造方法将其进行依赖注入。
当我们需要注入Bean的时候可以直接在类上添加@RequiredArgsConstructor注解使用,代替了Autowrited注解。
@RequiredArgsConstructor
@RestController
@RequestMapping("/test")
public class TestController {
private final TestService testService;
private final UserService userService;
}
Spring注解之依赖注入@Autowired和@Resource的更多相关文章
- 07 Spring框架 依赖注入(四)基于注解的依赖注入
前面几节我们都在使用xml进行依赖的注入,但是在实际的开发中我们往往偏爱于使用注解进行依赖注入,因为这样更符合我们人的思维,并且更加快捷,本节就来讲述Spring基于注解的依赖注入: 信息注入注解 @ ...
- Spring下的@Inject、@Autowired、@Resource注解区别(转)
1.@Inject javax.inject JSR330 (Dependency Injection for Java) 这是JSR330中的规范,通过AutowiredAnnotationBean ...
- Spring:基于注解的依赖注入的使用
1.什么是pojo?什么是bean? 首先,在之前几篇Spring的介绍文章当中,自己都提到了一个名词叫做POJO类,但是在回顾Spring的注解的使用的时候,去形容java当中的对象还有一个名词是叫 ...
- Spring Boot2(007):关于Spring beans、依赖注入 和 @SpringBootApplication 注解
一.关于Spring beans 和 依赖注入(Dependency Injection) spring boot 和 Spring 全家桶无缝衔接,开发过程中可以很轻松地使用 Spring 全家桶的 ...
- spring 四种依赖注入方式以及注解注入方式
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...
- Spring-Context的注解实现依赖注入功能
使用Spring-Context的注解实现依赖注入功能. Demo要点: 本例子中主要使用Annotation功能来实现对MoviceService的注入.我们将Cinema.java的头部标注为@C ...
- spring六种种依赖注入方式
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...
- JavaEE开发之Spring中的依赖注入与AOP
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework的依赖注入和控制反转
Dependency Injection and Inversion of Control 1.概述: 1.1相关概念 bean:由IoC容器所管理的对象,也即各个类实例化所得对象都叫做bean 控制 ...
随机推荐
- 如何加速C++文件的编译速度?
一.为什么慢? 重要的一个原因是C++的基本 头文件-源文件的编译模型: 每个源文件为一个编译单元 头文件数量多,可能会包含上百甚至上千个头文件 存在重复解析,每个编译单元中,这些头文件都要从硬盘里读 ...
- angular 获取DOM元素 多种方式
第一种方式 ---ViewChild <div #box>我是div----添加在html页面中</div> @ViewChild('box') box: ElementRef ...
- java学习之旅(day.17)
GUI编程 GUI:图形用户界面编程 GUI快淘汰了 GUI的核心技术:Swing . AWT 这是类 做一个场景页面涉及的组件 窗口.弹窗.面板.文本框.列表框.按钮.图片.监听事件.鼠标.键盘.破 ...
- java netty 实现 websocket 服务端和客户端双向通信 实现心跳和断线重连
java netty 实现 websocket 服务端和客户端双向通信 实现心跳和断线重连 maven依赖 <dependency> <groupId>io.netty< ...
- docker之企业级镜像仓库Harbor
Harbor概述 Habor是由VMWare公司开源的容器镜像仓库.事实上,Habor是在Docker Registry上进行了相应的 企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管 ...
- containerd 源码分析:启动注册流程
0. 前言 containerd 是一个行业标准的容器运行时,其强调简单性.健壮性和可移植性.本文将从 containerd 的代码结构入手,查看 containerd 的启动注册流程. 1. 启动注 ...
- springboot 整合 recketMQ 详细步骤
前提 RocketMQ的部署环境可用 1 依赖包 <dependency> <groupId>org.apache.rocketmq</groupId> <a ...
- ObjectArx 创建一个自定义实体项目步骤
我使用的环境是cad2018+objectarx2018+vs2015+win10.先要安装desk向导程序,用向导创建项目对于初学者来说是很方便的,然后在配置程序编译链接的环境,最后就可以写一个项目 ...
- 经验分享之会员 SaaS 系统
经验分享之会员 SaaS 系统 一.前言 2018年,这是不平凡的一年:互联网行业的中台战略.会员经济等模式如火如荼,同时也逐渐地走入我们公司每个人的视野.在南海集团的战略规划背景下,当时我所在的公司 ...
- 基于docker一键化部署LNMP环境
cd / && wget https://files.cnblogs.com/files/superlinux/install_lnmp.sh && bash inst ...