【Java EE】Spring IOCDI

Spring IOC & DI

文章目录

  • Spring IOC & DI
    • 一、Spring是什么?
    • 二、IOC(控制反转)
      • 2.1 通俗理解
      • 2.2 造汽车的例子理解IOC
      • 2.3 IOC详解
        • 1. 获取Bean
        • 2. 方法注解——@Bean
          • 1. 应用场景:
          • 2. 应用方法:
          • 3. 注意要点:
      • 特别注意:
    • 四、DI
      • 4.1 属性注入
        • 使用方法
      • 4.2 构造方法注入
        • 使用方法
      • 4.3 在setter方法注入
        • 使用方法
      • 4.4三种注⼊优缺点分析
      • 4.5 @Autowired出现多个同类型Bean的情况
        • 原因:
        • 解决方法:
          • 1. 使用 `@Primary` 指定默认匹配的项目
          • 2. 使用`autowireCandidate = false`去除默认匹配
          • 3. 使用 `@Resource(name="**")`对于特定名称的Bean进行注入
      • 4.6 @Autowired和@Rescource的区别

一、Spring是什么?

Spring是一个开发的框架,包含了很多的依赖,比如Spring MVC, Spring Boot等,这些让我们开发变得容易,可以说,Spring是一个包含很多工具方法的容器。

二、IOC(控制反转)

2.1 通俗理解

Inversio of Control ,也就是说,Spring是一个 “控制反转” 的容器。

控制反转就是让一个事物的控制权交由其他人。

2.2 造汽车的例子理解IOC

造汽车的流程:

在这里插入图片描述

代码:
汽车类:

package com.example.springioc.v1;public class Car {// 汽车依赖于框架private Frame frame;public Car() {frame = new Frame();System.out.println("汽车安装框架中...");}
}

框架类:

package com.example.springioc.v1;public class Frame {// 框架依赖于底盘private Bottom bottom;public Frame() {bottom = new Bottom();System.out.println("框架安装底盘中...");}
}

底盘类:

package com.example.springioc.v1;import jdk.jfr.Frequency;public class Bottom {// 底盘依赖于轮胎private Tire tire;// 有了尺寸的需求,需要进行传参public Bottom(int size) {tire = new Tire(size);System.out.println("底盘安装轮胎中...");}
}

轮胎类:

package com.example.springioc.v1;public class Tire {public Tire() {System.out.println("打造默认尺寸轮胎中...");}
}

运行结果:

在这里插入图片描述

这种代码架构,每个类的控制权都在调用他的那一方中,调用的一方创造了怎样的他,那他就是怎样的。

如果想要更换任意尺寸的轮胎,那就需要传递一个size参数,此时要依次对于代码做修改。

首先是轮胎类,需要增加 size 属性,但是这样最上层的 Car 类并不能够选择自己想要的尺寸,仍然需要对于控制着 Tire 的Bottom进行添加参数以便Frame能够添加参数,这样依赖,Frame也得添加size参数,Car 也需要。

最终代码(对于每一级都添加了size参数):

汽车类:

package com.example.springioc.v1;public class Car {// 汽车依赖于框架private Frame frame;// 对于汽车类添加了size参数构造public Car(int size) {frame = new Frame(size);System.out.println("汽车安装框架中...");}
}

框架类:

package com.example.springioc.v1;public class Frame {// 框架依赖于底盘private Bottom bottom;public Frame(int size) {bottom = new Bottom(size);System.out.println("框架安装底盘中...");}
}

底盘类:

package com.example.springioc.v1;import jdk.jfr.Frequency;public class Bottom {// 底盘依赖于轮胎private Tire tire;public Bottom(int size) {tire = new Tire(size);System.out.println("底盘安装轮胎中...");}
}

轮胎类:

package com.example.springioc.v1;public class Tire {// 轮胎的大小private Integer size;public Tire() {System.out.println("打造默认尺寸轮胎中...");}public Tire(int size) {System.out.println("打造"+size+"号的轮胎中...");}
}

显而易见,这样的代码架构维护起来非常臃肿
每一下级的控制权都由上一级保管,如果对于下一级的需求发生了变化,那么这就需要改动所有的类。(比如:如果现在用户需要对于轮胎的轮毂进行制定,那就还需要给Tire的构造函数增添一个 style 属性,如果还有颜色等的需求,那就还得一直加;只加Tire一个类的还好,因为每一上级都直间或者间接依赖于这个Tire,每一个类都需要进行修改,耦合度非常高。)

所以就需要 “控制反转” 思想,将整个控制反转:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

修改后的代码:

