前几天有个朋友问了个问题,觉得可以分享给大家。问题如下图所示。这是一项历史工程。里面有很多类没有交给spring管理,现在需要统一添加日志。面对这样的问题,其实只要了解了AOP的原理,就会有很多种方法。AOP是基于动态代理实现的,最常见的动态代理有cglib和java动态代理。不明白的可以看千户君之前写的文章,java动态代理为什么要基于接口?cglib动态代理对类没有限制吗?但是这两种方法在这样的场景下似乎很难实现,需要大量修改代码,那么有什么好的解决方案吗?答案当然是肯定的。首先要明确的是,AOP的底层实现原理是字节码。我们只需要从字节码层面解决这个问题。因此,可以使用编译时增强和运行时增强。常见的方案有两种,一种是JavaAgent技术,一种是AspectJ方案。JavaAgentJavaAgent中文名称为javaprobe。可以在运行java时指定probe程序,不会侵入原程序。一些常见的APM工具将执行此操作,例如skywalking。稍后我会介绍给大家。如下图所示的java代理的主要原理是使用JVMTI(JVMToolInterface)。JVM用于暴露一些接口集合供用户扩展,所以可以在这里做一些运行时字节码的增强。JavaAgent的内容很多,很多大家耳熟能详的工具都是基于它的,比如阿里的arthas。本文不做介绍,后面会详细介绍JavaAgent。AspectJ方案可以使用aspectj+javac编织代码,或者使用maven插件aspectj-maven-plugin。下面我们使用AspectJ注解+aspectj-maven-plugin来练习一下。aspectj-maven-plugin官网http://www.mojohaus.org/aspectj-maven-plugin/usage.html引入了依赖编译增强,依赖于这个jarimportorg.aspectj.lang.annotation.Aspect;importorg.aspectj。lang.注释。Before;importorg.aspectj.lang.annotation.Pointcut;@AspectpublicclassAop{@Pointcut("执行(*com.ganhuojun.gracefulshutdown.controller..*.*(..))")publicvoidpointcut1(){}@Before("pointcut1()")publicvoidbefore(){System.out.println("controllerbefore");}}定义注解注意:不要给spring管理
