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

发布时间:2026/6/30 14:16:57
Spring AOP(XML配置版):代理机制与拦截器 本章节介绍AOP面向切面编程用于将日志、事务等横切逻辑从业务代码中解耦通过代理机制在方法执行前后织入增强逻辑。1.引入依赖1.创建maven依赖进行管理引入以下依赖?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdorg.example/groupId artifactIdspring-springaop-lon-boke/artifactId version1.0-SNAPSHOT/version properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding spring.version5.2.2.RELEASE/spring.version aspectj.version1.9.6/aspectj.version /properties dependencies dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-aop/artifactId version${spring.version}/version /dependency !-- 3. AspectJ 织入器仅引入一次适配 Spring 5.2 -- dependency groupIdorg.aspectj/groupId artifactIdaspectjweaver/artifactId version${aspectj.version}/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.28/version scopeprovided/scope /dependency !-- 新增日志依赖Logback适配 Commons Logging -- dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.2.11/version /dependency /dependencies /project2创建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 namejp.getSignature().getName(); System.out.println(name方法发生了异常t.getMessage()); } // 环绕 public Object test5(ProceedingJoinPoint p){ String namep.getSignature().getName();//获取方法的名字 try { System.out.println(环绕前); Object op.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 version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:aophttp://www.springframework.org/schema/aop xsi:schemaLocationhttp://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-classtrue/ !-- 创建切面类的bean-- bean idaspect classcom.spring.lon.aop.Aspect1/ !-- 创建目标类-- bean idCaculator classcom.spring.lon.aop.Calculator/ aop:config aop:pointcut idaaa expressionexecution(public * com.spring.lon.aop.Calculator.*(..))/ aop:aspect refaspect aop:before methodtest1 pointcut-refaaa/ aop:after methodtest2 pointcut-refaaa/ aop:after-returning methodtest3 pointcut-refaaa returningo/ aop:after-throwing methodtest4 throwingt pointcut-refaaa/ !-- aop:around methodtest5 pointcut-refaaa/-- /aop:aspect /aop:config /beans1.解释aop:aspectj-autoproxy proxy-target-classtrue/这个是开启SpringAop自动代理机制使spring能够根据切点表达式自动为匹配的bean创建代理对象Spring AOP 使用 AspectJ 的表达式体系 注解规范但底层仍然是 Spring 代理机制有两种1.JDK动态代理 proxy-target-classfalse默认是false基于接口2.CGLIB代理proxy-target-classtrue 基于继承注意有接口默认JDK 没有接口和proxy-target-classtrue强制使用CGLIB。JDK动态代理代理实现目标类的接口返回一个bean实现了接口的代理对象只能通过接口类型访问对象。CGLIB代理通过继承生成目标类的子类来实现代理代理对象是目标类型的子类增强子类可以转换为目标类也就可以转换为其父类或接口可以来接非final方法private不能拦截。两种代理都是需要满足什么才能拦截1.通过代理对象调用方法2.方法必须匹配切入点表达式方法签名3.方法必须是能被代理的方法注意JDK代理限制 1.有接口2.方法必须在接口中声明3.必须通过接口调用CGLIB代理限制 1.方法不能是final和private2.方法能重写---------------------------------------------------------------------------------------------2.解释xml代码的作用a.整体逻辑目标类-----被代理------切面类-----提供增强逻辑--------AOP配置切点加通知-----------在方法执行前后插入b.开启aop代理前面解释了c.为springBean注册 切面类和目标类————————————————————————————bean idaspect classcom.spring.lon.aop.Aspect1/bean idCaculator classcom.spring.lon.aop.Calculator/————————————————————————————d.AOP核心配置--aop:config开始定义切点 切面 通知--aop:pointcut idaaaexpressionexecution(public * com.spring.lon.aop.Calculator.*(..))/切点和个方法标签相同的方法都会被增强execution后面的是切点表达式其中相关解释如[xxxxx]public[public方法] * [返回值任意]com.spring.lon.aop.Calculator[类].*[所有方法](..)[任意参数]--aop:aspect refaspect切面增强逻辑的相关提供者--aop:before methodtest1 pointcut-refaaa/aop:after methodtest2 pointcut-refaaa/aop:after-returning methodtest3 pointcut-refaaa returningo/aop:after-throwing methodtest4 throwingt pointcut-refaaa/这4条都是相关通知表示在遇到和方法标签的匹配的方法的时候就会调用对应的增强逻辑。--通知说明类型方法执行时机前置test1方法前后置test2方法后返回test3正常返回异常test4抛异常环绕test5全包围3.编写测试类1.创建CalculatorTest 类 如下图 2-1 CalculatorTest类public class CalculatorTest { public static void main(String[] args) { ApplicationContext ctxnew 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通知说明1aop:before方法执行前2Target Method目标方法执行3aop:after一定执行类似 finally4aop:after-returning正常返回时执行5aop:after-throwing不执行2.异常出现顺序XML通知说明1aop:before方法执行前2Target Method目标方法异常3aop:after一定执行4aop:after-throwing异常时执行5aop:after-returning不执行执行流程如下main执行后加载xml创建对应的bean然后通过bean来调用相关的方法方法前before|目标方法执行|根据执行结果分支|—— 正常 → after-returning|—— 异常 → after-throwing|after一定执行Spring AOP 的本质是通过代理对象拦截方法调用在目标方法执行前后插入增强逻辑。