尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

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

Spring AOP(XML配置版):代理机制与拦截器
📅 发布时间:2026/6/30 14:26:07

本章节介绍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 的本质是:通过代理对象拦截方法调用,在目标方法执行前后插入增强逻辑。

相关新闻

  • Kali Linux实战:SQL注入与XSS漏洞攻防演练
  • 泰国华商出海数字化选型解析:国内大厂、本土软件与出海专属系统对比(批发 / 零售业态专属)
  • 这个级别的配置两万,别碰积家翻转古董表,单看这处表壳加工公差就会吃亏

最新新闻

  • Windows 10 环境下 Nessus 8.15 专业版离线部署与无限IP授权实战
  • SQLServer进行计算平均值,计算批次损耗率=损耗比例的平均值,用于统计指标卡
  • 别再手动描边了!CVAT分割标注的‘自动边框’和‘智能裁剪’功能,帮你效率翻倍
  • ZLAN_ACC:从零到一,详解ABAP程序迁移与备份的自动化利器
  • Ubuntu环境实战:从源码编译到应用,解锁GStreamer NVENC/NVDEC插件全流程
  • VHDL流程控制实战:从IF/CASE语法到高效数字电路设计

日新闻

  • 【计算机毕业设计案例】基于 Spring Boot+Vue 的电影售票系统设计与实现 前后端分离架构下影院在线购票管理平台(程序+文档+讲解+定制)
  • 到底 TMD 用哪个: npm, pnpm, Yarn, Bun, Deno? 傻瓜, 当然用 npm 啦
  • Google限制Meta使用Gemini模型 凸显AI授权竞争白热化

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号