前言
项目中可以使用aop切面来进行增强处理,也可以自行实现一个methodinterceptor对代码进行增强处理,相比与使用aop可以更加轻便的形成连接器链;
使用
引入pom
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-aop</artifactid>
</dependency>
配置interceptor
import jakarta.annotation.resource;
import org.springframework.aop.aspectj.aspectjexpressionpointcut;
import org.springframework.aop.support.defaultpointcutadvisor;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
@configuration
public class serviceinterceptorconfig {
private static final string execution = "execution(* com.lhz.demo.service.userservice.*(..))";
@resource
private serviceinterceptor serviceinterceptor;
@bean
public defaultpointcutadvisor defaultpointcutadvisor() {
defaultpointcutadvisor advisor = new defaultpointcutadvisor();
aspectjexpressionpointcut pointcut = new aspectjexpressionpointcut();
pointcut.setexpression(execution);
advisor.setpointcut(pointcut);
advisor.setadvice(serviceinterceptor);
advisor.setorder(-1);
return advisor;
}
}
自定义interceptor
@component
@slf4j
public class serviceinterceptor implements methodinterceptor {
@override
public object invoke(methodinvocation methodinvocation) throws throwable {
log.info("进入serviceinterceptor...");
object[] arguments = methodinvocation.getarguments();
return methodinvocation.proceed();
}
}
排序
单个interceptor、多个interceptor、aop使用的相同的pointcut时,请求都会进入,只是进入的先后顺序不同,aop中可以直接通过@order注解控制,interceptor通过advisor.setorder()方法进行设置;
验证
同时存在aop和interceptor的情况,并且aop的order=-2,interceptor的order=-1
aop代码如下:
@aspect
@component
@slf4j
@order(-2)
public class serviceaop {
@pointcut("execution(* com.lhz.demo.service.userservice.*(..))")
public void point() {
}
@before("point()")
public void dobeforeadvice(joinpoint point) {
log.info("进入前置通知...");
}
@around("point()")
public void doaroundadvice(proceedingjoinpoint point) throws throwable {
log.info("进入环绕通知...");
point.proceed();
}
}
结果:

对比
| 对比维度 | methodinterceptor | aop (广义) |
|---|---|---|
| 定位 | aop 的具体实现组件 | 编程范式/思想 |
| 抽象层级 | 具体的技术实现 | 高层次的设计理念 |
| 标准化 | aop alliance 标准接口 | 无统一标准,各框架实现不同 |
核心差异
| 特性 | methodinterceptor | 声明式aop | 差异分析 |
|---|---|---|---|
| 实现方式 | 实现methodinterceptor接口 | 使用@aspect注解 | 前者需手动编码,后者通过元数据配置 |
| 拦截粒度 | 方法调用级别控制 | 切入点表达式匹配 | methodinterceptor可获取methodinvocation完整上下文 |
| 执行控制 | 显式调用invocation.proceed() | 隐式调用joinpoint.proceed() | 前者对执行流程控制更直观 |
| 性能开销 | △ 较低(直接方法调用) | ○ 略高(需解析注解) | 差异在微秒级,高并发场景需考虑 |
| 适用阶段 | 动态代理 | 支持ltw/ctw | aspectj的编译时织入能力更强 |
| 依赖关系 | 仅依赖aop alliance api | 依赖具体框架(如spring aop) | 前者更易移植 |
| 调试复杂度 | 需跟踪代理链 | 切面集中管理 | 声明式aop的堆栈信息更友好 |
| 动态能力 | ★★★★ 可运行时修改拦截逻辑 | ★★ 配置后固定 | methodinterceptor适合需要热更新的场景 |
| 代码侵入性 | 目标类无需修改 | 但需引入aop依赖 | 两者都符合aop的非侵入理念 |
| 典型应用场景 | 安全校验/参数过滤/熔断机制 | 日志/事务/缓存等常规切面 | 根据业务复杂度选择 |
注:实际使用时建议将图标替换为对应的emoji或移除图标标记
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论