4.Spring IoCDI

news2025/6/15 17:14:34

文章目录

  • 1.Ioc - 控制反转(解耦)
    • 1.1传统开发
    • 1.2批量生产车轮(修改代码) - 传统方式,繁琐
    • 1.3解耦
      • 1.3.1使用Ioc方法后
      • 1.3.2添加变量颜色 只需要修改Tire即可
    • 1.4Bean的存储
      • 1.4.1@Controller(控制器存储)
      • 1.4.2@Service(服务存储)
        • 1.4.2.1根据context来获取bean
        • 1.4.2.2根据名称来获取bean
        • 1.4.2.3根据名称和类型获取bean
        • 1.4.2.4特殊情况-类名前两位都大写,bean的名称为类名
      • 1.4.3@Repository (仓库存储)
      • 1.4.4@Component (组件存储)
      • 1.4.5@Configuration (配置存储)
      • 1.4.6为什么要这么多类注解? - 五大注解
      • 1.4.7@Controller和其他注解的区别
      • 1.4.8@Bean 使用
        • 1.4.8.1@Bean正常使用举例
        • 1.4.8.2测试@Bean传递参数是如何选择的
      • 1.4.9启动类位置关系影响
    • 1.5 Bean命名
    • 1.6@Bean取
  • 2.DI - 依赖注入
    • 2.1属性注入
      • 2.1.1属性注入流程
      • 2.1.2属性注入问题
    • 2.2构造方法注入
      • 2.2.1只存在一个构造函数时
      • 2.2.2存在多个构造函数时
    • 2.3Setter方法注入
    • 2.4三种注入优缺点分析
    • 2.5@Autowired存在问题
      • 2.5.1.属性名和你需要使用的对象名保持一致
      • 2.5.2.使用@Primary注解标识默认的对象
      • 2.5.3.使用@Qualifier
      • 2.5.4 使用 @Resource 注解
    • 2.6常见面试题 - @Autowird 与 @Resouce的区别
  • 3.Ioc、DI、AOP的关系
    • 2.6常见面试题 - @Autowird 与 @Resouce的区别
  • 3.Ioc、DI、AOP的关系

大家好,我是晓星航。今天为大家带来的是 Ioc和DI 相关的讲解!😀

1.Ioc - 控制反转(解耦)

1.1传统开发

软件设计原则:高内聚,低耦合。

高内聚:一个模块内部的关系

低耦合:各个模块之间的关系

我们的实现思路是这样的:

先设计轮子(Tire),然后根据轮子的大小设计底盘(Bottom),接着根据底盘设计车身(Framework),最后根据车身设计好整个汽车(Car)。这里就出现了一个"依赖"关系: 汽车依赖车身,车身依赖底盘,底盘依赖轮子.

image-20240315202415950

最终程序的实现代码如下:

Main.java

package com.example.demo.ioc;

/**
 * Created with IntelliJ IDEA
 * Description
 * User: 晓星航
 * Date: 2024 -03 -15
 * Time: 20:16
 */
public class Main {
    public static void main(String[] args) {
        Car car = new Car(17);
        car.run();

        Car car2 = new Car(19);
        car2.run();
    }
}

Car.java

package com.example.demo.ioc;

/**
 * Created with IntelliJ IDEA
 * Description
 * User: 晓星航
 * Date: 2024 -03 -15
 * Time: 20:16
 */
public class Car {
    private Framework framework;

    public Car(int size) {
        framework = new Framework(size);
        System.out.println("car init...");
    }

    public void run() {
        System.out.println("car run");
    }
}

FrameWork.java

package com.example.demo.ioc;

/**
 * Created with IntelliJ IDEA
 * Description
 * User: 晓星航
 * Date: 2024 -03 -15
 * Time: 20:17
 */
public class Framework {
    private  Bottom bottom;

    public Framework(int size) {
        bottom = new Bottom(size);
        System.out.println("framework init...");
    }
}

Bottom.java

package com.example.demo.ioc;

/**
 * Created with IntelliJ IDEA
 * Description
 * User: 晓星航
 * Date: 2024 -03 -15
 * Time: 20:19
 */
public class Bottom {
    private Tire tire;

    public Bottom(int size) {
        tire = new Tire(size);
        System.out.println("bottom init...");
    }
}

Tire.java

package com.example.demo.ioc;

/**
 * Created with IntelliJ IDEA
 * Description
 * User: 晓星航
 * Date: 2024 -03 -15
 * Time: 20:20
 */
public class Tire {
    private int size;

