浅谈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日志并进行多维度分析。
目录
打赏
0
0
0
0
397
分享
相关文章
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
169 26
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
159 6
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
10天前
|
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
23 0
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——什么是AOP
本文介绍了Spring Boot中的切面AOP处理。AOP(Aspect Oriented Programming)即面向切面编程,其核心思想是分离关注点。通过AOP,程序可以将与业务逻辑无关的代码(如日志记录、事务管理等)从主要逻辑中抽离,交由专门的“仆人”处理,从而让开发者专注于核心任务。这种机制实现了模块间的灵活组合,使程序结构更加可配置、可扩展。文中以生活化比喻生动阐释了AOP的工作原理及其优势。
26 0
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
138 25
|
1月前
|
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
96 24
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
121 8
|
6月前
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
135 1
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
713 1
什么是AOP面向切面编程?怎么简单理解?