一、Javaagent
网上关于Javaagent的介绍很多,请找度娘和谷兄。唯一提的一点是字节码注入比较好用的是bytebuddy,封装度很高,使用简单。
二、代码样例
以下为关键代码样例,可以依样画瓢自行改造。
1.编写agent入口
package com.javashizhan.trace;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isSetter;
import static net.bytebuddy.matcher.ElementMatchers.nameContainsIgnoreCase;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWithIgnoreCase;
import static net.bytebuddy.matcher.ElementMatchers.not;
import java.lang.instrument.Instrumentation;
import com.javashizhan.trace.interceptor.AbstractJunction;
import com.javashizhan.trace.interceptor.ProtectiveShieldMatcher;
import com.javashizhan.trace.interceptor.TraceInterceptor;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
public class TraceAgent {
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.type(buildMatch())
.transform((builder, type, classLoader, module) ->
builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(TraceInterceptor.class)) // 拦截器
).installOn(instrumentation);
}
public static ElementMatcher<? super TypeDescription> buildMatch() {
ElementMatcher.Junction judge = new AbstractJunction<NamedElement>() {
@Override
public boolean matches(NamedElement target) {
return true;
}
};
judge = judge.and(not(isInterface())).and(not(isSetter()))
.and(nameStartsWithIgnoreCase("io.spring"))
.and(not(nameContainsIgnoreCase("util")))
.and(not(nameContainsIgnoreCase("interceptor")));
judge = judge.and(not(isSetter()));
return new ProtectiveShieldMatcher(judge);
}
}
2.拦截器类TraceInterceptor.java
package com.javashizhan.trace.interceptor;
import java.io.I