SpringAop新链实现任意无参方法调用
字数 2111 2025-08-29 22:41:01
Spring AOP 新链实现任意无参方法调用技术分析
1. AOP核心概念
1.1 基本术语
- 切面(Aspect): 公共功能的实现模块,如日志、权限、验签等。使用
@Aspect注解修饰的Java类 - 通知(Advice): 切面的具体实现方法,分为:
- 前置通知(Before)
- 后置通知(AfterReturning)
- 异常通知(AfterThrowing)
- 最终通知(After)
- 环绕通知(Around)
- 连接点(JoinPoint): 程序运行中可插入切面的位置,Spring仅支持方法级连接点
- 切点(PointCut): 定义通知应应用到哪些连接点的规则
- 引入(Introduction): 动态为类添加新接口实现
1.2 依赖关系
spring-boot-starter-aop包含:
spring-aopaspectjweaver
2. AOP实现机制
2.1 动态代理与拦截
JdkDynamicAopProxy类:
- JDK动态代理的调用处理器
- 代理对象方法调用时跳转到
invoke方法处理 - 调用目标方法前检查是否配置拦截链
两种处理路径:
- 拦截链为空(
chain.isEmpty()): 直接反射调用目标方法 - 配置拦截链: 通过拦截链层层处理后再调用目标方法
2.2 拦截链构建
AdvisedSupport类处理代理配置:
readObject初始化空的methodCacheMap- 首次获取拦截链返回null
- 通过
getInterceptorsAndDynamicInterceptionAdvice构建拦截链
拦截链构建过程:
- 从配置获取
Advisor(包含advice和匹配过滤器) - 判断advice类型(PointCut或Introduction)
- 通过
DefaultAdvisorAdapterRegistry.getInterceptors获取Interceptor - 合并到
interceptorList
MethodInterceptor接口:
- 用于拦截目标方法调用
- 通过
invoke方法添加拦截逻辑
2.3 拦截链执行
ReflectiveMethodInvocation类:
currentInterceptorIndex跟踪当前拦截器位置- 执行完所有拦截器后调用目标方法(
invokeJoinpoint) - 动态匹配方法时先检查方法是否匹配
3. 切面方法调用机制
3.1 Advice调用流程
AbstractAspectJAdvice抽象类:
- 包含各种通知类型的子类(Before, After等)
invokeAdviceMethod最终调用切面方法aspectJAdviceMethod: advice对应的方法(如logBefore)
方法恢复:
Method未实现SerializableaspectJAdviceMethod由transient修饰readObject时通过反射恢复
3.2 实例工厂
AspectInstanceFactory实现类:
SimpleAspectInstanceFactory: 反射调用无参构造器(不可序列化)SingletonAspectInstanceFactory: 单例工厂(可序列化)SimpleBeanFactoryAwareAspectInstanceFactory: 由Bean工厂创建SimpleJndiBeanFactory: JNDI工厂(不可序列化)
3.3 参数绑定
AbstractAspectJAdvice#argBinding:
jpMatch来自getJoinPointMatch- 需要
ProxyMethodInvocation#setUserAttribute设置属性 - 当前仅支持无参方法调用
4. 任意无参方法调用实现
4.1 关键问题
直接构造会报错缺少MethodInvocation:
ExposeInvocationInterceptor拦截器负责设置MethodInvocation- 需要先注册此interceptor再注册advice
4.2 实现步骤
- 创建
SingletonAspectInstanceFactory实例 - 设置目标方法(如
TemplatesImpl#newTransformer) - 构建拦截链:
- 先添加
ExposeInvocationInterceptor - 再添加自定义advice
- 先添加
- 通过
JdkDynamicAopProxy执行调用链
4.3 示例代码结构
// 1. 创建单例工厂
SingletonAspectInstanceFactory factory = new SingletonAspectInstanceFactory(targetObject);
// 2. 设置目标方法
Method method = TemplatesImpl.class.getMethod("newTransformer");
// 3. 构建拦截链
List<Object> interceptors = new ArrayList<>();
interceptors.add(new ExposeInvocationInterceptor());
interceptors.add(new MyAdvice(factory, method));
// 4. 创建代理调用
JdkDynamicAopProxy proxy = new JdkDynamicAopProxy(config);
proxy.invoke(proxy, method, new Object[]{});
5. 限制与注意事项
- 仅支持无参方法调用
- 依赖
SingletonAspectInstanceFactory可序列化 - 拦截链顺序必须正确(ExposeInvocationInterceptor优先)
- 目标类必须可访问
- 安全限制可能阻止某些方法调用
6. 防御建议
- 限制反序列化源
- 监控可疑的AOP配置
- 更新Spring框架版本
- 实施最小权限原则
- 对输入进行严格验证