这里面提到了实现ltw的三种方式,其中第一种,就是我们前面说的java instrumentation的方式,只是这里的agent是使用aspectjweaver.jar;第二种,使用了专有命令来执行,这种方式比较奇葩,直接跳过不理;第三种,和我们前面说的类似,就是自定义classloader的方式:
Enabling Load-time WeavingAspectJ 5 supports several ways of enabling load-time weaving for an application: agents, a command-line launch script, and a set of interfaces for integration of AspectJ load-time weaving in custom environments.
Agents
AspectJ 5 ships with a number of load-time weaving agents that enable load-time weaving. These agents and their configuration are execution environment dependent. Configuration for the supported environments is discussed later in this chapter.Using Java 5 JVMTI you can specify the -javaagent:pathto/aspectjweaver.jar option to the JVM.Using BEA JRockit and Java 1.3/1.4, the very same behavior can be obtained using BEA JRockit JMAPI features with the -Xmanagement:class=org.aspectj.weaver.loadtime.JRockitAgent
Command-line wrapper scripts aj
The aj command runs Java programs in Java 1.4 or later by setting up WeavingURLClassLoader as the system class loader. For more information, see .The aj5 command runs Java programs in Java 5 by using the -javaagent:pathto/aspectjweaver.jar option described above. For more information, see .
Custom class loader
A public interface is provided to allow a user written class loader to instantiate a weaver and weave classes after loading and before defining them in the JVM. This enables load-time weaving to be supported in environments where no weaving agent is available. It also allows the user to explicitly restrict by class loader which classes can be woven. For more information, see and the API documentation and source for WeavingURLClassLoader and WeavingAdapter.
第一种方式呢,我这里弄了个例子,代码放在:
https://gitee.com/ckl111/spring-boot-first-version-learn/tree/master/all-demo-in-spring-learning/java-aspectj-agent
整个demo的代码结构如下图:
目标类,是要被增强的对象
package foo; public class StubEntitlementCalculationService { public void calculateEntitlement() { System.out.println("calculateEntitlement"); } }
切面类
package foo; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @Aspect public class ProfilingAspect { @Around("methodsToBeProfiled()") public Object profile(ProceedingJoinPoint pjp) throws Throwable { System.out.println("before"); try { return pjp.proceed(); } finally { System.out.println("after"); } } // 这里定义了切点 @Pointcut("execution(public * foo..*.*(..))") public void methodsToBeProfiled(){} }
aop配置,指定要使用的切面,和要扫描的范围
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <!-- only weave classes in our application-specific packages --> <include within="foo.*"/> </weaver> <aspects> <!-- weave in just this aspect --> <aspect/> </aspects> </aspectj>
测试类
package foo; public final class Main { public static void main(String[] args) { StubEntitlementCalculationService entitlementCalculationService = new StubEntitlementCalculationService(); // 如果进展顺利,这处调用会被增强 entitlementCalculationService.calculateEntitlement(); } }
启动测试
执行步骤: 1.mvn clean package,得到jar包:java-aspectj-agent-1.0-SNAPSHOT 2.把aspectjweaver-1.8.2.jar拷贝到和本jar包同路径下 3.cmd下执行: java -javaagent:aspectjweaver-1.8.2.jar -cp java-aspectj-agent-1.0-SNAPSHOT.jar foo.Main执行的效果如下:
Aspectj的LTW的原理剖析我们这一小节,简单说说其原理。我们前面提到,aspectj的ltw共三种方式,我们上面用了第一种,这种呢,其实就是基于instrumentation机制来的。
只是呢,这里我们指定的agent是aspectj提供的aspectjweaver.jar。我这里把这个jar包(我这里版本是1.8.2)解压缩了一下,我们来看看。