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

【JavaEE】Spring中注解的方式去获取Bean对象

【JavaEE】Spring的开发要点总结(3)

在这里插入图片描述

文章目录

  • 【JavaEE】Spring的开发要点总结(3)
    • 1. 属性注入
      • 1.1 @Autowired注解
      • 1.2 依赖查找 VS 依赖注入
      • 1.3 配合@Qualifier 筛选Bean对象
      • 1.4 属性注入的优缺点
    • 2. Setter注入
      • 2.1 @Autowired注解
      • 2.2 命名规则
      • 2.3 Setter注入的优缺点
    • 3. 构造方法注入
      • 3.1 @Autowired注解
      • 3.2 命名规则
      • 3.3 构造方法注入的优缺点
    • 4. 另一个注入可以用的注解@Resource
      • 4.1 来源不同
      • 4.2 匹配机制不同
      • 4.3 参数不同
      • 4.4 @Resource多一个匹配Bean对象名称的方案
      • 4.5 使用上的区别
    • 5. 综合练习

【JavaEE】Spring的开发要点总结(3)

在前面的代码里,我们获取Bean对象也比较麻烦:

在这里插入图片描述

本文章就是为了更方便地去获取Bean对象~

  • 对象装配
  • 也叫 对象注入

那么有没有对应的注解去实现这个功能呢?

Spring提供的三种实现方法:

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

而这种非明文获取Bean对象的过程,就是DI

  • 而之前就是DL

首先,先创建一个新的项目,这次用规范的写法(工程分层):在这里插入图片描述

  • 配置文件自己去配~

在对应的层就是对应的注解:

在这里插入图片描述

1. 属性注入

在这里插入图片描述

这是数据持久层的一个插入方法,而 这个方法理论上是要在service层去调用的

在这里插入图片描述

但是new对象的写法在Spring已经不用啦:
在这里插入图片描述

属性注入则可以更便捷获取Bean对象~

1.1 @Autowired注解

在这里插入图片描述

自动接通吧,差不多那个意思~

利用这个注解,就能有以下操作:

在这里插入图片描述

在这里插入图片描述

这就是依赖注入,DI~

不用通过代码显示查找

  • 而是在Spring中,隐式用高效的方式自动地扫描到对应的Bean对象(n. 依赖)
  • 然后赋值(v. 注入)给这个成员属性

测试一下:

在这里插入图片描述

  • new对象的方式不行,跟Bean对象是否加载存储到Spring中五无关~

也可以通过单元测试的方式去测试代码,后期更新测试开发博客文章的时候讲解~

1.2 依赖查找 VS 依赖注入

参考之前的文章:

在这里插入图片描述

在这里体现出来的一点就是,依赖查找依赖Bean的名称,而依赖注入则会自动匹配和找到Bean对象,注入到属性中

  • 不是说依赖注入没有“查找”的过程,只是依赖注入重点在于注入

DI 流程是这样的:

  1. getType,从容器中获取对象
    • 如果能拿到唯一一个,那么就直接赋值给属性变量里
    • 这个时候变量名没有要求~
    • 正如上面写的~

在这里插入图片描述

  1. 如果找到多个,则根据名称去匹配对应的Bean对象!

在这里插入图片描述

测试结果:

在这里插入图片描述

  • 确实是不同的Bean对象~
  • 也验证了 DI 使用名称去匹配~
  • 这个时候你的变量名就必须是Bean对象其中一个的名称了~
    • 否则会报找不到,不唯一…的异常

1.3 配合@Qualifier 筛选Bean对象

你不管三七二十一,就想要一个响当当的属性名:“userSuperDao”,但是没有这个名的Bean对象(现在有多个Bean)

你就可以利用这个注解:

在这里插入图片描述

1.4 属性注入的优缺点

参考链接: https://juejin.cn/post/7135235294265081887

优点:实现/使用简单

缺点:

  1. 无法注入到一个不可变的变量(final 修饰的变量)

在这里插入图片描述

