【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,一经查实,立即删除!

相关文章

【第10章】MyBatis-Plus持久层接口之Db Kit

文章目录 前言一、使用示例二、使用提示总结 前言 Db Kit 是 Mybatis-Plus 提供的一个工具类,它允许开发者通过静态调用的方式执行 CRUD 操作,从而避免了在 Spring 环境下可能出现的 Service 循环注入问题,简化了代码,提升了开发…

计算经纬度坐标之间的真实距离

要计算两组经纬度坐标之间的距离,我们可以使用大地测量学中的公式,例如Haversine公式或者更精确的Vincenty公式。这里我将使用Haversine公式,因为它适用于小范围内的距离计算,且计算相对简单。 Haversine公式的基本形式如下&…

计算机视觉 | 基于 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 程序设计语言基础

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

使用Python实现一个简单的密码管理器

文章目录 一、项目概述二、实现步骤2.1 安装必要的库2.2 设计密码数据结构2.3 实现密码加密和解密2.4 实现主要功能2.4.1 添加新密码2.4.2 显示所有密码2.4.3 查找特定密码2.4.4 更新密码2.4.5 删除密码 2.5 实现用户界面 三、代码示例3.1 加密和解密示例3.2 用户界面示例 在现…

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应用实践 本系列文…

前端无感登录(无感刷新token)

1. 在响应器中拦截(判断token返回过期后,调用刷新token的接口) 2. 后端返回过期时间,前端判断token的过期时间,去调用刷新token的接口 3. 写定时器,定时刷新token接口 流程: 1. 登录成功后保存两…

降薪20%,那些压力山大的事情

1.开会一天,研发工作没完成,怎么办?? 2.项目接手,一堆问题等着处理怎么办? 3.产品研发,客户验收,公司要求,同事间相互的配合,完成一件事那么难,…

数据结构和顺序表

什么是数据结构 数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 数据元素的三要素 数据结构包括三方面的内容:逻辑结构、存储结构、数据的运算。 逻辑结构 逻辑结构是指数据元素之间的逻辑关系,即从逻辑关系上描述数据。数据的逻辑结…

Android 第三方组件整理

Banner图: me.militch:banner-holder 注解: com.jakewharton:butterknifecom.jakewharton:butterknife-compiler 拼音: com.github.promeg:tinypinyin 日期: com.haibin:calendarview 二维码扫码: com.journeyapps:zxing…

跨过45分门槛,单独划线让软考证书可能失而复得

在软考的竞技场上,分数是拿证的那道坎,那就是45分!但别急,故事总有转折,国家为了那些在乡村振兴道路上奋力追赶的地区,特别开启了一扇窗——单独划线政策。 单独划线地区分数线并不是固定的,届时…

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

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

MQ运行时遇到的问题

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

中介子方程三十九

XXFXXuXXWXXuXXdXXrXXαXXuXpXXKXηXiXXnXXyXηXuXXrXXaXXrXXuXηXyXXnXXiXηXKXXpXuXXαXXrXXdXXuXWXπXXWXeXyXeXbXπXpXXNXXqXeXXrXXαXXuXpXXKXηXiXXnXXyXηXuXXrXXaXXrXXuXηXyXXnXXiXηXKXXpXuXXαXXrXXeXqXXNXXpXπXbXeXyXeXWXXπXWXuXXdXXrXXαXXuXpXXKXηXiXXnXXyXη…

昇思25天学习打卡营第8天|保存与加载

当模型训练好以后,就可以用来预测了。后续我们在其他端部署的时候不需要再次训练,直接使用训练好的模型进行推理就可以了。 在保存和加载的时候我们都需要传入模型。保存的API是save_checkpoint(model,path), 对应的加载的API是 load_checkpoint(model,…

Java实现发送邮件

引入jar包 <dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version></dependency># 发送邮件配置 mail:smtp:host: smtp.163.comport: 25auth: trueusername: 139*****163.…

vue3+ el-upload封装上传组件

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

启航数据科学:Jupyter Notebook安装全攻略,轻松入门!

目录 简介安装步骤 安装Python安装pip安装Jupyter Notebook 启动Jupyter Notebook基本使用常见问题总结 简介 Jupyter Notebook 是一个交互式的笔记本环境&#xff0c;支持运行和展示 Python 代码&#xff0c;以及文本、图表和公式。它广泛应用于数据分析、机器学习和科学计算…

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

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