【Spring篇】spring核心——AOP面向切面编程

目录

想要彻底理解AOP,我觉得你的先要了解框架的模块化思想,为此先记录框架在讲AOP

什么是java框架?为什么要出现框架?

我总结以下七点来讲述和帮助理解java框架思想 

什么是AOP?

如何理解上面这句话呢?

最重要的来了,什么是面向切面编程?

我们现在将横向的关注点剥离成了一个一个的切面,呢我们如何用代码把切面织入进去呢?

呢么现在就有了新的问题:什么是AspectJ框架?他在AOP编程中起到了什么作用?

知道了概念之后我们开始使用

Spring AOP的实现原理

最后概念化AOP


想要彻底理解AOP,我觉得你的先要了解框架的模块化思想,为此先记录框架在讲AOP

什么是java框架?为什么要出现框架?

在我开始接触java框架知识后,我发现所谓的java框架就是把原本的一个整体分成了一小块一小块的部分,有种模块化思想,就是将分工变得更加明确,专业的人负责专门的事,让程序员更加专注于业务本身,将什么事务操作、日志操作抽取出去,模块化成一个小整体去专门负责做,然后将这个小整体做好后,像堆积木一样堆到事务该出现的位置,然后让一块一块的小积木堆成一个搭积;

我总结以下七点来讲述和帮助理解java框架思想 

  1. 模块化思想: 框架通常采用模块化设计,将系统拆分成独立的功能模块。每个模块专注于特定的功能或关注点,如数据库访问、事务管理、日志记录、安全性等。这种模块化思想使得系统更易于理解、扩展和维护。

  2. 分工明确: 各个模块由专业的开发者或团队负责,这样可以充分发挥每个人的专业技能。例如,数据库模块由专门的数据库开发者负责,日志模块由专门的日志开发者负责。这种分工使得开发过程更加高效,同时降低了系统的复杂性。

  3. 抽象和封装: 框架通过抽象和封装隐藏了底层的复杂性,提供了高层次的接口供开发者使用。这样,开发者在使用框架时不需要关心底层的实现细节,只需关注业务逻辑的实现。这种抽象和封装有助于提高代码的可读性和可维护性。

  4. 面向切面编程(AOP): AOP 是一种重要的框架设计思想,它允许将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来。例如,事务管理、安全性、日志记录等关注点可以被模块化成切面,然后通过AOP织入到业务逻辑中。这使得系统的关注点更加清晰,同时避免了代码重复。

  5. 依赖注入(DI): 框架通常使用依赖注入来管理组件之间的依赖关系。这样,开发者不需要手动创建和管理对象之间的关系,而是由框架负责。DI提高了代码的灵活性和可测试性。

  6. 约定优于配置(Convention over Configuration): 框架倡导使用一些默认约定,减少配置的复杂性。通过约定,开发者只需要配置那些与默认约定不一致的部分,减少了样板代码的编写,提高了开发效率。

  7. 开放封闭原则: 框架遵循开放封闭原则,允许系统扩展而不需要修改已有的代码。新的功能通过扩展现有的模块或添加新的模块来实现,而不是修改已有的代码。这种原则有助于保持系统的稳定性和可维护性。

 框架就是为了让一个复杂代码的逻辑更加清晰,分工更加明确;

什么是AOP?

        Spring有两个极其重要的核心概念,一个是IOC/DI,另一个就是AOP呢么什么是AOP呢?刚刚已经总结过了,AOP 是一种重要的框架设计思想,它允许将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来。例如,事务管理、安全性、日志记录等关注点可以被模块化成切面,然后通过AOP织入到业务逻辑中(就好比搭积木)。这使得系统的关注点更加清晰,还增加了代码的复用性。