原因是final的特征:

  1. 被final修饰的成员变量要在
    • 定义时直接被赋值
    • 构造方法中第一次赋值
    • 实例代码块中第一次赋值
  2. 除了成员变量外的final变量,要在第一次赋值后不能被修改
  1. 通用性问题
    • 测试困难
    • 依赖项之间的耦合
    • 运行时的验证困难
    • 依赖关系的不清楚,复杂
    • 我们这种简单地用,@Autowired注解在属性上,去注入的方式可能不适用与非IoC容器的
      • 而Setter和构造方法注入是通过调用方法的,所以没有这个问题
  2. 设计原则问题:更容易违背单一设计原则

参考官方文档:Spring | Home

 单一设计原则要求一个类应该只有一个引起改变的原因,即一个类应该只有一个主要责任。当使用属性注入时,可能会出现以下情况:
  1. 因为开销比较小,在这个类里有啥需要就写一个属性,涉及多个职责耦合
  2. 依赖关系不清楚,乱,说到底还是属性写太多,设计不单一

但是,开发就是这样,不会很完美,3这个点很难避开

  • 有时候为了速度,牺牲耦合性的情况也有
    • 比如一个页面的信息有分类的,有不同的职责
    • 但是,如果访问这个页面,要去访问那么多个接口,就有很多次“三次握手四次挥手”了
  • 实际场景实际分析!

2. Setter注入

在这里插入图片描述

顾名思义,借此模仿,就是Setter方法加对应的注解

2.1 @Autowired注解

在这里插入图片描述

这就自动在Spring中找到Bean对象,然后通过Setter注入给对应的成员变量~

  • DI,是这样的

测试:

在这里插入图片描述

2.2 命名规则

命名规则跟属性注入基本一致,你可以理解为属性注入套了层皮,就是Setter注入

正好现在我有两个UserDao的Bean对象,来演示一下:

  • 一个aaa,一个userDao

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

观察一下,再看答案:

  1. 跟方法名无关
  2. 跟属性名无关
  3. 跟方法的参数名有关
  4. 可以结合@Qualifier注解

规则:

  1. 通过参数的类型,如果只获得一个Bean对象,那么这个属性的名字是啥都OK
  2. 如果获取到多个Bean对象,则需要 通过属性名进行匹配
    • @Qualifier去筛选,就不用考虑参数名的问题~

2.3 Setter注入的优缺点

优点:

  • 通常情况下,构造Setter只去Set一两个属性,并不会构造全部的Setter方法
  1. 所以Setter注入,更符合单一设计原则,就不会像属性注入那样的广泛

  2. 通用性更好一点(相对于属性注入)

    • 属性注入如果在别的容器上,失效了,但是Setter注入暴露出一个Set方法了呀,我们可以通过Set方法去挽救,自己手动赋值个Bean对象/new一个进去~
    • 而属性注入的属性,一般是private,在别的类不能直接修改其值

这个优点很牵强 ^ _ ^

缺点:

  1. 无法注入到一个final修饰的变量
  2. Setter注入的对象可以被修改
    • 相比于属性注入,Setter方法是公开的,所以这个方法可能被多次调用并修改
      • 这样就导致注入的结果被覆盖~
      • 或者原本设置的值被注入修改~
    • 属性注入也可以,但是是private,所以只能在对应的类中修改

3. 构造方法注入

这是官方推荐的一种注入方式~

  • 虽然如此,官方写的代码,用这个的不多🤣
  • 虽然更加完美,但是写起来麻烦

在这里插入图片描述

(Spring 4.x 之后推荐的注入方式)

3.1 @Autowired注解

在这里插入图片描述

  • 在构造方法上加上个@Autowired注解~

这也是标准的写法~

不标准的写法,不加@Autowired注解不会报错:

  • 因为官方推荐,所以搞了点小特殊🤣

在这里插入图片描述

  • 这个类如果只有一个构造方法的情况下,才是可以省略的!

在这里插入图片描述

  • 空的构造方法还行,就相当于啥也不注入,至少在构造UserService3的时候可以调用这个方法

在这里插入图片描述

  • 这个方法直接是不能调用了,因为不确定调用哪个构造方法,该注入啥