package com.example.springioc.v2;import com.example.springioc.v1.Frame;public class Main {static class Tire {int size;public Tire(int size) {this.size = size;System.out.println("打造"+size+"号轮胎...");}}static class Bottom{Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("打造底盘...");}}static class Framework {Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("打造框架...");}}static class Car {Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("打造汽车...");}}public static void main(String[] args) {Tire tire = new Tire(1);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);}
}

这样一来,如果用户对于轮胎有新的需求,那也只需要修改轮胎这一个类,完成了整个代码的解耦。

也就是说,我们将控制权转让给了Tire自己,Tire的上级类不再享有控制权,传来什么Tire,就用什么。

2.3 IOC详解

控制反转之后,对象进入Spring容器就会变成Bean,也就是说,Spring中的对象都叫做Bean。

1. 获取Bean
  1. 注册Bean:使用五大注解,让Spring Boot能够发现@Bean
  2. 主要方法:使用 context 的 getBean() 进行获取
  3. 得到的Bean就相当于从Spring Boot中取到了这个对象

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 方法注解——@Bean
1. 应用场景:
  1. 当对于外部类的方法,无法通过修改源码进行注册Bean,所以可以使用Spring的@Import注解来导入一个配置类,在这个配置类中你可以使用@Bean注解来声明这个外部类作为一个Bean,并对其进行配置。

  2. 如果一个类中需要多个实例,可以使用@Bean对于实例进行别名命名(value和name),以示区分。

2. 应用方法:
		/*** 使用@Bean的演示*/// 使用类,获得整个类的BeanUser bean1 = context.getBean(User.class);System.out.println(bean1);// li4是使用name属性定的别名User bean2 = (User) context.getBean("li4");System.out.println(bean2);// user3是方法的名字User bean3 = (User) context.getBean("user3");System.out.println(bean3);
3. 注意要点:
  1. @Bean是方法级的注解
  2. 需要配合类注解进行使用
  3. 使用value和name属性可以命名别名
  4. Bean的名字就是方法的名字
  5. autowireCandidate 可以消除:当有多个能够匹配的实例的时候,排除这个实例

特别注意:

@ComponentScan 可以定义Spring的扫描路径。

使用方法:

@ComponentScan({"com.example.springioc.bean_test"})

直接在()中使用{}定义路径。

四、DI

DI就是依赖注入。

4.1 属性注入

使用 @Autowired 注入。

使用方法
package com.example.springioc.di_test.controller;import com.example.springioc.di_test.service.TireSeervice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class TireController {@AutowiredTireSeervice tireSeervice;public void doTire() {System.out.println("成功调用轮胎控制器...");tireSeervice.doTire();}
}

使用 @Autowired 将service属性注入到控制器中。

package com.example.springioc.di_test.service;import com.example.springioc.di_test.model.Tire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class TireService {@AutowiredTire tire;public void doTire() {tire.setSize(12);tire.setColor("红");System.out.println("制作"+tire.getSize()+"号"+tire.getColor()+"色的轮胎");}
}

同时在服务类中将需要的轮胎对象注入。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.2 构造方法注入

将构造方法使用 @Autowired 注入。