如何理解上面这句话呢?

        假设将我们编写的业务代码看成一个搭积木的过程,我们将交叉业务看成一个个小积木,当我们做完核心业务代码之后,然后将做好的小积木像搭积木一样,加入已经做好的小积木块,这样就避免了我们程序员在编写主要业务逻辑时,还要考虑数据库事务啊,访问数据库啊等,其他和业务无关的逻辑,让我们程序员负责写订单生成的就只负责写订单生成,负责写数据库访问的就只负责写数据库访问,使的分工明确,结构清晰,最后拼在一起即可构成高楼大厦;

        这里的积木与积木之间是否能够拼在一起就能正常运行就涉及到解耦合思想了;

看上面这张图,我们将业务代码看成纵向的一个过程,将和业务主要代码无关的代码,如事务管理、安全性、日志记录等关注点可以被模块化成小积木块,等需要这些的时候,像刀一样横向的插入进去,然而能够把一个整体抽象成模块化的思想就是AOP的主要思想;


最重要的来了,什么是面向切面编程?

        我们把事务管理、安全性、日志记录等和主从业务无关的关注点看成一个一个的切面,将他们从主要业务逻辑中分离出来。然后在需要用到他们的地方再将他们织入进去,当然这需要完全的解耦合;


我们现在将横向的关注点剥离成了一个一个的切面,呢我们如何用代码把切面织入进去呢?

呢我们就要说到spring对AOP的实现技术,AspectJ框架,实际开发中,都是Spring+AspectJ来实现AOP。

常用的Spring对AOP的实现包括以下2种方式:

  • 第一种方式:Spring框架结合AspectJ框架实现的AOP,基于注解方式。
  • 第二种方式:Spring框架结合AspectJ框架实现的AOP,基于XML方式。

依赖如下:

<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.0-M2</version>
</dependency>

呢么现在就有了新的问题:什么是AspectJ框架?他在AOP编程中起到了什么作用?

AspectJ是一个基于Java的面向切面编程(AOP)框架,它提供了一种强大的方式来实现横切关注点的模块化。我们刚刚不是已经将关注点剥离成了切面吗?呢JVM怎么知道你就是切面呢他怎么知道这个切面要放到哪里呢,还有他怎么就知道代码执行到一半还要先执行切面呢?AspectJ的作用就出来了;

在AOP中,AspectJ主要起到以下作用:

  1. 切面定义: AspectJ允许开发者定义切面,切面是横切关注点的模块化单元。切面通常包含一组通知(advice)以及切点(pointcut)的定义。

  2. 通知(Advice): 通知是切面中的代码块,它定义了在目标方法的哪个时机执行。AspectJ支持五种类型的通知:前置通知(Before advice)、后置通知(After advice)、返回通知(After-returning advice)、异常通知(After-throwing advice)和环绕通知(Around advice)。

  3. 切点(Pointcut): 切点定义了在目标类中的哪些位置执行通知。AspectJ允许开发者使用表达式来定义切点,从而选择性地将通知应用到目标类的特定方法或代码块

  4. 连接点(Join point): 连接点是在程序执行过程中可以插入切面的点。AspectJ将切点看作连接点,并在连接点上执行相应的通知。

  5. 织入(Weaving): 织入是将切面与目标类或对象关联的过程。AspectJ使用编译时织入、类装载时织入和运行时织入等方式来将切面织入到目标代码中。

  6. 增强(Introduction): AspectJ允许通过引入(Introduction)在不修改目标类代码的情况下为类添加新的方法或字段。这对于为已有的类添加新的行为非常有用。

  7. 类型匹配和织入控制: AspectJ提供了丰富的类型匹配和织入控制的功能,允许开发者精确地指定切面的应用范围。

总体而言,AspectJ通过定义切面、通知、切点等概念,使得开发者能够以一种更模块化和清晰的方式处理横切关注点。通过AspectJ,可以将与业务逻辑无关的关注点(如日志、事务、安全性等)独立出来,使得代码更易维护、扩展和理解


知道了概念之后我们开始使用

我们引入一个案例:一个订单生成业务,我们需要再订单生成方法执行前织入一个切面MyAspect ,添加一些增强代码:

// 目标类
@service
public class OrderService {// 目标方法public void generate(){System.out.println("订单已生成!");}
}

切面类:

// 切面类
@Aspect
@Component
public class MyAspect {// 切点表达式@Before("execution(* com.lypnode.spring.service.OrderService.*(..))")// 这就是需要增强的代码(通知)public void advice(){System.out.println("我是一个通知");}
}

 使用了AspectJ框架中的@Aspect这个注解之后,就表明这个类是个切面类,

spring.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启组件扫描--><context:component-scan base-package="com.lypnode.spring.service"/><!--开启自动代理--><aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

<aop:aspectj-autoproxy proxy-target-class="true"/> 开启自动代理之后,凡事带有@Aspect注解的bean都会生成代理对象。

proxy-target-class="true" 表示采用cglib动态代理。

proxy-target-class="false" 表示采用jdk动态代理。默认值是false。即使写成false,当没有接口的时候,也会自动选择cglib生成代理类。

关于cglib动态代理和jdk动态代理下面我们会说:

 测试类:

public class AOPTest {@Testpublic void testAOP(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");OrderService orderService = applicationContext.getBean("orderService", OrderService.class);orderService.generate();}
}

运行结果: 

 

通过上面的总结和代码我么可以知道,AOP底层是调用了动态代理技术的,呢么就会生成代理类,可见上面的代码中,看似在调用orderService类,实则调用的是动态生成的代理类