加上就不会有事:

在这里插入图片描述

原理就是:

  • 框架在构造UserService的时候,会根据@Autowried去挑选构造方法,而参数的来源就是Bean对象
  • 因此构造方法就会将这些Bean对象注入到属性上

所以不能有多个@Autowired修饰的构造方法:

在这里插入图片描述

3.2 命名规则

跟Setter注入一样!

  • 只不过不能用@Qualifier注解!

在这里插入图片描述

  1. 这个类只有一个Bean对象,那么参数名无所谓
  2. 这个类有多个Bean对象,那么参数名必须要匹配对应的Bean对象的名称

在这里插入图片描述

3.3 构造方法注入的优缺点

优点:

  1. 可以注入到一个final修饰的变量
    • 因为构造方法的第一次赋值final变量是允许的
    • 但是一定要保证每个构造方法涉及到的成员,都包含所有的final变量,即保证final变量都可以被初始化
      • 一个都不能缺

在这里插入图片描述

在这里插入图片描述

运行结果没问题:

在这里插入图片描述

  1. 注入的对象不会被修改,因为构造方法只会加载一次

    • 硬要修改还是可以的,只不过不能通过构造方法
  2. 保证使用的时候,注入对象都被初始化了

  3. 通用性更好(相对其他)

    • 同Setter注入
    • 因为必须传值,因为优点3

缺点:

  • 可以传入多个属性,不太符合单一设计原则
  • 这一点是写代码方面的初心问题吧。因为硬要这么说,你完全也可以给那个别的属性构造个Setter呀
  1. 写法比较复杂
  2. 无法解决循环依赖的问题
    • a依赖b,b依赖a,就是一个“循环”
    • 得用Spring三级缓存去解决
    • 这个循环依赖后面详细讲,现在就了解一下~

常见的面试题就是三者的区别:就是把他们的使用和优缺点讲一下~

4. 另一个注入可以用的注解@Resource

这个可以直接替换@Autowired注解,用IDEA专业版的话,有些场景下,用@Autowired是会报错的~

  • 但是属于误报,运行还是可以运行(设置把报错信息忽略掉)~

在这里插入图片描述

Resource就没啥问题:

在这里插入图片描述

用法基本一致:
在这里插入图片描述

这也是个常见的面试题:@Autowired和@Resource的区别是什么?

4.1 来源不同

@Autowired来自Spring框架,而@Resource来自JavaEE规范

4.2 匹配机制不同

  • @Autowired先进行类型匹配再用名称匹配
    • 但是专业版在这个注解判断代码正确与否的时候,并不会进一步用名称去匹配
    • 所以会误报
  • @Resource先进行名称匹配再进一步用类型匹配
    • 名称对不上,也会用类型去找,有多个Bean会报错,只有一个Bean就忽略名称的问题
  • 当然误报的原因可能有很多,甚至不是单一的原因…
  • IDEA兼容性不同~

4.3 参数不同

@Autowired只有一个参数,required,而@Resource没有这个参数,但是有很多其他的参数

在这里插入图片描述

required默认为true,代表要求Bean注入一定要存在

required设置为false,代表不要求Bean一定存在,不注入即可,就不会报找不到Bean对象异常~

在这里插入图片描述

在这里插入图片描述

4.4 @Resource多一个匹配Bean对象名称的方案

在这里插入图片描述

因此,@Resource多了一个匹配名称的方案:设置name的值即可:

在这里插入图片描述

4.5 使用上的区别

@Resource不支持构造方法注入

在这里插入图片描述

5. 综合练习

补充: 无论怎么样,静态属性是无法被注入Bean的,因为静态属性的加载是在Spring之前的,即类加载的时候,是这个类通用的属性,而Bean对象是一个实例!难不成每次获取Bean对象,Spring都会注入覆盖这个值吗~

这不合理~

  • 而依赖注入发生在你获取Bean对象的时候,Spring帮你构造实例的时候,而不是你自己new和设置的时候
  • 所以在main方法中,还是要通过DL去获取Bean

