当前位置: 首页 > news >正文

Spring AOP(XML配置版):代理机制与拦截器

本章节介绍AOP(面向切面编程)用于将日志、事务等横切逻辑从业务代码中解耦,通过代理机制在方法执行前后织入增强逻辑。

1.引入依赖

(1).创建maven依赖进行管理,引入以下依赖

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>spring-springaop-lon-boke</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>5.2.2.RELEASE</spring.version> <aspectj.version>1.9.6</aspectj.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!-- 3. AspectJ 织入器(仅引入一次,适配 Spring 5.2) --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> <scope>provided</scope> </dependency> <!-- 新增日志依赖:Logback(适配 Commons Logging) --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> </dependency> </dependencies> </project>

(2)创建Calculator类,如下图1-1 Calculator类:

public class Calculator { public void mySQL(){ System.out.println("数据库的相关逻辑!"); } }

图 1-1 Calculator类

(3).创建切面类Aspect1类如下图 1-2 Aspect1类:

public class Aspect1 { // 前置 public void test1(JoinPoint joinPoint){ System.out.println(joinPoint.getSignature()+"方法执行了!"); } // 后置 public void test2(JoinPoint joinPoint){ System.out.println(joinPoint.getSignature()+"方法执行完成!"); } // 返回 public void test3(JoinPoint joinPoint,Object o){ System.out.println(joinPoint.getSignature()+"方法执行了\n"+"执行结果是"+o); } // 异常 public void test4(JoinPoint jp,Throwable t){ String name=jp.getSignature().getName(); System.out.println(name+"方法,发生了异常:"+t.getMessage()); } // 环绕 public Object test5(ProceedingJoinPoint p){ String name=p.getSignature().getName();//获取方法的名字 try { System.out.println("环绕前"); Object o=p.proceed();//表示在调用目标方法,所以在这行代码之前的逻辑就相当于前置通知 // 这行代码后面的就相当与后置通知和返回通知 // 在catch里的逻辑就相当于异常通知 System.out.println("环绕后"); return o; } catch (Throwable e) { System.out.println("环绕异常"); throw new RuntimeException(e); } } }

图 1-2 Aspect1类

其中图 1-2 Aspect1类 中的环绕通知在逻辑上覆盖前置、后置、返回和异常四种通知能力,但需要手动控制执行流程。

其中有存在一个继承关系:JoinPoint(父类接口)--->ProceedingJoinPoint(子类接口)。

父类(JoinPoint):只能查看方法信息。

子类(ProceedingJoinPoint):可以“控制执行”。

核心方法 : X.proceed()。

SpringAOP是一个基于拦截器链实现的,执行时通过责任链逐层推进链路,X.proceed() 的作用是继续执行拦截器链,在合适的位置触发目标方法执行。

2.编写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: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"> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 创建切面类的bean--> <bean id="aspect" class="com.spring.lon.aop.Aspect1"/> <!-- 创建目标类--> <bean id="Caculator" class="com.spring.lon.aop.Calculator"/> <aop:config> <aop:pointcut id="aaa" expression="execution(public * com.spring.lon.aop.Calculator.*(..))"/> <aop:aspect ref="aspect"> <aop:before method="test1" pointcut-ref="aaa"/> <aop:after method="test2" pointcut-ref="aaa"/> <aop:after-returning method="test3" pointcut-ref="aaa" returning="o"/> <aop:after-throwing method="test4" throwing="t" pointcut-ref="aaa"/> <!-- <aop:around method="test5" pointcut-ref="aaa"/>--> </aop:aspect> </aop:config> </beans>

(1).解释

<aop:aspectj-autoproxy proxy-target-class="true"/>

这个是开启SpringAop自动代理机制,使spring能够根据切点表达式自动为匹配的bean创建代理对象(Spring AOP 使用 AspectJ 的表达式体系 + 注解规范,但底层仍然是 Spring 代理机制)

有两种:1.JDK动态代理 proxy-target-class="false"(默认是false)基于接口

2.CGLIB代理proxy-target-class="true" 基于继承

注意:有接口默认JDK 没有接口和proxy-target-class="true",强制使用CGLIB。

JDK动态代理:代理实现目标类的接口,返回一个bean(实现了接口的代理对象),只能通过接口类型访问对象。

CGLIB代理:通过继承生成目标类的子类来实现代理,代理对象是目标类型的子类(增强子类),可以转换为目标类也就可以转换为其父类或接口,可以来接非final方法,private不能拦截。

两种代理都是需要满足什么才能拦截:

1.通过代理对象调用方法

2.方法必须匹配切入点表达式(方法签名)

3.方法必须是能被代理的方法

注意:JDK代理限制 1.有接口

2.方法必须在接口中声明

3.必须通过接口调用

CGLIB代理限制 1.方法不能是final和private

2.方法能重写

---------------------------------------------------------------------------------------------
(2).解释xml代码的作用

a.整体逻辑

目标类-----被代理------>切面类-----提供增强逻辑-------->AOP配置(切点加通知)----------->在方法执行前后插入

b.开启aop代理前面解释了

c.为springBean注册 切面类和目标类

————————————————————————————

<bean id="aspect" class="com.spring.lon.aop.Aspect1"/>

<bean id="Caculator" class="com.spring.lon.aop.Calculator"/>

————————————————————————————

d.AOP核心配置

-->

<aop:config>

开始定义切点 切面 通知

-->

<aop:pointcut id="aaa"
expression="execution(public * com.spring.lon.aop.Calculator.*(..))"/>

切点,和个方法标签相同的方法都会被增强,execution后面的是切点表达式

其中相关解释如[xxxxx]

public[public方法] * [返回值任意]com.spring.lon.aop.Calculator[类].*[所有方法](..)[任意参数]

-->

<aop:aspect ref="aspect">

切面增强逻辑的相关提供者

-->

<aop:before method="test1" pointcut-ref="aaa"/>
<aop:after method="test2" pointcut-ref="aaa"/>
<aop:after-returning method="test3" pointcut-ref="aaa" returning="o"/>
<aop:after-throwing method="test4" throwing="t" pointcut-ref="aaa"/>

这4条都是相关通知,

表示在遇到和方法标签的匹配的方法的时候就会调用对应的增强逻辑。

-->通知说明

类型方法执行时机
前置test1方法前
后置test2方法后
返回test3正常返回
异常test4抛异常
环绕test5全包围

3.编写测试类

(1).创建CalculatorTest 类 如下图 2-1 CalculatorTest类

public class CalculatorTest { public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("springAOP.xml"); Calculator ca= (Calculator) ctx.getBean("Caculator"); ca.mySQL(); } }

