Spring AOP原理和用法

article/2025/9/18 10:17:06

AOP也就是面向切面编程,首先AOP不等于Spring aop,前者是编程所要实现的目标,后者仅仅是AOP的实现方式之一,作为一种动态注入的实现方式,还有一些别的例如AspectJ(静态注入)等

一. Spring aop使用场景分析

Spring aop
如图是常规思维下一个登陆流程的实现,在登陆的流程中,每一步都不能发生任何错误(这里指的当然不是空指针这种RuntimeException),而是指的数据传输出现了错误,比如http传了一个name=a,但是controller却接收成了name=b,这样就会导致整个程序的出错
这一条自上而下的逻辑,可以理解为主逻辑,而每个部分可能都会有他们自己的切向的一些方法的调用
在这里插入图片描述
例如在进入controller的过程中,调用了一个f方法,而f方法作为一个日志,比方说记录了一个日志log,就是说我在什么时候调用了这个方法,作为一个记录,
然后进入service,又调用了f1方法,f1方法就是验证从上面传下来的用户名是否有权限对service进行调用,如果都验证成功了,则进入dao,dao自然记录的场景就是事务处理。
在这里插入图片描述
那么,为什么这些是作为切面?
因为这些内容和主逻辑没有关系,就是说无论日志记录的如何,权限验证如何,dao事务如何处理,和主逻辑一概没有关系,可能会有很多的切面,但都不影响主逻辑自己的运行,除非你主逻辑写错了tx

切面一般对如下内容进行封装,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可扩展性和可维护性

  • 事务
  • 权限处理
  • 日志
  • 性能检测
  • 异常处理

二.SpringAOP的常用术语

在这里插入图片描述
在spring framework的官方文档,地址添加链接描述,首先第一段话大致就是aop和oop的区别,阐述了面向切面编程和面向对象编程的联系

下面的术语来逐条看
Aspect中文翻译是切面,对于切面的理解,得结合后面的几点,总体来说就是join point, cut point和advice所在的类称之为切面。在这里插入图片描述

join point

连接点(join point),中文翻译大致意思是join point在spring aop中作为一种方法或者是对报错的处理。比如说刚举的例子,切面log是基于f方法的,而这个f方法就是连接点,我个人理解就是切面和主逻辑的连接处。

Advice

在这里插入图片描述
也就是增强,为了实现log日志,得编写一些逻辑代码Logic,但此时,我们需要在不同的连接点编写代码,可以说advice决定了在原有方法功能中出现的位置和时机。可分为around before after

Pointcut

可以与任何join point点进行匹配,匹配后的位置就是切面的位置。

target object

顾名思义,目标对象
在这里插入图片描述
如上图,f方法里实现的m功能再进行一些修改后(或者说增强)实现了n功能,而target object,也就是基础对象,增强后的方法f,则是被存在代理对象proxy object中。

AOP Proxy

aop代理,也就是为了实现方法增强而编写的对象,编写方式有jdk动态代理等,在我的另一篇文章也有写到。

Weaving

编织,也就是把切面应用到目标对象来创建新的代理对象的过程。也就是把上图的target object通过切面穿件proxy object的过程。

三.Spring aop实现方式

第一步得输入依赖

 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency>

这方面我稍微了解了一下,aspectj其实是和spring aop一样,都是aop的一种实现方式,按理来说是竞争对手的关系,那这里为什么出现了Aspectj呢,而且在spring的官网上也能看到对aspectj的描述
在这里插入图片描述
我个人的了解是在spring aop诞生之初,想实现aop的操作非常复杂(具体怎么实现不知道 我那时候可能还在打dota) 后来是借助了Aspectj的样式,并取其精华,使用AspectJ为切入点解析和匹配提供的库解释与AspectJ 5相同的注释。具体可以详见sping.io官网
下面列举几个spring aop的实现方式

实现方式一(通过 Spring API 实现)