要求:在Spring项目中,通过main方法获取到Controller类,在Controller类里调用Service类,在Service类中获取Dao类,在Dao类中的一个方法,用伪代码new一个User,进行返回,返回给main方法,打印user。

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

报错了,这也是常见的问题,就Test类并没有在demo目录下,而是与其并列,要把他放进目录里:

在这里插入图片描述

运行结果:

在这里插入图片描述

是不是跟之前普通java代码对IoC的理解思想差不多😀

【JavaEE】JavaEE进阶:框架的学习 - Spring的初步认识_s:103的博客-CSDN博客


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

代码链接:

  1. SpringDemo3 · 游离态/马拉圈2023年7月 - 码云 - 开源中国 (gitee.com)
  2. SpringDemo4 · 游离态/马拉圈2023年7月 - 码云 - 开源中国 (gitee.com)

用注解的方式去获取Bean对象,是不是很方便🤭


相关文章:

【JavaEE】Spring中注解的方式去获取Bean对象

【JavaEE】Spring的开发要点总结(3) 文章目录 【JavaEE】Spring的开发要点总结(3)1. 属性注入1.1 Autowired注解1.2 依赖查找 VS 依赖注入1.3 配合Qualifier 筛选Bean对象1.4 属性注入的优缺点 2. Setter注入2.1 Autowired注解2.2…...

【基于CentOS 7 的iscsi服务】

目录 一、概述 1.简述 2.作用 3. iscsi 4.相关名称 二、使用步骤 - 构建iscsi服务 1.使用targetcli工具进入到iscsi服务器端管理界面 2.实现步骤 2.1 服务器端 2.2 客户端 2.2.1 安装软件 2.2.2 在认证文件中生成iqn编号 2.2.3 开启客户端服务 2.2.4 查找可用的i…...

解决安装依赖时报错:npm ERR! code ERESOLVE

系列文章目录 文章目录 系列文章目录前言一、错误原因二、解决方法三、注意事项总结 前言 在使用 npm 安装项目依赖时,有时会遇到错误信息 “npm ERR! code ERESOLVE”,该错误通常发生在依赖版本冲突或者依赖解析问题时。本文将详细介绍出现这个错误的原…...

98、简述Kafka的rebalance机制

简述Kafka的rebalance机制 consumer group中的消费者与topic下的partion重新匹配的过程 何时会产生rebalance: consumer group中的成员个数发生变化consumer 消费超时group订阅的topic个数发生变化group订阅的topic的分区数发生变化 coordinator: 通常是partition的leader节…...

【人工智能】监督学习、分类问题、决策树、信息增益

文章目录 Decision Trees 决策树建立决策树分类模型的流程如何建立决策树?决策树学习表达能力决策树学习信息论在决策树学习中的应用特征选择准则一:信息增益举例结论不足回到餐厅的例子从12个例子中学到的决策树:Decision Trees 决策树 什么是决策树 —— 基本概念 非叶节…...

Pytorch迁移学习使用Resnet50进行模型训练预测猫狗二分类

目录 1.ResNet残差网络 1.1 ResNet定义 1.2 ResNet 几种网络配置 1.3 ResNet50网络结构 1.3.1 前几层卷积和池化 1.3.2 残差块:构建深度残差网络 1.3.3 ResNet主体:堆叠多个残差块 1.4 迁移学习猫狗二分类实战 1.4.1 迁移学习 1.4.2 模型训练 1.…...

HTML与XHTML的不同和各自特点

HTML和XHTML都是用于创建Web页面的标记语言。HTML是一种被广泛使用的标记语言,而XHTML是HTML的严格规范化版本。在本文中,我们将探讨HTML与XHTML之间的不同之处,以及它们各自的特点。 HTML与XHTML的不同之处 HTML和XHTML之间最大的不同在于它…...

微服务如何治理

微服务远程调用可能有如下问题: 注册中心宕机; 服务提供者B有节点宕机; 服务消费者A和注册中心之间的网络不通; 服务提供者B和注册中心之间的网络不通; 服务消费者A和服务提供者B之间的网络不通; 服务提供者…...

