【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.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面向切面编程的初步理解,内容有点复杂,逻辑有点乱,后续还会修改文章;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

Redis面试题:redis做为缓存,数据的持久化是怎么做的?两种持久化方式有什么区别呢?这两种方式,哪种恢复的比较快呢?

目录 面试官&#xff1a;redis做为缓存&#xff0c;数据的持久化是怎么做的&#xff1f; 面试官&#xff1a;这两种持久化方式有什么区别呢&#xff1f; 面试官&#xff1a;这两种方式&#xff0c;哪种恢复的比较快呢&#xff1f; 面试官&#xff1a;redis做为缓存&#xff…

【【Linux编程介绍之关键配置和常用用法】】

Linux编程介绍之关键配置和常用用法 Hello World ! 我们所说的编写代码包括两部分&#xff1a;代码编写和编译&#xff0c;在Windows下可以使用Visual Studio来完成这两部&#xff0c;可以在 Visual Studio 下编写代码然后直接点击编译就可以了。但是在 Linux 下这两部分是分开…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《前景导向的主动配电网智能储能软开关规划方法》

这个标题涉及到电力系统中的主动配电网&#xff08;Active Distribution Network&#xff09;以及与之相关的智能储能软开关的规划方法。下面是对标题中各个关键词的解释&#xff1a; 前景导向的&#xff08;Future-oriented&#xff09;&#xff1a; 这表明该方法是以未来发展…

球面的表面积

此推导需要用到重积分的知识&#xff0c;另外关于曲面的面积公式可以看我之前的博客

线性表,也是Java中数组的知识点!

线性表定义&#xff1a; 由n (n≥0)个数据特性相同的元素构成的有限序列称为线性表&#xff0c;(n0)的时候被称为空表。 线性表的顺序表示 线性表的顺序存储又被称为顺序表 优点 无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以随意读取任意位置的元素 缺点 插入…

【Mybatis】预编译/即时sql 数据库连接池

回顾 Mybatis是一个持久层框架.有两种方式(这两种方式可以共存) 1.注解 2.xml 一.传递参数 以使用#{} 来接受参数为例 (以上两种方式一样适用的) 1)传递单个参数 #{} 可以为任意名称 2)多个参数 默认的参数名称就是接口方法声明的形参 3)参数为对象 默认给每个对象的每个属性都…

中海油“海安杯”一站到底知识竞赛真的很有特色

中海油“海安杯”一站到底知识竞赛规格高&#xff0c;赛制复杂&#xff0c;天纵知识竞赛系统为此次知识竞赛提供了软件支持。本次竞赛设置选手区和擂台区两个区域。比赛共分为五个轮次&#xff0c;五个轮次选手区所有参赛选手均需答题。 第一轮&#xff1a;“脱颖而出” 所有参…

ruoyi-plus-vue docker 部署

本文以 ruoyi-vue-plus 5.x docker 部署为基础 安装虚拟机 部署文档 安装docker 安装docker 安装docker-compose 配置idea环境 上传 /doicker 文件夹 到服务器&#xff1b;赋值 777权限 chmod -R 777 /docker idea构建 jar 包 利用 idea 构建镜像; 创建基础服务 docker…

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

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

2017年11月16日 Go生态洞察:Go用户调查深度解析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

CSDN助手:一键下载CSDN博客:高效保存,随时阅读

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f3e1; 环境 &#x1f3e1;&#x1f4d2; 使用方法 &#x1f4d2;⚓️ 相关链接 ⚓️ &#x1f4d6; 介绍 &#x1f4d6; 这是我自己无聊的时候写的一个应用&#xff0c;以前UI有点丑&#xff0c;这次重写了一下UI 功能如下 …

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

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

Linux python安装 虚拟环境 virtualenv,以及 git clone的 文件数据, 以及 下资源配置

根目录创建 venvs 文件夹 sudo mkdir /venvs 进入 /venvs 目录 cd /venvsp 创建虚拟环境&#xff0c;前提要按照 python3 安装 的 命令 sudo apt install python3 sudo python3 -m venv 虚拟环境名 激活虚拟环境 source /venvs/zen-venv/bin/activate 安装flask pip install fl…

Java + openCV更换证件照背景色

最近在小红书上看到很多更换证件照背景色的需求&#xff0c;联想到以前自己也更换过证件照背景色而且还是付费的&#xff0c;碰巧最近在看一本书《JavaOpenCV高效入门》&#xff0c;于是查找资料&#xff0c;找到了通过技术解决这个需求的办法。 先看效果图&#xff08;图片来自…

每日一题2023.11.26——个位数统计【PTA】

题目要求&#xff1a; 输入格式&#xff1a; 每个输入包含 1 个测试用例&#xff0c;即一个不超过 1000 位的正整数 N。 输出格式&#xff1a; 对 N 中每一种不同的个位数字&#xff0c;以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。…

设备树是什么?

设备树&#xff1a; 设备树DTS(Device Tree Source) 描述设备信息的独立的文件。 为什么要引入设备树&#xff1f; 随着芯片的发展&#xff0c;Linux内核中就包含着越来越多这些描述设备的代码&#xff0c;导致Linux内核代码会很臃肿。因此引入了设备树文件&#xff0c;从…

Runloop解析

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

前端review

关于实时预览vs code中的颜色代码需要安装的插件&#xff0c;包括html文件格式中的颜色代码安装Flutter Color插件 VSCode 前端常用插件集合 1.Auto Close Tag自动闭合HTML/XML标签 2.Auto Rename Tag自动完成另一侧标签的同步修改 3.Beautify格式化代码&#xff0c;值得注…

Python武器库开发-前端篇之html概述(二十八)

前端篇之html概述(二十八) html概述 HTML5是构建Web内容的一种语言描述方式。HTML5是互联网的下一代标准&#xff0c;是构建以及呈现互联网内容的一种语言方式&#xff0e;被认为是互联网的核心技术之一。HTML产生于1990年&#xff0c;1997年HTML4成为互联网标准&#xff0c;…