使用方法
package com.example.springioc.di_test2.service;import com.example.springioc.di_test2.model.Tire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class TireService {Tire tire;@Autowired //构造函数上注入public TireService(Tire tire) {this.tire = tire;tire.setSize(12);tire.setColor("红");}public void doTire() {System.out.println("制作"+tire.getSize()+"号"+tire.getColor()+"色的轮胎");}}

在服务类的构造方法中使用@Autowired 中注入。

package com.example.springioc.di_test2.controller;import com.example.springioc.di_test2.service.TireService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class TireController {TireService tireService;@Autowired //构造函数上注入public TireController(TireService tireService) {this.tireService = tireService;}public void doTire() {System.out.println("成功调用轮胎控制器...");tireService.doTire();}}

在控制类的构造方法使用@Autowired 中注入。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.3 在setter方法注入

将构造方法使用 @Autowired 注入。

使用方法
package com.example.springioc.di_test3.service;import com.example.springioc.di_test3.model.Tire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class TireService {Tire tire;@Autowired //set方法上注入public void setTire(Tire tire) {this.tire = tire;tire.setSize(1);tire.setColor("green");}public void doTire() {System.out.println("制作"+tire.getSize()+"号"+tire.getColor()+"色的轮胎");}}

在服务类的setter方法中使用@Autowired 中注入。

package com.example.springioc.di_test3.controller;import com.example.springioc.di_test3.model.Tire;
import com.example.springioc.di_test3.service.TireService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class TireController {private TireService tireService;@Autowired //set方法上注入public void setTireService(TireService tireService) {this.tireService = tireService;}public void doTire() {System.out.println("成功调用轮胎控制器...");tireService.doTire();}}

在控制类的setter方法使用@Autowired 中注入。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.4三种注⼊优缺点分析

  1. 属性注⼊
    ◦ 优点: 简洁,使⽤⽅便;
    ◦ 缺点:
    ▪ 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指
    针异常)
    ▪ 不能注⼊⼀个Final修饰的属性

  2. 构造函数注⼊(Spring 4.X推荐)
    ◦ 优点:
    ▪ 可以注⼊final修饰的属性
    ▪ 注⼊的对象不会被修改
    ▪ 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
    是在类加载阶段就会执⾏的⽅法.
    ▪ 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的
    ◦ 缺点:
    ▪ 注⼊多个对象时, 代码会⽐较繁琐

  3. Setter注⼊(Spring 3.X推荐)
    ◦ 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
    ◦ 缺点:
    ▪ 不能注⼊⼀个Final修饰的属性
    ▪ 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险

4.5 @Autowired出现多个同类型Bean的情况

会发生报错:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

控制器类:

package com.example.springioc.autowired_test;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class TestController {@Autowired// 有两个String类型的BeanString name;public void sayHi() {System.out.println(name);}
}

组件类:

package com.example.springioc.autowired_test;import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class BeanConfig {@Beanpublic String test1() {return new String("zhang3");}@Beanpublic String test2() {return new String("li4");}
}

可以看出组件中有两个String类型的Bean。

原因:

@Autowired不知道选择哪个Bean进行注入,发生了冲突,需要解决这个冲突。

解决方法:
1. 使用 @Primary 指定默认匹配的项目
2. 使用autowireCandidate = false去除默认匹配
3. 使用 @Resource(name="**")对于特定名称的Bean进行注入

在这里插入图片描述

在这里插入图片描述

4.6 @Autowired和@Rescource的区别

  1. @Autowired 是spring提供的注解,@Rescource是Java EE提供的注解

  2. @Autowired按照默认规则进行注入,但是@Rescource根据名称注入,有更多的选项。

    默认规则:
    在这里插入图片描述

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

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

相关文章

计算机视觉 | 基于 PointNet 网络的飞机零件 3D 点云分割

目录 一、简要介绍二、环境设置2.1 实验配置2.2 必要库安装 三、数据集解析3.1 数据集加载3.2 数据文件夹结构3.3 点云数据可视化3.4 数据获取与预处理3.5 数据集定义 四、模型组网4.1 PointNet 介绍4.2 Paddle模型组网4.3 模型概要 五、模型训练六、模型预测七、总结 Hi&#…

2.1 程序设计语言基础

程序设计语言概述 常见的编程语言 编译和解释 程序设计语言的基本成分 数据成分、运算成分、控制成分、传输成分 函数 传值调用、传址调用 编译程序基本原理

window上部署sql server改动端口、和sqlserver的一些还原、批量插入存储过程的命令

1.端口的查看和启动 --windows上安装上sql server数据库后,搜索界面搜索sql,会出现配置管理器,点击进入 --进入后再次选择配置管理器 2. sqlserver数据库还原图形化 sqlserver还原数据库时会使数据库进入一个restore的还原状态,…

昇思25天学习打卡营第6天|Vision Transformer

文章目录 昇思MindSpore应用实践基于MindSpore的Vision Transformer1、Vision Transformer(ViT)简介网络结构 2、Attention模块Encoder部分用到的功能函数:整体构建ViT模型 3、模型训练4、模型验证 Reference 昇思MindSpore应用实践 本系列文…

linux网络命令:httpie详解-简单易用的命令行 HTTP 客户端

目录 一、命令概述 二、基本特点 1、直观和友好的命令语句 2、内置 JSON 支持 3、支持多种请求方法 4、支持 HTTPS、代理和授权验证 5、支持多种请求数据格式 6、自定义 headers 头 7、持久 sessions 存储 8、插件支持 三、安装 1、对于基于 Debian 的系统&#xf…

MQ运行时遇到的问题

遇到的问题描述:我在绑定通道的时候发现了通道绑定失败, 原因: 在代码中我第一次创建交换机的时候类型的默认没有修改成topic类型的,导致后面的代码再去进行注册的时候并没有实现那个类型 解决: 更改代码&#xff0…

vue3+ el-upload封装上传组件

组件功能介绍 上传格式限制上传大小限制上传文件数量限制自定义上传区上传成功回调禁用上传开关与点击上传自定义事件暴露所以上传文件列表&#xff08;uploadList&#xff09;与当前文件数据&#xff08;uploadLatestFile&#xff09; 组件代码Upload.vue <template>&l…

在Stimulsoft 报告中连接来自 MySQL 的数据

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…

Firewalld 防火墙基础

Firewalld 防火墙基础 一、Firewalld概述firewalld 简介firewalld 和 iptables 的关系firewalld 与 iptables service 的区别 二、Firewalld 网络区域区域介绍Firewalld数据处理流程 三、Firewalld 防火墙的配置方法firewall-config 图形工具“区域”选项卡“服务”选项卡改变防…

仓库管理系统24--统计报表

原创不易&#xff0c;打字不易&#xff0c;截图不易&#xff0c;多多点赞&#xff0c;送人玫瑰&#xff0c;留有余香&#xff0c;财务自由明日实现 1、引用LiveCharts 2、创建LiveChartViewModel using GalaSoft.MvvmLight; using LiveCharts.Wpf; using LiveCharts; using Sy…

从新手到高手:Scala函数式编程完全指南,Scala 数据类型(4)

1、Scala 数据类型 Scala 与 Java有着相同的数据类型&#xff0c;下表列出了 Scala 支持的数据类型&#xff1a;

ros1仿真导航机器人 navigation

仅为学习记录和一些自己的思考&#xff0c;不具有参考意义。 1navigation导航框架 2导航设置过程 &#xff08;1&#xff09;启动仿真环境 roslaunch why_simulation why_robocup.launch &#xff08;2&#xff09;启动move_base导航、amcl定位 roslaunch why_simulation nav…

无偏归一化自适应心电ECG信号降噪方法(MATLAB)

心电信号作为一种生物信号&#xff0c;含有大量的临床应用价值的信息&#xff0c;在现代生命医学研究中占有重要的地位。但心电信号低频、低幅值的特点&#xff0c;使其在采集和传输的过程中经常受到噪声的干扰&#xff0c;使心电波形严重失真&#xff0c;从而影响后续的病情分…

你还不会买智能猫砂盆吗?跟你们详细讲解今年最火的智能猫砂盆!

智能猫砂盆的坑&#xff0c;想必有很多养猫家庭都踩过吧。自己买回来的机器&#xff0c;不是空间不够大&#xff0c;导致猫咪拉到外面去&#xff0c;就是铲不干净&#xff0c;还得自己进行二次清理&#xff0c;搞得这个智能猫砂盆白买了。那如果我们想要购买合适自己家猫咪的智…

数据链路层分析

文章目录 前言一、数据链路层概述二、终端之间的通信三、帧格式1.Ethernet_II型2.IEEE 802.3 四、MTU分析五、数据帧的传输1.MAC地址2.单播3.广播4.组播5.数据帧的收发 前言 网络中传输数据需要定义并遵循一些标准&#xff0c;以太网是根据IEEE802.3标准来管理和控制数据帧的&…

sqlserver开启CDC

1、背景 由于需要学习flink cdc&#xff0c;并且数据选择sqlserver&#xff0c;所以这里记录sqlserver的cdc开启操作步骤。 2、基础前提 官方介绍地址&#xff1a;https://learn.microsoft.com/zh-cn/sql/relational-databases/track-changes/enable-and-disable-change-dat…

如何优化前端性能:提高网页加载速度的实用技巧

我们在前端开发中&#xff0c;性能优化是提高用户体验的关键因素。网页加载速度直接影响用户的满意度和留存率。本文将介绍几种优化前端性能的实用方法&#xff0c;帮助你提高网页加载速度。 问题描述 &#xff1a; 首先前端性能优化涉及多个方面&#xff0c;包括减少HTTP请…

专为运维工程师设计!阿里藏经阁出品的Python实战手册被我搞来了

Python 可能是极少数既简单又强大的编程语言中的一种。更重要的是&#xff0c;用它来编程是非常快乐的事。 今天给小伙伴们分享的是阿里“藏经阁”出品的专门给运维工程师设计的Python实战手册 废话不多说&#xff0c;下面把内容展示给大家 01 Python快速回顾 02 Python脚本…

【大模型】基于ChatGLM进行微调及应用 [更新中......]

文章目录 一、前言二、说明2.1 代码结构2.2 依赖包版本 三、启动对话演示3.1 命令行交互 cli_demo.py3.2 网页交互 web_demo.py 四、微调模型4.1 基于 P-Tuning v2 微调模型4.1.1 软件依赖4.1.2 下载数据集4.1.3 下载模型文件4.1.4 操作步骤 4.2 基于 Full Parameter 微调模型4…

从进程到协程,浅谈Java提高CPU利用率的发展

综合CPU利用率来讲,计算机远古时期,为提高CPU利用率,有以下概念 串行进程->并行进程->线程->线程池>->虚拟线程(协程) 一,串行进程, 早期的操作系统对任务调度,往往从最简单的实现开端,串型进程意思是对分配的一个任务,其任务能百分百占用CPU,哪怕…