一本通1919:【02NOIP普及组】选数

这道题感觉很好玩。 正文: 先放题目: 信息学奥赛一本通(C版)在线评测系统 (ssoier.cn)http://ybt.ssoier.cn:8088/problem_show.php?pid1919 描述 已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k&#…...

Kubernetes 集群管理和编排

文章目录 总纲第一章:引入 Kubernetes什么是容器编排和管理?容器编排和管理的重要性Kubernetes作为容器编排和管理解决方案 Kubernetes 的背景和发展起源和发展历程Kubernetes 项目的目标和动机 Kubernetes 的作用和优势作用优势 Kubernetes 的特点和核心…...

DDS协议--[第六章][Discovery]

DDS协议–Discovery 文章目录 DDS协议--Discovery侦听通告DDS提供发现协议参与者发现阶段(PDP)端点发现阶段(EDP)Fast DDS提供如下四种发现机制:简单发现机制简单发现机制步骤:侦听 侦听定位器用于接收DomainParticipant上的传入流量,是DDS发现机制和数据传输机制的关键…...

如何设置iptables,让网络流量转发给内部容器mysql

1.创建一个mysql ,无法外部访问 docker run -d --name mysql_container -e MYSQL_ROOT_PASSWORDliuyunshengsir -v /path/to/mysql_data:/var/lib/mysql mysql2.设置规则外部直接可访问 要使用 iptables 将网络流量转发给内部容器中的 MySQL 服务,你可…...

数字IC实践项目(7)—CNN加速器的设计和实现(付费项目)

数字IC实践项目(7)—基于Verilog的CNN加速器(付费项目) 写在前面的话项目整体框图神经网络框图完整电路框图 项目简介和学习目的软件环境要求 资源占用&板载功耗总结 写在前面的话 项目介绍: 卷积神经网络硬件加速…...

基于深度学习的高精度80类动物目标检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要:基于深度学习的高精度80类动物目标检测识别系统可用于日常生活中或野外来检测与定位80类动物目标,利用深度学习算法可实现图片、视频、摄像头等方式的80类动物目标检测识别,另外支持结果可视化与图片或视频检测结果的导出。本系统采用YO…...

海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储

文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/131679108 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…...

【NCNN】NCNN中Mat与CV中Mat的使用区别及相互转换方法

目录 相同点与不同点cv::Mat转ncnn::Matcv::Mat CV_8UC3 -> ncnn::Mat 3 channel swap RGB/BGRcv::Mat CV_8UC3 -> ncnn::Mat 1 channel do RGB2GRAY/BGR2GRAYcv::Mat CV_8UC1 -> ncnn::Mat 1 channel ncnn::Mat转cv::Mancnn::Mat 3 channel -> cv::Mat CV_8UC3 …...

Android 13 设置自动进入wifi adb模式

