Spring05 SpringIOC DI

news2024/11/19 4:36:17

名词解释

今天我们来介绍Spring框架的最重要的part之一   SpringIOC 和 DI

这里的SpringIOC 其实是容器的意思,Spring是一个包含了很多工具方法的IOC容器

什么是IOC呢?

IOC其实是Spring的核心思想 

Inversion of Control  (控制反转)

可能这里你还是不理解这个是啥意思  其实就是我们一般创建对象的方式是使用new等方式创建,但是这里我们让Spring帮助我们创建对象,程序中只需要进行DI(对象注入)即可

Spring是一个IOC容器,所以有时候Spring也称之为Spring容器

这里举一个生活上的例子来解释一下SpringIOC的含义

我们招聘的时候,其实企业员工的入职和解雇等操作都得老板自己来,但是这里我们老板转给了HR来处理

案例对比

传统方式

假如我们需要实现这么一个依赖关系的思路

我们第一版本先使用传统方式进行操作一下

//轮胎
public class Tire {
    private int size;
    private String color;

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

//底盘
public class Bottom {
    private Tire tire;

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

//框架
public class Framework {
    private Bottom bottom;

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

//汽车
public class Car {
    private Framework framework;

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

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

//启动类
public class Main {
    public static void main(String[] args)
    {
        Car car = new Car(10);
        car.run();
    }
}

这里我们发现,我们如果对车万一需要进行一些操作,就会导致牵一发而动全身的效果

比如,如果我们为车的轮胎指定轮胎的厂家,这样我们就需要从轮胎类逐个的向上进行修改

这样程序的耦合度就太高了,于是我们现在介绍一下SpringIOC的方式来管理对象

注:这里只是模拟SpringIOC的方式来创建对象,这里SpringIOC其实我们也可以理解为一种思想,本质上要求交给Spring管理的对象是无状态的

SpringIOC版本

这里我们可以将对象的创建放到一块儿,Spring框架的想法是将对象的创建交给Spring来,我们向使用的时候只需要使用DI注入即可

这里我们先模拟一下程序的解耦,避免这种牵一发而动全身的操作存在

//bottom
public class Bottom {
    private Tire tire;

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



//Car
public class Car {
    private Framework framework;

    public Car(Framework framework) {
        this.framework = framework;
        System.out.println("framework init...");
    }

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


//Framework
public class Framework {
    private Bottom bottom;

    public Framework(Bottom bottom) {
        this.bottom = bottom;
        System.out.println("bottom init....");
    }
}



//Tire
public class Tire {
    private int size;
    private String color;

    public Tire(int size, String color) {
        System.out.println("tire size:"+size+",color:"+color);
    }
}



//Main
public class Main {
    public static void main(String[] args) {
        Tire tire = new Tire(17, "red");
        Bottom bottom = new Bottom(tire);
        Framework framework = new Framework(bottom);
        Car car = new Car(framework);
        car.run();
    }
}

这里我们发现了对象创建的思路是这样的

传统方式是创建Car再去找需求的依赖,是一个从下到上的结构

而IOC的方式是将对象依赖注入,是改进之后的控制权反转

这里我们可以看出IOC思维的优势

1.减少了类之间的耦合度

2.便于对象的集中管理

DI

解释就是依赖注入的意思,我们刚刚这种传对象的操作其实理论依据就是DI

IOC详解

下面我们进行SpringIOC的详解

首先我们提出一个Bean的概念 Spring中的对象称之为Bean

我们如果想把某些对象交给Spring管理,我们可以用以下注解来修饰

1.类注解

@Repository   @Service @Component  @Configuration   @Controller

2.方法注解

@Bean

注:Spring也不一定需要在web网页上显示,我们也可以在控制台打印

首先我们来尝试一下这五大类注解

@Component
public class UserComponent {
    public void doComponent()
    {
        System.out.println("UserComponent");
    }
}


@Configuration
public class UserConfig {
    public void doConfig()
    {
        System.out.println("UserConfig doConfig");
    }
}


@Repository
public class UserRepo {
    public void doRepo()
    {
        System.out.println("UserRepo");
    }
}


@Service
public class UserService {

