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

news2024/11/28 2:49:10

目录

想要彻底理解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.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://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 {
    @Test
    public 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.coloradmin.cn/o/1254473.html

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

相关文章

HarmonyOS安装三方库遇到的问题

使用开发电脑系统为&#xff1a;MacOS, 开发工具为&#xff1a;DevEco-Studio版本号3.1.1 Release。在控制栏使用终端工具输入命令&#xff1a;ohpm install ohos/lottie遇到的第一个问题如下图。 解决方案&#xff1a; 1、在首选项中找到ohpm的安装路径。 2、打开bash_profil…

电子学会C/C++编程等级考试2022年06月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:小白鼠再排队 N只小白鼠(1 < N < 100),每只鼠头上戴着一顶有颜色的帽子。现在称出每只白鼠的重量,要求按照白鼠重量从小到大的顺序输出它们头上帽子的颜色。帽子的颜色用 “red”,“blue”等字符串来表示。不同的小白…

pyhon数据分析A股股票策略实际买卖总结(每月末更新数据)

简介 本篇文章主要记录python数据分析a股股票选股后实际买卖的记录。 选股策略 低位寻股&#xff0c;筛选出低位股价股票已经做过调整的股票&#xff0c;做短线交易&#xff08;不超过7天&#xff09;&#xff0c;不贪&#xff0c;小赚即走。分三个时段&#xff0c;开盘三十…

SSM企业风向管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 企业风向管理系统是一套完善的信息系统&#xff0c;结合springMVC框架完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库 &#xff0c;系统主要采用B/…

决策树(第四周)

一、决策树基本原理 如下图所示&#xff0c;是一个用来辨别是否是猫的二分类器。输入值有三个&#xff08;x1&#xff0c;x2&#xff0c;x3&#xff09;&#xff08;耳朵形状&#xff0c;脸形状&#xff0c;胡须&#xff09;&#xff0c;其中x1{尖的&#xff0c;圆的}&#xf…

***利用SecureCRT上传、下载文件(使用sz与rz命令)

使用SecureCrt连接到服务器。 1、上传文件&#xff1a;rz命令 输入“rz”&#xff0c;回车&#xff0c;在弹窗的文件选择框中选择本地磁盘中需要上传的文件&#xff0c;点击【Add】按钮&#xff0c;再点击传输指令即可。 注意&#xff08;如果没有权限不可能成功&#xff0c;…

Runloop解析

RunLoop 前言 ​ 本文介绍RunLoop的概念&#xff0c;并使用swift和Objective-C来描述RunLoop机制。 简介 ​ RunLoop——运行循环&#xff08;死循环&#xff09;&#xff0c;它提供了一个事件循环机制在程序运行过程中处理各种事件&#xff0c;例如用户交互、网络请求、定…

ps5ps4游戏室如何计时?计费系统怎么查看游戏时间以及收费如何管理

ps5ps4游戏室如何计时&#xff1f;计费系统怎么查看游戏时间以及收费如何管理 1、ps5ps4游戏室如何计时&#xff1f; 下图以佳易王计时计费软件V17.9为例说明 在开始计时的时候&#xff0c;只需点 开始计时按钮&#xff0c;那么开台时间和使用的时间长度项目显示在屏幕上&am…

Pure-Pursuit 跟踪五次多项式轨迹

Pure-Pursuit 跟踪五次多项式轨迹 考虑双移线轨迹 X 轴方向位移较大&#xff0c;机械楼停车场长度无法满足 100 ~ 120 m&#xff0c;因此采用五次多项式进行轨迹规划&#xff0c;在轨迹跟踪部分也能水一些内容 调整 double_lane.cpp 为 ref_lane.cpp&#xff0c;结合 FrenetP…

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试(1)

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试&#xff08;1&#xff09; 进行了多组实验&#xff0c;包括顺逆时针转向&#xff0c;直线圆弧轨迹行驶&#xff0c;以及Pure-Pursuit 轨迹跟踪测试 代码修改 需要修改的代码并不多&#xff0c;主要对 gps_sensor 功能包和…

