Spring AOP原理详解及实例

article/2025/9/18 10:18:50

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 can't find referenced pointcut……

观前提示:

本文所使用的Eclipse版本为Photon Release (4.8.0),IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141,Tomcat版本为9.0.12。

1.Spring AOP简介

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
在这里插入图片描述

2.AOP与OOP对比

AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。

AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

上面的陈述可能过于理论化,举个简单的例子,对于“雇员”这样一个业务实体进行封装,自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。

同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP对一个动作进行封装,则有点不伦不类。

换而言之,OOD/OOP面向名词领域,AOP面向动词领域。

3.AOP使用场景

AOP用来封装横切关注点,具体可以在下面的场景中使用:

  1. Authentication 权限

  2. Caching 缓存

  3. Context passing 内容传递

  4. Error handling 错误处理

  5. Lazy loading 懒加载

  6. Debugging 调试

  7. logging, tracing, profiling and monitoring 记录跟踪 优化 校准

  8. Performance optimization 性能优化

  9. Persistence 持久化

  10. Resource pooling 资源池

  11. Synchronization 同步

  12. Transactions 事务

4.AOP相关概念

  1. 切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。

  2. 连接点(Joinpoint): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。

  3. 通知/增强(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。spring aop advice的类型:
    1、前置通知(before advice),在目标方法执行之前执行。
    2、返回后通知(after returning advice),在方法正常执行结束之后的通知,可以访问到方法的返回值。
    3、抛出异常后通知(after throwing advice),在目标方法出现异常时执行的代码,可以访问到异常对象,且可以指定出现特定异常执行此方法。
    4、后置通知:(after[finally] advice),在目标方法执行之后执行(无论是否发生异常)。
    5、环绕通知:(around advice),可以实现上述所有功能。

  4. 切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

  5. 引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口

  6. 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

  7. AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

  8. 织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

5.AOP实例

需要的jar包:Jar包链接详情点我

需要的jar包
aspectjrt-1.9.2.jar、aspectjweaver-1.9.2.jar
在这里插入图片描述

5.1 基于xml配置方式

这里我使用的是Eclipse

目录结构
在这里插入图片描述
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><bean id="userService" class="cn.com.demo.service.UserService"/><bean id="logAopDemo" class="cn.com.demo.aop.LogAop"/><!-- 面向切面编程 --><aop:config><aop:aspect ref="logAopDemo"><!-- 定义切点 --><aop:pointcut expression="execution(* *..*(..))" id="pointCut"/><!-- 声明前置通知 (在切点方法被执行前调用)--><aop:before method="beforeAdvice" pointcut-ref="pointCut"/><!-- 声明后置通知 (在切点方法被执行后调用)--><aop:after method="afterAdvice" pointcut-ref="pointCut"/></aop:aspect></aop:config>
</beans>

注:aop:aspect 子节点还可配置

<aop:config><aop:aspect ref="logAopDemo"><!-- 定义切点 --><aop:pointcut expression="execution(* *..*(..))" id="pointCut"/><!-- 声明前置通知 (在切点方法被执行前调用)--><aop:before method="beforeAdvice" pointcut-ref="pointCut"/><!-- 声明后置通知 (在切点方法被执行后调用)--><aop:after method="afterAdvice" pointcut-ref="pointCut"/><aop:after-returning method="aferReturning" pointcut-ref="pointCut"/><aop:after-throwing method="aferThrowing" pointcut-ref="pointCut"/><aop:around method="around" pointcut-ref="pointCut"/></aop:aspect></aop:config>

日志类LogAop.java

package cn.com.demo.aop;public class LogAop {public void beforeAdvice() {System.out.println("beforeAdvice");}public void afterAdvice() {System.out.println("afterAdvice");}
}

UserService.java

package cn.com.demo.service;public class UserService {public void insertUser() {System.out.println("插入用户成功");}public boolean updateUser() {System.out.println("更新用户成功");return true;}
}

测试类TestAop

package cn.com.demo.test;import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.com.demo.service.UserService;public class TestAop {private ClassPathXmlApplicationContext ac;@Beforepublic void before() {ac = new ClassPathXmlApplicationContext("*/applicationContext.xml");}@Testpublic void test() {try {UserService userService = (UserService) ac.getBean("userService");userService.insertUser();userService.updateUser();} catch (Exception e) {e.printStackTrace();}}
}

测试结果
在这里插入图片描述

5.2 基于注解配置方式

这里我使用的是Eclipse

目录结构
在这里插入图片描述
applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><bean id="userService" class="cn.com.demo.service.UserService"/><!-- 启用注释驱动自动注入 --><!-- <context:annotation-config/> --><!-- 配置自动扫描的包 --><context:component-scan base-package="cn.com.demo"></context:component-scan><!-- 开启aop注解方式,此步骤不能少,这样java类中的aop注解才会生效 --><aop:aspectj-autoproxy/>
</beans>

<aop:aspectj-autoproxy/>为开启aop注解方式,此步骤必不能少,这样java类中的aop注解才会生效。
日志类LogAop.java

package cn.com.demo.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Component
@Aspect
public class LogAop {@Pointcut("execution(* cn.com.demo.service.UserService.insertUser(..))")public void ponitCut() {}@Before("ponitCut()")public void beforeAdvice() {System.out.println("beforeAdvice");}@After("ponitCut()")public void afterAdvice() {System.out.println("afterAdvice");}//环绕通知。注意要有ProceedingJoinPoint参数传入@Around("ponitCut()")public void around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("注解类型环绕通知..环绕前");pjp.proceed();//执行方法System.out.println("注解类型环绕通知..环绕后");}
}

UserService.java

package cn.com.demo.service;public class UserService {public void insertUser() {System.out.println("插入用户成功");}public boolean updateUser() {System.out.println("更新用户成功");return true;}
}

测试类TestAop

package cn.com.demo.test;import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.com.demo.service.UserService;public class TestAop {private ClassPathXmlApplicationContext ac;@Beforepublic void before() {ac = new ClassPathXmlApplicationContext("*/applicationContext.xml");}@Testpublic void test() {try {UserService userService = (UserService) ac.getBean("userService");userService.insertUser();} catch (Exception e) {e.printStackTrace();}}
}

运行结果
在这里插入图片描述

5.3 @AspectJ切点函数

参考文章:@AspectJ切点函数详解

6.可能出现的问题及解决方法

6.1 java.lang.IllegalArgumentException: error at :: 0 can’t find referenced pointcut……

如果出现如下错误:
在这里插入图片描述
可能是你的aspectjweaver和aspectjrt与你的jdk版本不匹配。


http://chatgpt.dhexx.cn/article/SrZuLCAJ.shtml

相关文章

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类在实例…

IIS 配置网站出现500内部服务器错误,显示具体错误信息

1、打开IIS 找到如下图的部分&#xff0c;双击点开 2、点开之后找到如下图部分&#xff0c;点击 3、选择如下图部分&#xff0c;然后点击确定。 4、这个时候页面会出现详细的错误&#xff0c;如果没有出现详细错误&#xff0c;配置如下图部分&#xff0c;不勾选。 5、这时会出现…

Nextcloud 内部服务器错误解决

在部署nextcloud过程中最后登录页面时出现内部服务器错误&#xff0c;心态当时就炸了。 在网上找了各种方案&#xff0c;但是大部分博主都告诉我是/var/lib/php/session/属组的权限问题&#xff0c;或者web目录的权限不对。但是对我这个问题没有用。 我把他们的方案贴出来对你…

IDEA中HTTP500 - 内部服务器错误类型 在 [] 行处理 [/.jsp] 时发生异常情况;java.lang.NoSuchMethodError: com.Bean.Person.setId

问题&#xff1a; HTTP状态 500 - 内部服务器错误 类型 异常报告 消息 在 [65] 行处理 [/pages/el 5/elDataDemo2.jsp] 时发生异常 描述 服务器遇到一个意外的情况&#xff0c;阻止它完成请求。 例外情况 org.apache.jasper.JasperException: 在 [65] 行处理 [/pages/el 5/elDa…

HTTP状态 500 - 内部服务器错误:No converter found for return value of type: class xxx(简单分析及解决)

问题描述 以下内容基于ssm框架&#xff0c;当我们向tomcat服务器发起请求时&#xff0c;出现如下的错误状态提示–500。 Tomcat日志信息&#xff1a; 原因分析&#xff1a; 未找到类型返回值的转换器&#xff1a;类 com.ssm.utils.Msg&#xff0c;使用jackson绑定数据时出现…

阿里云服务器出错500 - 内部服务器错误

阿里云服务器部署并发布成功后&#xff0c;访问该网页时出错&#xff0c;报 500 - 内部服务器错误。 原因&#xff1a;1.http 500内部服务器错误说明IIS服务器无法解析ASP代码&#xff0c;如果你联网还发现找不到服务器就是500错误了. 2.在安装Framework v4.0之后&#xff0c…

HTTP 500 - Internal Server Error 服务器内部错误

php出现如下错误 原因是出现了中文字符 修改后&#xff0c;页面成功访问

500错误及服务器内部错误

500错误及服务器请求错误 一、简言&#xff1a;500错误代表着你请求的后端或者说服务器端出现了错误。 可能的原因非常多&#xff0c;因为很多程序内部都会把代码运行出现的错误捕捉然后直接返回一个“服务器内部错误500”&#xff0c;这也就导致了我们在前端发送请求时见到的…

远程服务器返回错误: (500) 内部服务器错误解决办法

在.net中发送 xml post请求和接受xml 的post请求时&#xff0c;经常会遇到“远程服务器返回错误: (500) 内部服务器错误”。 这里有2种解决办法&#xff1a; 第一种方法&#xff1a;修改请求端Content-Type 为“text/xml”(httpclient.Headers.Add("Content-Type",…

服务器错误500-内部服务器错误。您查找的资源存在问题,因而无法显示。

当我们用iis环境搭建的网站出现了服务器错误500错误时我们该怎么处理呢&#xff0c;小编的网站织梦网站就出现了服务器错误 500 - 内部服务器错误。 您查找的资源存在问题&#xff0c;因而无法显示这个问题&#xff0c;如下图所示。织梦网站后台登陆前台预览都是正常的&#x…