    public void doService() {
        System.out.println("UserService doService");
    }
}


@Controller
public class helloTest {
    public void hello()
    {
        System.out.println("hello");
    }
}

//启动类
@SpringBootApplication
public class SpringIocApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);
        helloTest bean = context.getBean(helloTest.class);
        bean.hello();
    }

}

这里我们只需要用相同的模板就可以实现这里的IOC操作

这里我们介绍一下getBean的几个参数

我们可以根据类型找到类,可以根据类型+方法名找到类,也可以只根据方法名寻找类

注意这里Bean的名字是以小驼峰的方式去拿的

比如HelloTest 这里的Bean名称就是 helloTest

注意这里获取到的三个对象都是同一个对象

Bean的命名规则:如果只有开头字母是大写的,那么我们就将第一个字母变成小写的,如果前两个都是大写字母,那么我们就直接返回这个名字

假设这里我们使用的类名是HElloTest,我们使用首字母小写小驼峰的方式就会直接失败

这里我们可以看到日志显示找不到这个Bean 实际上开头两个字母都大写Bean就不会修改名称,直接使用原名即可获取

使用的就是这个方法

注:idea中查询类 使用 ctrl + shift + alt + n

再查询方法可以使用ctrl + f查询

Application和BeanFactory之间的关系?

1.父子关系  BeanFactory有的功能Application都有

2.除此之外Application有很多其他的功能

3.BeanFactory是一个懒加载的方式  

Application是一个预加载的方式,效率更高

五大注解的对比

我们看到除了component其他的四大注解基本上都是一样的

可以混用嘛??

理论上可以,但是工作中一般不允许混用,但是其中的界限分割的不明确,有的时候还是混用的

@Controller   @Conponent  主键

@Service 业务逻辑层  @Repository  数据层 @Configuration  表现层

注:这里的Controller有特殊用处,其余三个可以在理论上混用(事实上也可以)

其余四个注解都包含了Component

注:@Controller如果进行替换不一定能实现路由映射

注:这里不加上注解时无法将对象交给Spring管理的

这里我将@Controller注解删除

Spring就会获取不到这个Bean

下面开始使用Bean的方式书写

注意:@Bean的使用也需要配合五大注解一起使用

Spring不可能扫描所有的项目文件,这里我们就使用五大注解来标识一下需要扫描的文件

@Bean的命名方式就是方法名

Spring扫描的默认是哪些文件呢?

我们先做一个测试,将启动类放到component包下

这时候去获取component的类就是可以的,获取HelloTest的类就是失败的

Spring扫描的三大条件

1.使用五大注解标记类

2.使用Bean注解标记方法

3.默认扫描路径是启动类所在的目录以及子目录 

如果我们向让其扫描其他的路径,就可以使用@ComponentScan(basePackages = "")

我们这样就可以获取User对象了

@Configuration
public class UserConfig {
    @Bean