蓝桥杯每日一题2023.11.26

题目描述 奖券数目 - 蓝桥云课 (lanqiao.cn) 将每一个数字进行一一枚举&#xff0c;如果检查时不带有数字4则答案可以加1 #include<bits/stdc.h> using namespace std; int ans; bool check(int n) {while(n){if(n % 10 4)return false;n / 10; }return true; } int m…

基于Haclon的标签旋转项目案例

项目要求&#xff1a; 图为HALCON附图“25interleaved_exposure_04”&#xff0c;里面为旋转的二维码标签&#xff0c;请将其旋转到水平位置。 项目知识&#xff1a; 在HALCON中进行图像平移和旋转通常有以下步骤&#xff1a; &#xff08;1&#xff09;通过hom_mat2d_ident…

<JavaEE> Thread线程类 和 Thread的常用方法

目录 一、Thread概述 二、构造方法 三、常用方法 1.1 getId()、getName()、getState()、getPririty() 1.2 start() 1.3 isDaemon()、setDaemon() 1.4 isAlive() 1.5 currentThread() 1.6 Interrupt()、interrupted()、isInterrupted() 1.6.1 方法一&#xff1a;添加共…

基于Haclon的图形镜像案例

项目要求&#xff1a; 图为HALCON的例图“green-dot”&#xff0c;请将其中的圆形图案按水平和垂直两个方向分别进行镜像。 项目知识&#xff1a; 首先要用BLOB分析的方法&#xff0c;得到圆形图案的目标区域&#xff0c;再对其进行镜像。 在HALCON中与镜像相关的算子为mirr…

跟着chatgpt学习|1.spark入门

首先先让chatgpt帮我规划学习路径&#xff0c;使用Markdown格式返回&#xff0c;并转成思维导图的形式 目录 目录 1. 了解spark 1.1 Spark的概念 1.2 Spark的架构 1.3 Spark的基本功能 2.spark中的数据抽象和操作方式 2.1.RDD&#xff08;弹性分布式数据集&#xff09; 2…

实战oj题——括号匹配问题

前言&#xff1a;前面我们已经做了一些关于顺序表和链表的oj题&#xff0c;今天我们就来解决一些有关于栈和队列的oj题。 我们对这个题看起来毫无头绪&#xff0c;但是我们刚学习了栈&#xff0c;就可以用栈来解决这一类问题&#xff0c;如果我们读取到左括号就入栈&#xff0c…

Cache学习(3):Cache地址映射(直接映射缓存组相连缓存全相连缓存)

1 Cache的与存储地址的映射 以一个Cache Size 为 128 Bytes 并且Cache Line是 16 Bytes的Cache为例。首先把这个Cache想象成一个数组&#xff0c;数组总共8个元素&#xff0c;每个元素大小是 16 Bytes&#xff0c;如下图&#xff1a; 现在考虑一个问题&#xff0c;CPU从0x0654…

再见 Pandas,再见算法

大家好,《再见pandas》 系列已有200多位朋友加入学习了,这段时间亲眼见证了很多朋友的飞跃进步,从无到有,从一个问问题的小白到开始慢慢回答别人的问题,在讨论和练习中不断成长。虽说pandas已经很普及了,但普及内容的深度却远远不够。 下面这套原创图文是我和几位小伙伴…

深入了解 Pinia:现代 Vue 应用的状态管理利器

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

手把手教你如何在Linux下写进度条小程序(附源码)

效果展示 录屏2023 一、建立文件 mkdir ProgressBar //在当前目录下&#xff0c;建立新的目录 cd ProgressBar //进入这个目录 touch main.c makefile progressbar.c progressbar.h //在ProgressBar这个目录建立这几个文件进入ProgressBar这个目录之后&#xff0c;使…