    public Tire(int size) {
        this.size =size;
        System.out.println("tire init...size" + size);
    }
}

输出结果:

image-20240315203338137

1.2批量生产车轮(修改代码) - 传统方式,繁琐

我们为了批量化生产各种型号的车轮胎,继而修改了Tire类中的size变量为默认值,传参到Tire中,这就导致了Bottom的关联问题。

image-20240315203403081

在将参数int size传到Bottom中之后,Tire不报错了,但是Bottom又出现了关联问题

image-20240315203412088

在将参数int size传到Framework中之后,Bottom不报错了,但是Framework又出现了关联问题

在将参数int size传到Car中之后,Framework不报错了,此时Car中可以正常批量化生产各种型号的车轮的车了

使用@Component和@Autowired来简化代码

image-20240316132512242

@Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean

@Autowired: 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作

image-20240316134424056

我们之前都用@Controller管理,为什么现在用@Component

image-20240316134358595

因为@Controller就是用@Component来实现的。

1.3解耦

1.3.1使用Ioc方法后

image-20240315211617940

传统方法耦合性高,我们为了提高代码编写效率就引入了Ioc可以将代码进行解耦操作,提高代码编写的效率

1.2中我们只为了更改轮胎的尺寸,但是我们改了轮胎Tire之后,导致我们还要修改底盘Bottom,车身Framework,以及汽车Car,那么有没有什么方法可以只修改轮胎Tire一个代码呢?

传统方法:

image-20240315205246577

使用了Ioc之后的方法:

image-20240315205219055

通过上述两个图的对比,我们可以明显发现使用完Ioc之后,无论我们在车上加任意种新的元素,我们代码都不会产生关联报错。

使用Ioc的车代码:

Car.java:

image-20240315205642046

Framwork.java:

image-20240315205607623

Bottom.java:

image-20240315205728762

Tire.java:

image-20240315205831388

Main.java:

image-20240315210615758

运行结果

image-20240315210857033

1.3.2添加变量颜色 只需要修改Tire即可

  1. 在Tire中增加color变量
image-20240315210941681
  1. 在传参时多传一个颜色参数即可
image-20240315211023075

运行结果:

image-20240315211136604

image-20240315211711046

1.4Bean的存储

共有两种注解类型可以实现:

1.注解: @Controller、 @Service、 @Repository、 @Component、 @Configuration

2.方法注解: @Bean.

1.4.1@Controller(控制器存储)

启动类和我们的容器类一定要同级或者启动类高于其他类,这样启动类中的bean才能拿到其他类中的值

image-20240316152357281

启动类:

image-20240316150200308

spring上下文

image-20240316150244800

使用getBean获取spring容器中的对象

image-20240316151156594

可以看到,此时我们使用bean来获取spring容器中的值已经成功!

image-20240316151307210

如果删除@Controller注解,就会报如下错误

image-20240316151352935

1.4.2@Service(服务存储)

1.4.2.1根据context来获取bean

再写一个userService类,我们还是在启动类中使用bean来获取spring容器中的类中的元素

image-20240316152510172

输出结果:

image-20240316152623272

注:启动类在文件夹中的存放位置一定要等于或高于其他类的位置,不然启动类的作用会失效。

image-20240316152614063

1.4.2.2根据名称来获取bean

image-20240316153625344

image-20240316153613749

image-20240316153926600
1.4.2.3根据名称和类型获取bean

image-20240316153625344

image-20240316153839780

image-20240316153900407
1.4.2.4特殊情况-类名前两位都大写,bean的名称为类名

image-20240316154300883

image-20240316154341541

1.4.3@Repository (仓库存储)

代码:

image-20240316184309930

image-20240316184330618

运行结果图:

image-20240316184339258

1.4.4@Component (组件存储)

代码:

image-20240316184654458

image-20240316184709503

运行结果:

image-20240316184723357

1.4.5@Configuration (配置存储)

代码:

image-20240316185032106

image-20240316184948307

运行结果:

image-20240316184938053

1.4.6为什么要这么多类注解? - 五大注解

  • @Controller: 控制层,接收请求,对请求进行处理,并进行响应
  • @Servie: 业务逻辑层,处理具体的业务逻辑
  • @Repository: 数据访问层,也称为持久层。负责数据访问操作
  • @Configuration: 配置层,处理项目中的一些配置信息

image-20240316185450624

程序的应用分层,调用流程如下:

image-20240316185124591 image-20240316190512217

image-20240316191900580

1.4.7@Controller和其他注解的区别

使用@Controller

image-20240316191440577

image-20240316191430758