(2).测试结果如下:

10:55:11.787 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Caculator' void com.spring.lon.aop.Calculator.mySQL()方法执行了! 数据库的相关逻辑! void com.spring.lon.aop.Calculator.mySQL()方法执行完成! void com.spring.lon.aop.Calculator.mySQL()方法执行了 执行结果是null Process finished with exit code 0

解释如下:

从执行结果可以看出,执行成功。

异常出现和异常不出现的相关流程

1.异常不出现

顺序XML通知说明
1<aop:before>方法执行前
2Target Method目标方法执行
3<aop:after>一定执行(类似 finally)
4<aop:after-returning>正常返回时执行
5<aop:after-throwing>不执行

2.异常出现

顺序XML通知说明
1<aop:before>方法执行前
2Target Method目标方法(异常)
3<aop:after>一定执行
4<aop:after-throwing>异常时执行
5<aop:after-returning>不执行

执行流程如下

main执行后加载xml创建对应的bean,然后通过bean来调用相关的方法

方法前(before)
|
目标方法执行
|
根据执行结果分支:
|—— 正常 → after-returning
|—— 异常 → after-throwing
|
after(一定执行)

Spring AOP 的本质是:通过代理对象拦截方法调用,在目标方法执行前后插入增强逻辑。

http://www.jsqmd.com/news/1096442/

相关文章:

  • 【硬件设计实战】JTAG接口上下拉电阻配置全解析:从标准到芯片手册
  • 【小白也能轻松玩转龙虾】虾壳云一键部署教程,OpenClaw v2.7.9 可视化安装全过程(附最新安装包)
  • 2026年企业级AI API聚合平台选型指南:六大主流中转服务横向对比与技术评测
  • 终极音乐解放:3分钟掌握ncmdumpGUI,永久解锁网易云音乐加密文件
  • Kali Linux实战:SQL注入与XSS漏洞攻防演练
  • 从拒稿到录用:我的IEEE TII投稿实战复盘与避坑指南
  • 误删微信聊天记录不用愁,全套官方恢复教程,文末科普第三方渠道
  • 《重启日记》第十四周|主业忙碌,更新放缓:流量起伏无碍长期沉淀
  • 泰国华商出海数字化选型解析:国内大厂、本土软件与出海专属系统对比(批发 / 零售业态专属)
  • 别急着追Multi-Agent,先想清楚这三个问题
  • GPU内存完整性验证:MemtestCL架构解析与实战配置指南
  • 从状态访问到动作决策:占用度量如何量化策略的探索足迹
  • 这个级别的配置两万,别碰积家翻转古董表,单看这处表壳加工公差就会吃亏
  • d2s-editor:重新定义暗黑破坏神2存档编辑体验的开源工具
  • 免费开源项目文档:基于HSV颜色空间和形态学特征的火灾与烟雾智能检测系统
  • AI正在变成特权,你还配用吗 - 微元算力(weytoken)
  • 【银河麒麟V10】vsFTPd服务实战:从零部署到安全加固全攻略
  • 【UE5蓝图实战】从零实现高效物体框选:原理、优化与多类型Actor筛选
  • Python实战:打造阴阳师御魂副本智能挂机脚本,兼顾效率与防检测
  • Docker 从零到实战:Windows Linux 安装、命令与配置全攻略
  • Python 多源行情数据冲突排查:symbol、timestamp、字段口径和原始返回校验
  • 龙口让人放心防水公司特点
  • openEuler HPC Runner性能优化秘籍:提升HPC应用运行效率的10个技巧
  • 暗黑破坏神2存档编辑器终极指南:零基础学会角色自定义
  • C#:XmlNodeList
  • 三步完成Beyond Compare 5永久激活:开源密钥生成器完整指南
  • 点胶点钻设备现场调试笔记:压电阀与视觉定位系统的工艺适配分析
  • 别让 AI 误读你的资产:用推送接口构建带“防伪签名”的 GEO 数据源
  • 3分钟掌握:这款免费Chrome插件让你轻松下载网页视频
  • 电商OAuth2.0授权码泄露漏洞自动化渗透测试与防御实战