首先编写我们的业务接口和实现类,这里用一个简单的增删改查,配合之前一篇动态代理的笔记来理解。

public interface UserService {public void add();public void delete();public void update();public void search();
}
public class UserServiceImpl implements UserService{public void add() {System.out.println("增加用户");}public void delete() {System.out.println("删除用户");}public void update() {System.out.println("更新用户");}public void search() {System.out.println("查询用户");}
}

然后去写增强类 , 一个前置增强 一个后置增强,也就是advice里的语句,before和after

public class Log implements MethodBeforeAdvice {public void before(Method method,Object[] args,Object target)throws Throwable{System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");}
}
public class AfterLog implements AfterReturningAdvice {public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("执行了" + method.getName()+"的"+method.getName()+"方法,"+"返回值:"+o);}
}

然后去applicationContext.xml文件下注入,并实现aop切入

<bean id="userService" class="com.vincewang.service.UserServiceImpl"/><bean id="Log" class="com.vincewang.log.Log"/><bean id="afterLog" class="com.vincewang.log.AfterLog"/><aop:config><aop:pointcut id="pointcut" expression="execution(* com.vincewang.service.UserServiceImpl.*(..))"/><aop:advisor advice-ref="Log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config>

前面三行的bean注入就不解释了
而pointcut,就是切入点,expression就是表达式,execute执行,
execution(* com.kuang.pojo.UserServiceImpl.*(…))
解释:一开始的的意思就是所有文件,com.vincewang.service,UserServiceImpl就是切入在这个类里,
.就是当前类下的所有方法,(…)括号里的两个点代表可以是任意参数
execution的书写规范可以详见https://www.cnblogs.com/xbzg/p/4807092.html

