如何通过AspectJ替换System.currentTimeMillis()调用?切面为何未生效?
问题:AspectJ切面无法替换System.currentTimeMillis()返回值
我需要在测试用例中用自定义值替换System.currentTimeMillis()的返回结果,编写了如下AspectJ切面代码与测试代码:
切面代码
package org.example.aspectj; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class TimeAspect { @Around("execution(public static native long currentTimeMillis())") public long changeCallsToCurrentTimeInMillisMethod(ProceedingJoinPoint pjp) { return 0; } }
测试代码
package org.example.aspectj; public class TimeDemo { public static void main(String[] args) { long currentTimeMillis = System.currentTimeMillis(); System.out.println("currentTimeMillis -> " + currentTimeMillis); } }
运行时出现警告:
[warning] advice defined in org.example.aspectj.TimeAspect has not been applied [Xlint:adviceDidNotMatch]
控制台输出原时间:
Task :TimeDemo.main() currentTimeMillis -> 1710770641050
时间并未被替换,请问问题出在哪里?
问题原因与解决办法
1. 切点表达式选错:用execution而非call
execution切入点匹配的是方法执行的逻辑位置,但System.currentTimeMillis()是JDK核心类java.lang.System的native方法,AspectJ无法修改JDK类的方法执行逻辑。我们需要匹配的是调用这个方法的代码位置,因此必须使用call切入点:
修正后的切面切点:
@Around("call(public static native long java.lang.System.currentTimeMillis())")
2. 必须使用原生AspectJ织入,不能用Spring AOP
如果是Spring环境,Spring AOP基于动态代理,不支持静态方法的切面拦截,必须切换为原生AspectJ的织入方式:
- 编译时织入(CTW):在Maven/Gradle等构建工具中配置AspectJ编译器,让切面代码被织入到调用
System.currentTimeMillis()的目标类中。 - 加载时织入(LTW):通过JVM参数指定AspectJ代理类加载器,在类加载阶段动态织入切面逻辑。
3. 修正后的完整切面代码
package org.example.aspectj; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class TimeAspect { @Around("call(public static native long java.lang.System.currentTimeMillis())") public long changeCallsToCurrentTimeInMillisMethod(ProceedingJoinPoint pjp) { // 返回自定义时间戳 return 1600000000000L; } }
4. Gradle构建配置示例
如果用Gradle,需要添加AspectJ插件并配置织入范围:
plugins { id 'java' id 'io.freefair.aspectj' version '8.6' } dependencies { implementation 'org.aspectj:aspectjrt:1.9.21' implementation 'org.aspectj:aspectjweaver:1.9.21' } aspectj { ajcOptions { // 确保织入包含调用System.currentTimeMillis()的类 include 'org/example/aspectj/**' } }
内容的提问来源于stack exchange,提问作者Alexandre Marechal Ferrant
相关产品推荐
相关产品推荐