    public User doConfig()
    {
        User u1 = new User();
        u1.setName("zhangsan");
        u1.setId(1001);
        return u1;
    }
}

DI注入

这里有三种方式注入

1.依赖注入/属性注入

2.构造器注入

3.setter注入

首先是依赖注入  我们只需要给需要交给Spring的对象加上五大注解,给需要注入的属性加上Autowired让他去Spring里面获取对应的对象即可

我们将注解干掉,使用构造器的方式也可以获取到

但是如果加上一个空参构造器,就会产生异常

这里出现空指针了,因为这里的Spring是调用构造函数来创建对象的,是使用反射的方式来操作的,这里有两个对应的构造函数了,默认就直接使用无参的构造函数了

如果我们再加一个属性和一个两个参数的构造函数

就会产生没有默认构造器的错误,这里我们可以使用@Autowired修饰默认构造方法解决

这样就可以正常运行啦

总结:

对于构造函数注入

1.只有一个构造函数的时候,无需操作

2.多个构造函数的时候需要@Autowired指定对应的构造函数

注:规范的写法是任何时候都把无参的构造函数加上,然后把想用的构造函数加上@Autowired注解即可

set方法+@autowired注解仍然可以完成任务

三种属性注入的优缺点

1.属性注入

优点是简洁并且书写方便

缺点也明显 只能用于IOC容器,使用的时候肯呢个出现空指针问题

不能注入final修饰的属性

2.构造器注入

优点:可以注入final修饰的属性

通用性好,JDK支持,所以任何框架都行

依赖对象使用前一定会被完全初始化

3.set方法注入

优点是方便在类实例之后重新堆起对象进行配置和注入

缺点是不能注入final修饰的属性

也可能被其他人修改

我们使用已有的bean来命名是可以正常执行内容的

但是只要我们改一下名字,立马就找不到对应的bean了

我们可以理解这里的查找方式是先根据类型和名称查询,查不到就根据类型查找,在没有就报错异常

这里可以使用三种方式去拿到对应的Bean对象

1.使用Primary注解给对应的Bean标记上,指定使用这个Bean

2.使用Qualifier注解,选出使用Bean的方法名

3.使用resourse注解加上方法名的方式也可以解决问题

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

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

相关文章

xilinx的高速接口构成原理和连接结构

本文来源: V3学院 尤老师的培训班笔记【高速收发器】xilinx高速收发器学习记录Xilinx-7Series-FPGA高速收发器使用学习—概述与参考时钟GT Transceiver的总体架构梳理 文章目录 一、概述:二、高速收发器结构:2.1 QUAD2.1.1 时钟2.1.2 CHANNEL…

【SysBench】OLTP 基准测试示例

前言 本文采用 MySQL 沙盒实例作为测试目标,使用 sysbench-1.20 对其做 OLTP 基准测试。 有关 MySQL 沙盒的更多信息,请参阅 玩转 MySQL Shell 沙盒实例,【MySQL Shell】6.8 AdminAPI MySQL 沙盒 。 1、部署一个 MySQL 沙盒实例 使用 mysq…

【ESP32S3 Sense接入百度在线语音识别】

视频地址: 1. 前言 使用Seeed XIAO ESP32S3 Sense开发板接入百度智能云实现在线语音识别。自带麦克风模块用做语音输入,通过串口发送字符“1”来控制数据的采集和上传。 步骤概括    (1) 在百度云控制端选择“语音识别”并创建应用获取API Key和Secr…

MapReduce学习问题记录

1、如何跳过对某行数据的处理 第一行数据是字段名不需要处理,我们知道第一行偏移量是0(行记录的时候是从数组首地址开始,到了行标识符进行一次计数,这个计数就是行偏移量,从0开始),我们根据偏移…

银行5G短消息应用架构设计

(一)RCS简介 1.1 RCS的提出与标准制定 RCS(Rich Communication Services & Suite,富媒体通信)是GSMA(Groupe Speciale Mobile Association,全球移动通信系统协会)在2008年提出的一种通讯方式,RCS融合了语音、消息…

【算法每日一练]-图论(保姆级教程篇16 树的重心 树的直径)#树的直径 #会议 #医院设置

目录 树的直径 题目:树的直径 (两种解法) 做法一: 做法二: 树的重心: 题目: 会议 思路: 题目:医院设置 思路: 树的直径 定义:树中距离最…

android.os.TransactionTooLargeException解决方案,Kotlin

android.os.TransactionTooLargeException解决方案,Kotlin 首先,特意制造一个让Android发生TransactionTooLargeException的场景,一个Activity启动另外一个Activity,在Intent的Bundle里面塞入一个大的ArrayList: import android.…

阿里云OSS存储的视频如何加水印

OSS是不能进行视频添加水印的,可以图片添加水印。 您可以在视频点播中进行配置: https://help.aliyun.com/zh/vod/user-guide/video-watermarks?spma2c4g.11186623.0.i2 原来的业务代码都是使用python 对oss的 视频进行上传 的,上传的视频路径已经保存到…

设计数据库之外部模式:数据库的应用

Chapter5:设计数据库之外部模式:数据库的应用 笔记来源:《漫画数据库》—科学出版社 设计数据库的步骤: 概念模式 概念模式(conceptual schema)是指将现实世界模型化的阶段进而,是确定数据库理论结构的阶段。 概念模…

系统架构设计-构建系统应用

1. 系统架构目标与设计原则 在设计系统架构时,我们的目标是确保系统具有以下特点: 可靠性:系统能够持续稳定运行,保证业务可用性。可伸缩性:系统能够根据负载变化自动扩展或收缩,以应对不同的流量需求。容…

【Java高级】利用反射机制获取类的所有信息

文章目录 1.相关准备2.导航图3. 相关的方法----------------------------------------------类------------------------------------------------------1 类的修饰符2 类名 -----------------------------------------------属性--------------------------------------------…

FileZilla 链接服务器提示 20 秒连接超时

FileZilla 有个默认设置是如果 20 秒没有数据的话会自动中断链接。 Command: Pass: **************** Error: Connection timed out after 20 seconds of inactivity Error: Could not connect to server修改配置 这个配置是可以修改的,修改的步骤为: …

保研复习概率论1

1.什么是随机试验(random trial)? 如果一个试验满足试验可以在相同的条件下重复进行、试验所有可能结果明确可知(或者是可知这个范围)、每一次试验前会出现哪个结果事先并不确定,那么试验称为随机试验。 …

零基础机器学习(4)之线性回归的基本原理

文章目录 一、线性回归的基本原理1.相关与回归2.线性回归的原理分析①线性回归的一般公式②线性回归的损失函数③线性回归方程的参数求解方法A.最小二乘法B.梯度下降法 一、线性回归的基本原理 1.相关与回归 相关描述的是变量之间的一种关系。 从统计角度看,变量之…

数据可视化-ECharts Html项目实战(5)

在之前的文章中,我们学习了如何设置滚动图例,工具箱设置和插入图片。想了解的朋友可以查看这篇文章。同时,希望我的文章能帮助到你,如果觉得我的文章写的不错,请留下你宝贵的点赞,谢谢 数据可视化-ECharts…

OpenLayers基础教程——WebGLPoints中要素样式的设置方法解析

1、前言 前一篇博客介绍了如何在OpenLayers中使用WebGLPoints加载海量数据点的方法,这篇博客就来介绍一下WebGLPoints图层的样式设置问题。 2、样式运算符 在VectorLayer图层中,我们只需要创建一个ol.style.Style对象即可,WebGLPoints则不…

【QT+QGIS跨平台编译】之九十:【QGIS_Crashhandler+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、QGIS_Crashhandler介绍二、QGIS下载三、文件分析四、pro文件五、编译实践一、QGIS_Crashhandler介绍 QGIS_Crashhandler模块是QGIS中的一个重要组成部分,它提供了QGIS程序的错误崩溃处理与跟踪。 二、QGIS下载 QGIS网址: QGIS Source Download 获取最新版本的…

iOS UIFont-新增第三方字体

背景 在项目中添加三方字体,是在开发中比较常见的需求,每次新增字体,都会遗忘其中某个步骤,又要去百度一下才能把字体添加使用成功。每次这样有点浪费时间和打击自信,于是便想着,自己好好来理一理新增字体…

ubuntu arm qt 读取execl xls表格数据

一,ubuntu linux pc编译读取xls的库 1,安装libxls(读取xls文件 电脑版) 确保你已经安装了基本的编译工具,如gcc和make。如果没有安装,可以使用以下命令安装: sudo apt-update sudo apt-get install build-essentia…

康奋威科技邀您到场参观2024长三角快递物流展

参展企业介绍 杭州康奋威科技股份有限公司创立于2005年,由国家“万人计划”专家任天挺先生创立并担任法人,是一家专业从事智能装备研发与制造的国家级高新技术企业。专注于自动化控制、机械设计、信息化方面的技术研究,主要为太阳能光伏、智…