(注意!一定要增加aop的约束

 http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd">

否侧会出现org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException这样的报错

现在就可以进测试类进行测试了

public class MyTest {@Testpublic void test(){ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService=(UserService)context.getBean("userService");userService.add();}
}

输出
在这里插入图片描述
这里可以很好的理解advice增强了,用before和after编写的语句都在输出里有很好的体现,分别出现在了原来的输出的前面和后面,但并没有改变UserServiceImpl类下的一兵一卒,完全是由两个增强类继承spring aop的接口,通过applicationContext.xml注入,就实现了aop的一种操作流程

实现方式二(自定义类来实现)

上面这种方法,可能程序复杂以后就会出现记不住接口的情况
记录下第二种方法
首先创建一个diy的类 里面有两种方法

public class DiyPointCut {public void before(){System.out.println("-----方法执行前-----");}public void after(){System.out.println("-----方法执行后-----");}
}

然后进入applicationContext.xml进行配置

<bean id="userService" class="com.vincewang.service.UserServiceImpl"/>
<bean id="diy" class="com.vincewang.diy.DiyPointCut"/><aop:config><aop:aspect ref="diy"><aop:pointcut id="point" expression="execution(* com.vincewang.service.UserServiceImpl.*(..))"/><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config>

解释:
<aop:aspect ref=“diy”>
由上文可知 aspect是一个类 切面类 既然是类就有他所依赖的位置 位置在bean中已经注入为class="com.vincewang.diy.DiyPointCut,所以称为自定义切面,既然是切面就需要切入点Pointcut,和通过spring api方式实现的一样。然后就是advise增强,切入刚自定义的before和after方法,和他们的切入依赖point,也就是在point这个切入点之后定义了两个diy的方法。
输出
在这里插入图片描述

实现方式三(注解实现)

新建类

@Aspect
public class AnnotationPointCut {@Before("execution(* com.vincewang.service.UserServiceImpl.*(..))")
public void before(){System.out.println("------方法执行前------");
}
}

与之前不同,一开始得加上@Aspect注解,后面只要在方法名上面使用注解定义切入点即可

 <bean id="annocationpointcut" class="com.vincewang.diy.AnnotationPointCut"/><aop:aspectj-autoproxy/>

输出
在这里插入图片描述


http://chatgpt.dhexx.cn/article/01SAQVcO.shtml

相关文章

一篇文章详细解读Spring的AOP原理过程(Spring面向切面详解)

目录 概述 使用登录例子说明 AOP AOP&#xff08;底层原理&#xff0c;了解&#xff09; 有两种情况动态代理 第一种 有接口情况&#xff0c;使用 JDK动态代理 第二种 没有接口情况&#xff0c;使用 CGLIB 动态代理 回顾JDK静态代理 ①明星唱歌&#xff0c;经纪人替他签…

IOC/DI、AOP相关原理

文章目录 IOC/DI为什么IOC就降低了耦合性 AOP原理使用AOP的名词们概念性名词JoinPoint/TargetIntroductionProxyWeaving 在代码中有对应注解的名词AspectPointcut&#xff08;在哪儿切&#xff09;Advice&#xff08;什么时候切&#xff09; 示例代码 IOC/DI IOC全称是Inversio…

Spring——AOP原理及流程详解

AOP原理及流程详解 一、AOP结构介绍Pointcut通知原理连接点拦截器 二、Bean介入点EnableAspectJAutoProxyAspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreatorAbstractAutoProxyCreator实例前执行初始化后执行循环依赖会调用 总结 三、处理切面获取所有切面其下通…

Spring中的AOP原理

目录 0 为什么需要AOP 1 基本概念 2 AOP原理 2.1 JDK动态代理 2.2 CGLIB 动态代理 0 为什么需要AOP 现在有一个情景&#xff1a; 我们要把大象放进冰箱&#xff0c;步骤为&#xff1a;打开冰箱->放入大象->关闭冰箱 如果再把大象拿出来&#xff0c;步骤为&#x…

Spring AOP的实现原理 ?

Spring AOP的实现原理 ? - 知乎 AOP的实现&#xff0c;最关键的有两步&#xff1a; 得到代理对象利用递归责任链执行前后置通知及目标方法 IOC容器初始化时&#xff0c;对于涉及AOP操作的目标类&#xff0c;其实Spring返回的是代理对象&#xff0c;而不是目标类的实例。至于…

AOP理解及底层原理

AOP 基础概念 一、概述 银行系统的简易取款流程如图&#xff1a; 将方框里的流程合为一个&#xff0c;另外系统还会有一个查询余额流程&#xff0c;如图&#xff1a; 这两个业务有一个共同的验证流程&#xff0c;如图&#xff1a; 为什么会有面向切面编程(AOP)&#xff…

Spring AOP原理分析一次看懂

什么是AOP AOP&#xff08;Aspect-OrientedProgramming&#xff0c;面向方面编程&#xff09;&#xff0c;可以说是OOP&#xff08;Object-Oriented Programing&#xff0c;面向对象编程&#xff09;的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构&…

AOP-底层原理

申明&#xff1a;学习笔记整理&#xff0c;内容非原创&#xff0c;仅供参考学习&#xff01;视频详细地址如下&#xff1a; 尚硅谷Spring框架视频教程&#xff08;spring5源码级讲解&#xff09;_哔哩哔哩_bilibili 目录 一、AOP概念 二、AOP底层原理 三、JDK动态代理代码…

Spring AOP原理详解及实例

Spring AOP原理详解及实例 1.Spring AOP简介2.AOP与OOP对比3.AOP使用场景4.AOP相关概念5.AOP实例5.1 基于xml配置方式5.2 基于注解配置方式5.3 AspectJ切点函数 6.可能出现的问题及解决方法6.1 java.lang.IllegalArgumentException: error at :: 0 cant find referenced pointc…

JAVA AOP概念和实现原理 详解

// AOP 概念 1. 什么是AOP&#xff1f; // 面向切面&#xff08;方面&#xff09;编程 //利用AOP可以对业务逻辑的各个部分进行隔离&#xff0c;从而使得业务逻辑各部分之间的耦合度降低&#xff0c;提高程序的可重用性&#xff0c;同时提高了开发的效率 // 不通过修改源代码方…

Spring IOC和AOP 原理彻底搞懂

本博中关于Spring的文章&#xff1a;Spring IOC和AOP原理&#xff0c;Spring事务原理探究&#xff0c;Spring配置文件属性详解&#xff0c;Spring中的代理模式 Spring提供了很多轻量级应用开发实践的工具集合&#xff0c;这些工具集以接口、抽象类、或工具类的形式存在于Sprin…

spring AOP 原理

一、spring注册 AnnotationAwareAspectJAutoProxyCreator 通过EnableAspectJAutoProxy可以看到先把AspectJAutoProxyRegistrar通过Import注册到spring。 AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口&#xff0c;所以就有了将某个bean引入spring 的能力…

Spring的AOP实现原理

本学习笔记将尽可能的将AOP的知识讲解的通俗易懂&#xff0c;先从一个典型的问题出发&#xff0c;引入AOP这个概念&#xff0c;介绍AOP的基本概念&#xff0c;再到Spring中的AOP的实现方案&#xff0c;最后进行一个简单的总结归纳。本学习笔记中不考虑cglib、也不会太关注Sprin…

spring的AOP和IOC的原理

目录 一、spring的ioc与aop原理 二、代理模式&#xff1a; 三、静态代理 四、动态代理 五、实际的操作 六、动态代理的实现&#xff1a; 七、什么是AOP 八、主流的AOP框架&#xff1a; 九、术语&#xff1a; 十、通知的五种类型&#xff1a; 十一、AOP的优点&#x…

spring aop原理

&#x1f345; Java学习路线&#xff1a;搬砖工逆袭Java架构师 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、CSDN哪吒公众号作者✌ 、Java架构师奋斗者&#x1f4aa; &#x1f345; 扫描主页左侧二维码&#xff0c;加入群聊&#xff0c;一起学习、一起进步…

AOP原理

AOP原理 什么是AopAOP的作用AOP的基本概念AOP使用场景AOP原理如何动态修改功能AOP的编程思想AOP面向切面编程操作AOP通知执行的顺序代码执行流程准备工作源码揭开面纱 什么是Aop AOP&#xff08;Aspect Orient Programming&#xff09;也就是面向切面编程&#xff0c;作为面向对…

无法显示页面,因为发生内部服务器错误。

用iis添加网站后&#xff0c;访问域名&#xff0c;显示“无法显示页面&#xff0c;因为发生内部服务器错误。” 之前我将这些文件放在一个Demo文件夹中&#xff0c;把Demo放在test站点下&#xff0c;通过域名访问Demo报错。 我将Demo下的文件直接放在test下&#xff0c;访问成…

遇到“服务器内部错误http500怎么办?

出现500错误的原因是很多的&#xff0c;一般来说都是程序错误导致的&#xff0c;如果程序出错&#xff0c;那么在浏览器内会返回给用户一个友好的错误提示&#xff0c;统一称之为服务器500错误。 解决的方法就是您必须在http中能够正确的获得错误信息&#xff0c;方法为&#x…

500 - 内部服务器错误--解决方案

一般网上的方法是这样的&#xff1a; 一、打开 Internet 信息服务(IIS)管理器。点击出错的站点&#xff0c;并双击右边的ASP图标&#xff0c;如下图所示&#xff1a; 二、展开右侧配置中的“调试属性”&#xff0c;把“将错误发送到浏览器”的值设为 "true"&#xf…

HTTP状态 500 - 内部服务器错误 类型 异常报告,初学servlet遇到的问题

写给自己看&#xff0c;初学记录一下&#xff0c;maven项目中tomcat,Servlet遇到的问题 HTTP状态 500 - 内部服务器错误 类型 异常报告&#xff0c;初学servlet遇到的问题 类似这种报错&#xff0c;在hello world级别的servlet中碰到。 报错分析 大概是说自定义java类在实例…