Java Spring Boot项目中替代private辅助方法实现AOP日志追踪的方案
解决方案
你之前自注入ServiceImpl报NPE的核心原因是:Spring默认对实现了接口的Bean使用JDK动态代理,生成的代理对象仅实现你定义的Service接口,不属于ServiceImpl类型,所以直接注入ServiceImpl类型会拿不到实例。
方案1:适配现有Spring AOP(改动最小,无额外依赖)
完全复用你现有的AOP切面逻辑,仅需少量调整业务代码即可实现需求:
- 第一步:在application配置文件中添加配置开启CGLIB子类代理:
spring.aop.proxy-target-class=true - 第二步:调整自注入逻辑,添加
@Lazy注解避免循环依赖 - 第三步:将私有方法调整为包级私有(移除private修饰符即可,无需改为public,尽可能降低对外暴露范围),并添加你的耗时统计注解
- 第四步:内部调用时使用注入的self实例调用方法
调整后的代码示例:
@Service public class ServiceImpl implements Service { @Autowired @Lazy private ServiceImpl self; // 开启CGLIB代理后可正常注入 @MySpringAOPAnnotationThatWorks public SwaggerGeneratedDataType1 myPublicMethod(SwaggerGeneratedDataType2 myMethodArgument) { // ...原有业务逻辑 self.myNestedMethod1(myMethodArgument.getSomeAttribute1()); // ...原有业务逻辑 self.myNestedMethod2(myMethodArgument.getSomeAttribute2()); // 返回结果 } @MySpringAOPAnnotationThatWorks void myNestedMethod1(String myNestedMethodArgument1) { // 包级私有,仅同包类可访问 // 原有业务逻辑 } @MySpringAOPAnnotationThatWorks void myNestedMethod2(String myNestedMethodArgument2) { // 原有业务逻辑 } }
方案2:编译期AspectJ织入(无需修改业务代码)
如果不想调整原有方法的可见性和调用逻辑,可以用编译期AspectJ织入,直接支持拦截所有方法(包括private方法、内部自调用方法),不需要开启load time weaving,对运行期无侵入:
- 第一步:在service模块的pom.xml中引入
aspectj-maven-plugin,配置编译期织入规则,指定你的切面类路径 - 第二步:无需修改原有业务代码,私有方法、调用方式都保持原样即可,切面会在编译期直接织入到类的字节码中,所有加了自定义注解的方法都会被拦截统计耗时
备选方案:手动埋点统计
如果以上方案都不适用,且需要统计的私有方法数量很少,可以直接在私有方法首尾加耗时统计逻辑:
private void myNestedPrivateMethod1(String myNestedMethodArgument1) { long start = System.currentTimeMillis(); try { // 原有业务逻辑 } finally { long cost = System.currentTimeMillis() - start; // 记录耗时和响应信息日志 } }
内容的提问来源于stack exchange,提问作者PainIsAMaster
相关产品推荐
相关产品推荐

