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

news2024/11/27 1:27:36

【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对象,是不是很方便🤭


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/780413.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【漏洞复现】​金蝶云星空管理中心反序列化命令执行漏洞(RCE)

文章目录 前言声明一、系统简介二、漏洞描述三、影响版本四、漏洞复现五、整改意见 前言 ​金蝶云星空管理中心存在反序列化命令执行,攻击者可通过该漏洞获取敏感信息,进而接管服务器。 声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文…

Mybatis-plus 配置自定义sql(.xml文件)查询语句的步骤

这是使用Mybatis-plus 的自动生成实体类代码生成.xml文件, 所以他会在java目录下,不在resources目录下 如果在java目录下的xml文件,需要分别配置application.yml和pom.xml文件 application.yml 文件进行以下配置: mybatis-plus…

视频增强技术-对比度增强

在图像处理中,由于获取的图像质量不好,需要通过对比度增强来提升图片质量,主要解决的是由于图像灰度级范围较小造成的对比度较低的问题,作用是使图像的灰度级范围放大,从而让图像更加清晰。主要对比度增强方法包括线性…

CentOS 7.9 安装 mydumper(RPM方式)

链接:https://pan.baidu.com/s/1sGhtiKPOmJw1xj0zv-djkA?pwdtaoz 码:taoz 开始正文啦: rpm -ivh mydumper-0.14.5-3-zstd.el7.x86_64.rpm 问题如下: 解决: yum -y install epel-release yum install -y libzstd …

分布式消息流处理平台kafka(一)-kafka单机、集群环境搭建流程及使用入门

1.kafka概述 1.1 kafka的前世今生 kafka最初是LinkedIn的一个内部基础设施系统。最初开发的起因是,LinkedIn虽然有了数据库和其他系统可以用来存储数据,但是缺乏一个可以帮助处理持续数据流的组件。 所以在设计理念上,开发者不想只是开发一…

通过 EXPLAIN 分析 SQL 的执行计划

通过 EXPLAIN 分析 SQL 的执行计划 EXPLAIN SELECTleave_station_area_id,ROUND( ( SUM( station_dist ) / 1000 ) / ( SUM( station_travel_time ) / 60 ), 2 ) evnPeakAvgSpeedFROMV3_SHIFT_ANALYSISWHERESTAT_DATE DATE_SUB( CURRENT_DATE, INTERVAL 1 DAY )AND LEAVE_STA…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 20 日论文合集)

文章目录 一、分割|语义相关(11篇)1.1 Two Approaches to Supervised Image Segmentation1.2 Boundary-Refined Prototype Generation: A General End-to-End Paradigm for Semi-Supervised Semantic Segmentation1.3 Source-Free Domain Adaptive Fundus Image Segmentation w…

STL:vector的使用(初识迭代器迭代器失效)

vector也是动态类型的顺序表&#xff0c;可以存储任意类型的元素 string是动态类型顺序表&#xff0c;只能存储char vector< char >字符数组 string 字符串字符串结尾有\0&#xff0c;而vector是一个泛型类型&#xff0c;不能因为字符串需要\0&#xff0c;而对每个类型最…

分布式光伏并网防孤岛保护装置AM5SE-IS

分布式光伏并网防孤岛保护装置AM5SE-IS 应用场景 防孤岛原理&#xff1a;防孤岛保护装置检测到并网点有逆功率、频率突变、 等异常数据时&#xff0c;即发生孤岛现象时&#xff0c;装置可配合断路器快速切除并网点&#xff0c;使本站与电网侧快速脱离&#xff0c;保证整个电站…

jmeter随记3:常用jmeter功能(附带场景)

常用jmeter功能&#xff08;附带场景&#xff09; 一、jmeter其他特性1、请求的接口有多个 且 域名相同2、 jmeter支持统一管理参数的设置a、创建HTTP Header Managerb、用户定义参数c、csv数据文件设置 3、接口a的返回值作为 接口b的入参a、 json提取器b、 正则表达式 4、if c…

【密码学】二、古典密码

