Spring 4自定义方法拦截器:无源码下拦截do()方法并自定义逻辑
当然可以实现!
这种场景正好是Spring AOP的典型应用场景之一——哪怕你没有Impl1或Impl2的源码,也能轻松拦截方法调用并自定义逻辑。结合Spring 4和JDK 7,我给你梳理一套可行的实现方案:
核心思路
利用Spring的**环绕通知(Around Advice)**功能,通过切面(Aspect)拦截所有对do()方法的调用。环绕通知是最灵活的AOP通知类型,它允许你:
- 在原方法执行前后插入自定义逻辑
- 完全控制是否调用原方法实现(根据你的条件判断)
- 无需修改目标类的源码
具体实现步骤
1. 引入必要依赖
如果用Maven管理项目,确保pom.xml中包含适配Spring 4和JDK 7的依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.3.30.RELEASE</version> <!-- 替换为你实际使用的Spring 4版本 --> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.13</version> <!-- 该版本兼容JDK 7与Spring 4 --> </dependency>
2. 定义切面类实现拦截逻辑
假设你的目标接口是MyInterface(包含do()方法),我们创建一个切面类,用@Aspect标记,通过@Around注解定义环绕通知:
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Aspect @Component public class DoMethodInterceptor { // 切入点表达式:拦截所有实现MyInterface的类的do()方法 @Around("execution(* com.yourpackage.MyInterface.do(..))") public Object interceptDoMethod(ProceedingJoinPoint joinPoint) throws Throwable { // 第一步:执行自定义前置逻辑 System.out.println("[拦截器] 捕获到do()方法调用"); // 第二步:判断是否需要调用原方法的业务条件(替换为你的实际判断逻辑) boolean shouldInvokeOriginal = checkBusinessCondition(); Object result = null; if (shouldInvokeOriginal) { // 条件满足:调用原方法实现 System.out.println("[拦截器] 条件满足,执行原do()方法"); result = joinPoint.proceed(); // 触发原方法执行 } else { // 条件不满足:执行自定义实现,不调用原方法 System.out.println("[拦截器] 条件不满足,执行自定义逻辑"); customDoImplementation(); } // 第三步:执行自定义后置逻辑(可选) System.out.println("[拦截器] do()方法调用处理完成"); return result; } // 模拟业务条件判断,替换为你的实际逻辑 private boolean checkBusinessCondition() { // 示例:根据当前请求参数、上下文或其他规则判断 return true; } // 你的自定义do()方法实现 private void customDoImplementation() { // 这里编写你想要替代原方法的逻辑 System.out.println("[自定义实现] 这是我自己的do()方法逻辑"); } }
3. 开启Spring AOP支持
需要在Spring配置中开启注解式AOP的支持,有两种方式:
方式一: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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 扫描组件,让Spring识别切面类和目标Bean --> <context:component-scan base-package="com.yourpackage"/> <!-- 开启AspectJ注解驱动的AOP --> <aop:aspectj-autoproxy/> </beans>
方式二:Java配置(Spring 4支持)
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @ComponentScan(basePackages = "com.yourpackage") @EnableAspectJAutoProxy public class AppConfig { }
4. 确保目标类是Spring Bean
Impl1和Impl2必须被Spring管理(即成为Spring Bean),可以通过以下方式实现:
- 在类上添加
@Component/@Service等注解 - 在XML配置中通过
<bean>标签声明
只有这样,Spring才能为目标类生成代理对象,从而实现方法拦截。
关键注意事项
- 如果目标类没有实现接口,Spring会自动用CGLIB生成代理(JDK 7完全支持CGLIB);如果实现了接口,默认用JDK动态代理,两种方式都能正常工作。
- 环绕通知的
ProceedingJoinPoint.proceed()方法是触发原方法执行的关键——只有调用它,原方法才会执行;如果不调用,就完全用你的自定义逻辑替代。 - 切入点表达式可以根据你的需求调整,比如拦截特定包下的所有
do()方法,或者更精确的匹配规则。
内容的提问来源于stack exchange,提问作者Debopam
相关产品推荐
相关产品推荐