可正常访问

使用@Service

image-20240316191357259

image-20240316191329434

不能正常返回

证明@Controller可以作为程序的入口实现,而其他注解不行

1.4.8@Bean 使用

1.4.8.1@Bean正常使用举例

image-20240316193319796

image-20240316191906238

UserInfo.java:

image-20240316193851969

BeanConfig.java:

image-20240316193920806

启动类代码:

image-20240316193658479

此时代码没有正常运行,产生报错信息

image-20240316193811563

修改代码,将根据context获取bean变为根据名称来获取bean

image-20240316194029138

此时程序正常输出结果:

image-20240316194106553

总结:

image-20240316194230805

可以使用 名称获取bean 或者 根据名称和类型来获取bean 这两种方式都可以成功获取到bean。

1.4.8.2测试@Bean传递参数是如何选择的

当name和name2都存在时,Bean会取走对应的name值 zhangsan。(与name和name2先后顺序无关)

image-20240316195319989

当name被注释掉,只剩name2存在时,Bean会取走的name2值 wangwu。(bean会只能取走相关的值,而不会不取值,除非没有相关定义的name)

image-20240316195439130

image-20240316194940379

结论:如果需要的Bean的类型,对应的对象只有一个时,就直接赋值,如果有多个时,通过名称去匹配

1.4.9启动类位置关系影响

SpringBoot 特点;约定大于配置

其中之一体现: 就是扫描路径
默认扫描路径是: 启动类所在的目录及其子孙目录

image-20240316200356144

1.5 Bean命名

image-20240318151304230

如何修改BeanName
五大注解

image-20240318151333944 image-20240318151429945 image-20240318151436277

1.6@Bean取

1.属性注入 @AutoWired

2.构造方法注入

如果只有一个构造方法, @AutoWired可以省略

如果有多个构造方法,必须使用@Qualifier指定(参考2.5.3)一个对象,或使用@Primary注解标识默认的对象(参考2.5.2)

3.Setter方法注入

@Autowired出现的问题 - 参考2.5

2.DI - 依赖注入

image-20240316144543403

2.1属性注入

2.1.1属性注入流程

代码:

image-20240316203728679

image-20240316203845855

运行结果图:

image-20240316203759294

image-20240316203705508

2.1.2属性注入问题

启动类:

image-20240316211409557

UserController.java:

image-20240316211603667

BeanConfig.java:

image-20240316211336017

运行结果

image-20240316211459443

当我们使用类UserInfo属性来定义一个新的值时,程序没有发生报错,一切成功运行

我们修改一下代码,将userInfo改为user,再次运行

image-20240316211258866

我们可以看到报错了,报错信息为我们命名为user后,idea找到了一个userInfo和一个userInfo2,此时idea不知道应该使用哪一个导致报错

image-20240316211826039

如果只有一个对象,属性注入以类型进行匹配,与注入的属性名称无关

但是如果一个类型存在多个对象时,优先名称匹配,如果名称
都匹配不上,那就报错~

image-20240316212449211

2.2构造方法注入

2.2.1只存在一个构造函数时

代码:

image-20240316204753150

image-20240316203845855

运行结果图:

image-20240316204815125

2.2.2存在多个构造函数时

我们增加一个值后,相应的增加了构造函数:

image-20240316205048087

此时我们运行报了空指针异常。

image-20240316205123860

通过分析上述代码得知,我们idea默认调用了第一个无参的构造函数,导致us空指针异常

我们将无参的构造函数注解掉,再次运行

image-20240316205318885

报错信息大致为,无参构造函数注解掉后,idea不知道该使用哪个构造函数,导致找不到构造函数,从而报错

image-20240316205510939

再次修改代码,加上@Autowired,表示我们给idea指定了要用哪个构造函数,再次运行:

image-20240316205705302

此时可以发现,我们程序运行又回归正常了

image-20240316205854103

总结:如果存在多个构造函数时,需要加上@AutoWired注明使用哪个构造函数。
如果只有一个构造函数时,@AutoWired可以省略掉

image-20240316203947505

2.3Setter方法注入

当我们直接使用构造函数里面的Setter方法自动生成,此时我们的UserService有没有注入进来呢?

image-20240316210321839

我们运行一下,发现报错了

image-20240316210427649

报错信息为us空指针异常

我们修改一下代码,在Setter方法上面加上@Autowired

image-20240316210530888

再次运行,可以看到我们的元素再次注入成功!

image-20240316210611503

从上代码结果可以看出我们在使用Setter方法注入时,也需要在Setter方法上加上 @Autowired 才能运行成功

