浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 浅谈Spring的相关概念性问题 IOC DI AOP 工厂模式 单例

在我的理想观点中,软件的开发分为前端开发和后端开发;前端开发就是用Vue、Ext等JavaScript框架做出各种华丽的界面,直接面向用户,把用户的相关操作转化成指定形式,发给后端;后端开发就是从前端接取数据,对数据库进行增删改查。

其实一年前老师就让我们接触一下SSM框架,可那时的我还在沉迷Java的文件读写、GUI那一块,还有就是微信公众号。我在前几天看着视频学者搭建了SSM的开发环境,大致看懂了代码,然后翻博客,找知乎,初步理解了SSM中一些概念性问题,这里做一个整理。

Spring本质上是一个库,它提供了软件框架的功能,使软件之间的逻辑更加清晰,配置更灵活,Spring使用AOP和IoC,而AOP和IoC是一种思想。

在总结的时候可能用到其他博客的内容,参考网址写在最后面。

 

IOC 控制反转

书本定义

原先需要实现的对象创建、维护对象间的依赖关系,反转给容器帮忙实现。

看不懂很正常,请接着看下去

应用背景

采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。

例如我们家里挂的时钟,秒针转一圈之后,分针转一小格;同理分针转一圈,时针转一大格。

在面向对象编程中,即当秒针转了一圈的时候,秒针对象就要new一个分针对象,然后让分针的值+1,然后秒针的值归零。我们可以看出,秒针对象的正常运行需要分针对象,我们可以说是一种依赖关系,即秒针依赖于分针。(假设对象为单例)

如果我们打开时钟的后盖,就会看到与上面类似的情形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。上图中描述的就是这样的一个齿轮组,它拥有多个独立的齿轮,这些齿轮相互啮合在一起,协同工作,共同完成某项任务。我们可以看到,在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转。

面向对象编程中的“耦合关系”,就好比齿轮组中齿轮之间的啮合关系。对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。但是,伴随着编程开发的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。

所以我们必须要想办法优化这一个方面,即所谓实现对象之间的“解耦”,它是为了解决对象之间的耦合度过高的问题。好了,IOC这就来了。

IOC是什么

借助于“第三方”实现具有依赖关系的对象之间的解耦

spring IOC容器负责创建Bean,并通过容器将Bean注入到需要Bean的对象上。

还是刚刚的例子,由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系。

这时候,A、B、C、D这4个对象之间已经没有了耦合关系了,秒针转了一圈,只需要告诉IOC容器,我转了一圈了,IOC就会把分针的值加1;这样的话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,参与开发的每一成员只要实现自己的事情就可以了,别人的跟我没有任何关系

具体实现

还是刚刚的例子,设对象A为时钟的秒针,对象B是时钟的分针。

软件系统在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。在引入IOC容器之后,这种情形就完全改变了。由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了。


就比如,我们是如何找女朋友的?大学里,我们会到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、微信、电话……,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是很繁琐的,我们要在需要谈恋爱的时候,去手动new一个出来。传统的编程开发也是这样,在一个对象中,如果要使用另外的对象,就必须自己new一个,使用完之后还要将对象销毁。

那么有了IOC之后,有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚介。婚介管理了很多男男女女的资料,我可以向婚介告知一个需求,告诉它我想找个什么样的女朋友,比如身高一米七,等等等等,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。

DI 依赖注入

通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

通俗来讲,在软件系统运行过程中,对象A需要依赖对象B的时候,IOC容器动态的向对象A传输它需要的对象B这个传输的过程叫做注入,注入了什么?就是注入了依赖,所以全称叫做依赖注入。

比如说对象A某个时候需要连接数据库(A需要依赖Connection),原本需要自己new一个Connection对象,有了IOC之后,我们只需要告诉IOC,我需要Connection;IOC会在适当的时候创建Connection对象,至于什么时候创建,则么创建,不需要让对象A知道。那么IOC在向对象A传递Connection对象,我们叫做注入,就好比打针一样,把Connection对象注入到对象A中。

还有一个概念——反射:它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性。

spring就是通过反射来实现依赖注入的。

单例模式

即一个类实例化的对象唯一,例如Windows中的任务管理器,只能打开一个。具体可通过相关代码来实现,比如在类内部实例化私有对象,通过public方法调用该对象。

简单工厂模式

实质是由一个工厂类根据传入的参数, 动态决定应该创建哪一个产品类,就是暴力的if-else。原先是通过new方法实例化,现在只需要实例化一个工厂类,传入一个参数告诉工厂类你要什么,就可以获取你要的对象。比如传入一个"dog"字符串,返回给你一个狗对象。

工厂模式

假设有10个产品,那么该工厂模式有1个抽象父类工厂Factory(可以是接口、抽象类、具体类),该父类包含未实现工厂方法;接着有10个具体工厂子类,一一对应这10个产品类,因为父类工厂Factory未实现的工厂方法由子类来负责实现,不同具体工厂子类可以创建不同具体产品。工厂模式使得一个类的实例化延迟到其子类。

Spring Bean 的创建是典型的工厂模式, 这一系列的 Bean 工厂, 也即 IOC 容器为开发者管理对象间的依赖关系提供了很多便利和基础服务, 在 Spring 中有许多的 IOC 容器的实现供用户选择和使用。

 

AOP面向切面编程

书面定义

AOP就好比一把刀,在程序运行的时候,可以随意的插入和拔出,在插入拔出的位置(切面)可以为所欲为,比如记录日志等。利用AOP可以实现对业务逻辑的各个部分进行分离,降低耦合度。

解析

就比如上图,当我们在手机银行APP进行取款、查询、转账的时候,都会先让你验证身份吧,我们可以把这个“验证身份”过程提取出来,即画一个类似“切面”的绿线。即在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面

那么我们能不能把这个公共功能提取出来,包装一下呢?有了AOP之后,我们可以先把主要流程写完,然后反过来在另一个地方写验证身份的代码,然后告诉Spring要插入到哪些地方即可,而不需要你自己Copy过去。

AOP的主要思想是先实现程序的整体框架,然后再具体的编写每个部分的详细代码,最后插到整体框架里面


比如1个main函数调用了100个方法,现在要求在执行调用方法之前输出一句日志

最暴力的方法就是每个方法复制粘贴syso即可。

采用面向对象思想,就是编写一个日志打印方法,该方法执行这些日志打印操作,然后在每个业务方法之前加入这句方法调用

但是如果要求我们在业务方法结束时再打印一些日志呢,是不是还要去每个业务方法结束时加一遍?这样始终不是办法,而且我们总是在改业务方法,在业务方法里面掺杂了太多的其他操作,侵入性太高。这时候AOP就起到作用了,我们可以编写一个切面类(Aspect),在其中的方法中来编写横切逻辑(如打印日志),然后通过配置或者注解的方式来声明该横切逻辑起作用的位置,从而不需要改变原先代码即可实现所需要的功能。

 

实现方式

Spring AOP采用的是JDK动态代理,在运行期间对业务方法进行增强,所以不会生成新类。

 

参考网址列表:

参考网址1

参考网址2

参考网址3


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
18天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
39 2
|
1月前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
40 0
|
2月前
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
40 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
2月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
80 0
|
2月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
54 0
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
230 2
|
5天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
46 14
|
28天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
46 1
SpringBoot入门(7)- 配置热部署devtools工具
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
44 2
 SpringBoot入门(7)- 配置热部署devtools工具