父抽象类方法无法触发Aspect切面失效问题及AspectJ解决方案咨询
问题根因
切面未触发本质是Spring AOP的原生机制限制,同时存在代码语法错误:
- Spring AOP基于动态代理实现,仅拦截外部对象调用代理实例的公共方法,子类
process方法中调用父类constructBO属于类内部的this自调用,不会经过代理层,因此切点无法匹配。 @AfterReturning通知不能调用joinPoint.proceed(),该方法仅适用于@Around环绕通知,同时代码中存在result变量重复声明的问题。另外B类的process方法不能加abstract修饰、constructBO参数存在语法错误、父类constructBO的返回值类型与实际返回的RepaymentProductBO不匹配,需先修正这些编译问题。
适配Spring AOP的替代方案
如果不想引入AspectJ,可以调整代码逻辑绕开代理限制:
- 将
constructBO方法拆分到独立的Spring Bean中,注入到A/B类后调用,跨Bean的外部调用会走代理触发切面 - 调用
constructBO时通过Spring上下文获取当前类的代理实例,用代理实例调用方法:
// 先实现SpringContextUtil工具类获取上下文 A proxy = SpringContextUtil.getBean(this.getClass()); ProductBO productBO = proxy.constructBO("VISA", "VI-123456" + accountNumber);
AspectJ实现方案
AspectJ不需要依赖代理,直接通过字节码织入切面逻辑,可以拦截所有方法调用场景,包括内部自调用,配置步骤如下:
1. 引入依赖
以Maven为例:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.7</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
2. 修正切面代码
@Aspect // 不需要加@Component注解,AspectJ切面无需交给Spring管理 public class TransactionAdvice { @Pointcut("execution(* com.sample.handler.A+.constructBO(..))") private void logData() { } @AfterReturning(pointcut = "logData()", returning = "result") public void logData(JoinPoint joinPoint, Object result) { System.out.println("COME IN AfterReturning"); if (result instanceof ProductBO) { System.out.println("Works..."); } } }
3. 配置织入方式,二选一即可:
编译时织入
在build中配置aspectj编译插件,编译阶段直接将切面逻辑织入目标类字节码:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <complianceLevel>1.8</complianceLevel> <source>1.8</source> <target>1.8</target> <aspectLibraries> <aspectLibrary> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </aspectLibrary> </aspectLibraries> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin>
加载时织入
无需修改编译配置,启动时通过字节码增强织入切面:
- 在Spring启动类上添加
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)注解 - 应用启动命令添加JVM参数:
-javaagent:./lib/aspectjweaver-1.9.7.jar,替换为你实际的aspectjweaver包路径
内容的提问来源于stack exchange,提问作者Wenkai Fan
相关产品推荐
相关产品推荐