2.4三种注入优缺点分析

  • 属性注入

    • 优点:简洁,使用方便。
    • 缺点:
      • 只能用于 IoC 容器,如果是非 oC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常)
      • 不能注入一个Final修饰的属性
  • 构造函数注入(Spring 4.X推荐)

    • 优点:
      • 可以注入final修饰的属性
      • 注入的对象不会被修改
      • 依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法
      • 通用性好,构造方法是JDK支持的,所以更换任何框架,他都是适用的
    • 缺点:注入多个对象时,代码会比较繁琐
  • Setter注入(Spring 3.X推荐)

    • 优点:方便在类实例之后,重新对该对象进行配置或者注入
    • 缺点:
      • 不能注入一个Final修饰的属性
      • 注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险

2.5@Autowired存在问题

当程序中同一个类型有多个对象是,使用@Autowired会报错(一些情况下)

2.5.1.属性名和你需要使用的对象名保持一致

image-20240318142156845 image-20240318142231794 image-20240318142357726

可以看到只要名称保持一致,idea就可以正常找到对应的属性名,从而打印出正确的结果。

2.5.2.使用@Primary注解标识默认的对象

image-20240318141537121

2.5.3.使用@Qualifier

image-20240318141810602 image-20240318141914710

idea运行结果:

image-20240318141938193

可以看到在加上 @Qualifier("userInfo2") 指定属性名后,idea在运行时就能按照加的属性名指定使用,而不会导致idea不知道使用useInfo还是userInfo2。

2.5.4 使用 @Resource 注解

image-20240318142906929 image-20240318142939805 image-20240318143041304

可以看到在我们加上了 @Resource@Resource(name = "userInfo2") 指定属性名为 userInfo2 后,我们idea也可以正常打印出结果

2.6常见面试题 - @Autowird 与 @Resouce的区别

  • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
  • **@Autowired 默认是按照类型注入,而@Resource是按照名称注入.**相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。

image-20240318143626518

一个类型存在多个对象:

image-20240318143822736

按照名称来匹配:

image-20240318143848451

3.Ioc、DI、AOP的关系

di依赖注入 AOP面向切片 IOC控制反转
spring是一个轻量级控制反转Ioc和面向切片Aop的容器
控制反转IOC是一种设计思想,DI依赖注入是实现IOC的一种方法

性名为 userInfo2 后,我们idea也可以正常打印出结果

2.6常见面试题 - @Autowird 与 @Resouce的区别

  • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
  • **@Autowired 默认是按照类型注入,而@Resource是按照名称注入.**相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。

[外链图片转存中…(img-M4s0g0ws-1712818818828)]

一个类型存在多个对象:

image-20240318143822736

按照名称来匹配:

image-20240318143848451

3.Ioc、DI、AOP的关系

di依赖注入 AOP面向切片 IOC控制反转
spring是一个轻量级控制反转Ioc和面向切片Aop的容器
控制反转IOC是一种设计思想,DI依赖注入是实现IOC的一种方法

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

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

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

相关文章

实战篇06:更新用户头像

实战篇06:更新用户头像 一、接口信息 1.1 基本信息 请求路径:/user/updateAvatar 请求方式:PATCH 接口描述:该接口用于更新已登录用户的头像 1.2 请求参数 请求参数格式:queryString 请求参数说明: 参…

【C语言】万字讲解函数栈帧的创建与销毁

目录 前言 一、什么是函数栈帧? 二、理解函数栈帧能解决什么问题呢 三、函数栈帧的创建和销毁解析 3.1 什么是栈? 3.2 认识相关寄存器和汇编指令 3.3 剖析函数栈帧的创建和销毁 3.3.1 esp寄存器与ebp寄存器的重要性 3.3.2 函数的调用堆栈 3.3.…

SUV新车首发在即,车载随身wifi受追捧!格行随身wifi怎么样?

眼看距离2024年北京车展开幕越来越近,有关各家车企的新车消息也是层出不穷,今年的北京车展到底还有哪些重磅新车呢? 吉利银河E5车展动作:首发车型特点:全新纯电动SUV 此前,吉利全新纯电动SUV——吉利银河…

MySql数据库从0-1学习-第三天多表设计学习

项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种: 一对多(多对一)多对多一对一 一对多 需求:根据需求,完成部门和员工表的设计 一对多,很多人会使用外键,…

IP查询在追踪网络攻击源头中的应用