Android 13 设置自动进入wifi adb模式 文章目录 Android 13 设置自动进入wifi adb模式一、前言:二、解决Android 13 wifi adb每次重启自动重置问题方法1、分析系统中每次重置wifi adb属性的代码2、在开机广播里面进行设置wifi adb 相关属性(1&#xff09…...

(笔记)插入排序

插入排序 插入排序是一种简单且常见的排序算法,它通过重复将一个元素插入到已经排好序的一组元素中,来达到排序的目的。在插入排序算法中,将待排序序列分为已排序和未排序两个部分。初始时,已排序部分只包含一个记录,…...

结构型模式 - 组合模式

概述 对于这个图片肯定会非常熟悉,上图我们可以看做是一个文件系统,对于这样的结构我们称之为树形结构。在树形结构中可以通过调用某个方法来遍历整个树,当我们找到某个叶子节点后,就可以对叶子节点进行相关的操作。可以将这颗树理…...

EDM营销过时了?不,这才是跨境电商成功的最佳工具

根据最近的一项研究,电子邮件仍然是最具说服力的营销工具和沟通形式之一。虽然即时通讯等其他渠道正在扎根,但电子邮件仍然是影响最深远的商业交流形式。到2023年,每天发送和接收的电子邮件总数可能会超过333亿封。所以,如果您希望…...

Ubuntu 下同名文件替换后编译链接到旧内容的现象分析

Ubuntu 下同名文件替换后编译链接到旧内容的现象分析 在使用 Ubuntu 操作系统编译程序时,常常会遇到一个问题:当我们替换同名文件内容后,若不改变当前命令行目录,再次编译时,系统实际编译的仍是被覆盖前的旧文件内容。…...

三分钟打通Stable Diffusion提示词(附实战手册)

文章目录 一、提示词的本质是"思维翻译器"避坑指南1:三大常见翻车现场 二、结构化提示词公式(抄作业版)实战案例:生成赛博朋克猫咪 三、进阶玩家的秘密武器1. 权重控制大法2. 风格融合黑科技3. 时间轴控制 四、避不开的…...

【SpringCache 提供的一套基于注解的缓存抽象机制】

Spring 缓存(Spring Cache)是 Spring 提供的一套基于注解的缓存抽象机制,常用于提升系统性能、减少重复查询数据库或接口调用。 ✅ 一、基本原理 Spring Cache 通过对方法的返回结果进行缓存,后续相同参数的调用将直接从缓存中读…...

基于FPGA的二叉决策树cart算法verilog实现,训练环节采用MATLAB仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) MATLAB训练结果 上述决策树判决条件&#xff1a; 分类的决策树1 if x21<17191.5 then node 2 elseif x21>17191…...

湖北理元理律师事务所:债务优化中的生活保障实践

在债务压力与生活质量失衡的普遍困境中&#xff0c;法律服务的价值不仅在于解决债务问题&#xff0c;更在于帮助债务人重建生活秩序。湖北理元理律师事务所通过其债务优化服务&#xff0c;探索出一条“法律生活”的双轨路径。 债务规划的核心矛盾&#xff1a;还款能力与生存需…...

《软件工程》第 12 章 - 软件测试

软件测试是确保软件质量的关键环节&#xff0c;它通过执行程序来发现错误&#xff0c;验证软件是否满足需求。本章将依据目录&#xff0c;结合 Java 代码示例、可视化图表&#xff0c;深入讲解软件测试的概念、过程、方法及实践。 12.1 软件测试的概念 12.1.1 软件测试的任务 …...

计算机网络-MPLS VPN应用场景与组网

上一篇文章我们通过一个基础实验实现了企业分支间的MPLS VPN互联&#xff0c;如果还不理解的可以多看几遍前面的文章或者多敲下实验。今天来学习几种常见的MPLS VPN应用场景与这些场景下MPLS VPN的部署方法。 一、MPLS VPN典型应用 目前&#xff0c;MPLS VPN的主要应用包括企…...

静态资源js,css免费CDN服务比较

静态资源js,css免费CDN服务比较 分析的 CDN 服务列表&#xff1a; BootCDN (https://cdn.bootcdn.net/ajax/libs)jsDelivr (主域名) (https://cdn.jsdelivr.net/npm)jsDelivr (Gcore 镜像) (https://gcore.jsdelivr.net/npm)UNPKG (https://unpkg.com)ESM (https://esm.sh)By…...

Pydantic 学习与使用

Pydantic 学习与使用 在 Fastapi 的 Web 开发中的数据验证通常都是在使用 Pydantic 来进行数据的校验&#xff0c;本文将对 Pydantic 的使用方法做记录与学习。 **简介&#xff1a;**Pydantic 是一个在 Python 中用于数据验证和解析的第三方库&#xff0c;它现在是 Python 使…...

Keepalived 配置 VIP 的核心步骤

Keepalived 配置 VIP 的核心步骤主要涉及安装软件、主备节点配置及服务管理。以下是具体操作指南: 一、安装 Keepalived ‌Ubuntu/Debian 系统‌ sudo apt update sudo apt install keepalived ‌CentOS/RHEL 系统‌ sudo yum install keepalived 注:需确保已配置 EPE…...