 至于代理类生成看我另一篇文章:

【Spring篇】JDK动态代理-CSDN博客


Spring AOP的实现原理

Spring的AOP实现原理其实很简单,就是通过动态代理实现的。Spring AOP 采用了两种混合的实现方式:JDK 动态代理和 CGLib 动态代理。

JDK动态代理:Spring AOP的首选方法。 每当目标对象实现一个接口时,就会使用JDK动态代理。目标对象必须实现接口
CGLIB代理:如果目标对象没有实现接口,则可以使用CGLIB代理。

Spring默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理。当然你也可以自己制定;

proxy-target-class="true" 表示采用cglib动态代理。

proxy-target-class="false" 表示采用jdk动态代理。默认值是false。即使写成false,当没有接口的时候,也会自动选择cglib生成代理类。

最后概念化AOP

AOP 是一种重要的框架设计思想,动态代理是其实现机制之一。在 AOP 中,可以通过动态代理将横切关注点与核心业务逻辑分离,使代码更易维护和理解。它允许将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来。例如,事务管理、安全性、日志记录等关注点可以被模块化成切面,然后通过AOP织入到业务逻辑中。这使得系统的关注点更加清晰,同时避免了代码重复。

AOP可以拦截指定的方法并且对方法进行增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离,比如数据库访问、事务管理、日志记录、安全性等。这种模块化思想使得系统更易于理解、扩展和维护。

将系统拆分成独立的功能模块。每个模块专注于特定的功能或关注点,如数据库访问、事务管理、日志记录、安全性等。这种模块化思想使得系统更易于理解、扩展和维护。


这是我对AOP面向切面编程的初步理解,内容有点复杂,逻辑有点乱,后续还会修改文章;

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

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

相关文章

提示工程-Prompt Engineering

提示工程 提示工程 1、概述 Prompt Engineering&#xff1a; 提示工程 通过自然语言&#xff08;英语、汉语等&#xff09;来给AI下达指示&#xff0c;从而让AI完成你指定给他的工作的过程都可以称之为提示工程。&#xff08;面向自然语言编程&#xff09; 提示词要素 指令&…

华硕V4050E笔记本安装Win10不识别硬盘解决方法

笔记本硬件参数&#xff1a; ASUS VivoBook14 V4050E 型 号 V4050EP1135-0DAKXQ2X10 制造日期 2020-12 12M C P U 11th Gen Intel(R)Core(TM)i5-1135G72.4GHz 2.42GHz 4核心 8线程 L2&#xff1a;5MB L3&#xff1a;8MB 内 存 16.0GB &#xff08;8Gb X2 320…

显示器校准软件BetterDisplay Pro mac中文版介绍

BetterDisplay Pro mac是一款显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 BetterDisplay Pro mac软件特点 - 显示器校准&#xff1a;可以根据不同的需求和环境条件调整显示器的颜色、亮度和对比度等参数…

BeanUtil的正确使用方式

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 在实际的开发中&#xff0c;我们常常会用到工具类去拷贝对象的属性&#xff0c;将一个对象的属性转换成另外一个…

【21年扬大真题】编写程序,通过指针p的改变,实现一维数组的输入及逆序输出

【21年扬大真题】编写程序&#xff0c;通过指针p的改变&#xff0c;实现一维数组的输入及逆序输出 例如&#xff0c;输入为1,2,3,4,5,6,7&#xff1b; 输出为7,6,5,4,3,2,1 法一&#xff1a;不改变原数组&#xff0c;仅逆序打印输出 #define _CRT_SECURE_NO_WARNINGS #includ…

Linux服务器SSH客户端断开后保持程序继续运行的方法

目录 1. nohup 命令&#xff1a; 2. tmux 或 screen&#xff1a; 3 final shell 断开后服务器如何继续执行令&#xff1f; 方法一&#xff1a;使用 nohup 命令 方法二&#xff1a;将命令放在后台执行 4 你可以使用 jobs 命令查看当前终端中正在后台运行的任务 &#xff…

rsyslog出现Unit rsyslog.service is masked不可用问题解决

博主在测试将日志发送到日志服务器的功能时遇到了rsyslog服务不可用的问题&#xff0c;具体来说&#xff0c;就是执行systemctl restart rsyslog或者 service rsyslog restart命令时&#xff0c;出现了标题中所述的Unit rsyslog.service is masked问题。网上查找了很多资料&…

使用VC++设计程序对一幅256级灰度图像进行全局固定阈值分割、自适应阈值分割

图像分割–全局固定阈值分割、自适应阈值分割 获取源工程可访问gitee可在此工程的基础上进行学习。 该工程的其他文章&#xff1a; 01- 一元熵值、二维熵值 02- 图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像以及图像的旋转 03-邻域平均平滑算法、中值滤波算法、…

【DevOps】基于 KubeSphere 的 Kubernetes 生产实践之旅(万字长文)

基于 KubeSphere 的 Kubernetes 生产实践 1.KubeSphere 简介1.1 全栈的 Kubernetes 容器云 PaaS 解决方案1.2 选型理由&#xff08;从运维的角度考虑&#xff09; 2.部署架构图3.节点规划3.1 软件版本3.2 规划说明3.2.1 K8s 集群规划3.2.2 存储集群3.2.3 中间件集群3.2.4 网络规…

【开源】基于Vue+SpringBoot的农家乐订餐系统

项目编号&#xff1a; S 043 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S043&#xff0c;文末获取源码。} 项目编号&#xff1a;S043&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户2.2 管理员 三、系统展示四、核…

Int8量化算子在移动端CPU的性能优化

本文介绍了Depthwise Convolution 的Int8算子在移动端CPU上的性能优化方案。ARM架构的升级和相应指令集的更新不断提高移动端各算子的性能上限&#xff0c;结合数据重排和Sdot指令能给DepthwiseConv量化算子的性能带来较大提升。 背景 MNN对ConvolutionDepthwise Int8量化算子在…

Elasticsearch集群部署 head监控插件 Kibana部署 Nginx反向代理 Logstash部署

一、组件介绍1、Elasticsearch&#xff1a;2 、Logstash3、Kibana4、Kafka&#xff1a;5、Filebeat: 二、 Elasticsearch集群部署服务器创建用户安装ES修改配置文件创建数据和日志目录设置JVM堆大小 #7.0默认为4G修改安装目录及存储目录权限系统优化&#xff08;1&#xff09;增…