随着网络攻击事件的不断增加,追踪攻击源头成为网络安全领域的重要任务之一。IP查询技术通过分析网络流量中的IP地址,可以帮助确定攻击的来源。本文将探讨IP查询在追踪网络攻击源头中的应用,包括其原理、方法以及实际案例分析。 IP地址查询&a…

道可云文旅元宇宙平台:全面赋能文旅产业数字化转型

随着科技的迅猛发展,元宇宙、人工智能和虚拟数字人等技术逐渐成为推动社会进步的重要力量。在这一背景下,道可云文旅元宇宙平台以其独特的创新理念和前沿技术,为数字文博领域带来了革命性的变革。 道可云文旅元宇宙平台运用先进的元宇宙、人…

【软考---系统架构设计师】计算机网络章节

目录 一、TCP/IP协议族 (1)基本介绍 (2)TCP和UDP的区别 (3)DNS协议 (4)DHCP协议 二、网络规划与设计 (1)需求分析 (2)通信规范…

OpenResty,Nginx实现接口验签与黑名单控制

介绍 nginx与openresty是两种优秀知名的7层负载均衡软件,nginx以其出色的性能和稳定性成为首选,而openresty则是在Nginx基础上构建的,支持嵌入Lua语言,大幅提升了开发效率。 安装OpenResty 版本 openresty-1.25.3.1-win64下载地…

【leetcode面试经典150题】36. 旋转图像(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

OSCP靶场--Dibble

OSCP靶场–Dibble 考点(前端鉴权参数修改node.js代码注入 suid cp提权 ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.173.110 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-09 06:36 EDT Nmap scan repor…

一种快速移植 OpenHarmony Linux 内核的方法

移植概述 本文面向希望将 OpenHarmony 移植到三方芯片平台硬件的开发者,介绍一种借助三方芯片平台自带 Linux 内核的现有能力,快速移植 OpenHarmony 到三方芯片平台的方法。 移植到三方芯片平台的整体思路 内核态层和用户态层 为了更好的解释整个内核…

软件本地化:步骤、成本和障碍

瓦莱丽娅舍斯托博耶娃,Logrus IT翻译部门的经理,谈论了我们公司的运作方式、软件本地化是什么以及为什么它如此重要。 你能告诉我一些关于你们公司的情况吗,瓦莱丽娅?它做什么,成立多久了? Logrus IT今年…

袋鼠云春季发布会圆满落幕,构建Data+AI新质生产力

4月10日,以“DataAI,构建新质生产力”为主题的袋鼠云春季发布会圆满落幕。大会中,袋鼠云带来了一系列“AI”的数字化产品与最新行业沉淀,旨在将数据与AI紧密结合,打破传统的生产力边界,赋能企业实现更高质量…

基于springboot实现音乐网站管理系统项目【项目源码+论文说明】

基于SpringBoot实现音乐网站管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了音乐网站的开发全过程。通过分析音乐网站管理的不足,创建了一个计算机管理音乐网站的方案。文章介绍了音乐…

【pinia学习】pinia课程学习笔记

课程地址: VUE新一代状态管理工具Pinia超详细基础入门 贴两个链接: vue3官方文档 pinia官方文档 P1 《pinia的简介》 不得不说“开卷有益,学有所获”,前两天自己找pinia的官方文档好像也没找对,原来在vue3官方生态系…

万象皆歌everySings音乐与AI技术的邂逅,内测启动

在这个快节奏的数字时代,音乐依然扮演着连接人心、传递情感的重要角色。然而,音乐创作往往被视为门槛较高的艺术形式,需要复杂的理论知识和漫长的实践经验。但现在,随着人工智能技术的不断进步,让大众对音乐的获悉和交…

消息的可靠性·

面试题:Rabbitmq怎么保证消息的可靠性? 1.消费端消息可靠性保证: 消息确认(Acknowledgements): 消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAcktrue)。为保证消…

JS加密:对比JScrambler和JShaman加密效果

本文,以一个实例,比对JS加密两大神器:JScrambler、JShaman的加密结果,看看谁的加密效果更好。 注:本文不是技术文章,仅仅从加密结果的“型”上简单观查,不做技术分析,仅看哪个加密代…

【学习笔记】3、逻辑门电路

3.1 MOS逻辑门电路 按照器件结构的不同形式,分为NMOS、PMOS、CMOS三种逻辑门电路。 3.1.1 CMOS CMOS电路成为主导地位的逻辑器件。工作速度:赶上甚至超过TTL电路。(早期CMOS速度慢,后来工艺提升速度变快)功耗和抗干…

【讲解下TypeScript的基础知识点】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…