古典密码 1.置换密码1.1列置换密码1.2周期置换密码 2.代换密码2.1单表代换密码2.1.1凯撒密码2.1.2仿射密码 2.2多表代换密码2.2.1维吉尼亚密码2.2.2普莱费尔密码 3.轮转密码3.1恩尼格玛密码机Enigma3.1.1Enigma加密3.1.1Enigma解密 4.古典密码的分类5.古典密码的统计分析5.1单表…

【事业单位-语言理解1】中心理解02

【事业单位-语言理解1】中心理解02 1.中心理解1.1 并列关系1.2 主题词1.3程度词&#xff0c;表示强调 二、标题填入题&#xff08;优先考虑主题词&#xff09;三、词句理解题 1.中心理解 解题思路 1.1 并列关系 涉及时间顺序 注意选项不要逻辑不当 并列关系的时候&…

07统计模型练习

使用SPSS进行分析求解 第一题 下表1.1是中国1994-2016年国内旅游总花费Y、国内生产总值X1、铁路里程X2和公路里程X3的数据,请据此分析如下问题: (1)就建立简单线性回归模型,分别分析中国国内旅游总花费与国内生产总值、铁路里程和公路里程数据的数量关系。 (2)对建立的回归模型…

K8S下如何搭建eureka集群

背景 传统应用上云&#xff0c;基于传统应用需要考虑上云的方案和改造成本&#xff0c;这也是传统应用上云过程中的难点&#xff0c;本篇介绍3台eureka搭建的方案。 方案一 此方案借助了K8S中Service的一些功能。 这种方案是传统方案的简单迁移版本&#xff0c;比较易于理解…

前端 | ( 十一)CSS3简介及基本语法(上) | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 系列笔记&#xff1a; 【HTML4】&#xff08;一&#xff09;前端简介【HTML4】&#xff08;二&#xff09;各种各样的常用标签【HTML4】&#xff08;三&#xff09;表单及HTML4收尾…

一键批量JSON标注转PNG图片工具V1.1,支持labelme快捷矩形、圆以及轮廓标注

上次发布了一个批量将labelme标注的json文件转换为png文件工具&#xff0c;但是当时只是想着自己用的&#xff0c;功能相当简单&#xff0c;一些网友使用之后跟我反馈这玩意真”垃圾“&#xff0c;很多情况都没有进行设想&#xff0c;所以在功能上很欠缺。由于小陶这几天在外地…

Rust vs Go:常用语法对比(三)

题图来自When to use Rust and when to use Go[1] 41. Reverse a string 反转字符串 package mainimport "fmt"func Reverse(s string) string { runes : []rune(s) for i, j : 0, len(runes)-1; i < j; i, j i1, j-1 { runes[i], runes[j] runes[j], runes[i]…

高等数学❤️第一章~第三节~极限❤️连续函数的运算与初等函数的连续性~连续函数的运算

【精讲】高等数学中连续函数的运算 博主&#xff1a;命运之光的主页 专栏&#xff1a;高等数学 目录 【精讲】高等数学中连续函数的运算 导言 一、连续函数的运算规则 二、连续函数的性质 必需记忆知识点 例题&#xff08;用于熟悉高等数学中连续函数的运算&#xff09;…

【Java基础教程】(四十二)多线程篇 · 上:多进程与多线程、并发与并行的关系,多线程的实现方式、线程流转状态、常用操作方法解析~

Java基础教程之多线程 上 &#x1f539;本节学习目标1️⃣ 线程与进程&#x1f50d;关于多进程、多线程、并发与并行之间的概念关系&#xff1f; 2️⃣ 多线程实现2.1 继承 Thread 类2.2 实现 Runnable 接口2.3 多线程两种实现方式的区别2.4 利用 Callable 接口实现多线程2.5 …

Windows Server 2012 搭建网关服务器并端口转发

需求 使用 Windows server 作为Hyper-V 虚拟出许多虚拟机&#xff0c;基本上都分配了内网地址&#xff0c;现在需要这些虚拟机访问外网&#xff0c;或者外网直接访问这些虚拟机&#xff0c;必须配置一个网关服务器。我决定直接使用 Windows 的远程访问中的 NAT 服务来完成。 …