創(chuàng)建一個(gè)java maven工程
Step1 添加bytebuddy及日志依賴
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.9.RELEASE</version>
<scope>provided</scope>
</dependency>
<!-- 字節(jié)碼 注入 -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.19</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
Step2 書寫Agent的入口處
agent有兩個(gè)入口函數(shù)啊送,分別是premain和agentmain欣孤,用于兩種啟動(dòng)場(chǎng)景-javaagent啟動(dòng)場(chǎng)景和attach啟動(dòng)場(chǎng)景,我們這里先書寫-javaagent啟動(dòng)場(chǎng)景
package com.github.shoothzj.demo.agent;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.matcher.ElementMatchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.instrument.Instrumentation;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
/**
* @author hezhangjian
*/
public class AgentMain {
private static final Logger log = LoggerFactory.getLogger(AgentMain.class);
/**
* call on -javaagnet
* @param agentArgs
* @param inst
*/
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("start agent premain");
final ByteBuddy byteBuddy = new ByteBuddy();
new AgentBuilder.Default(byteBuddy)
//這些類都是常見的無(wú)需切面注入的類,忽略掉可以提升agent加載速度
.ignore(nameStartsWith("net.bytebuddy.")
.or(nameStartsWith("org.slf4j.")
.or(nameStartsWith("org.apache.logging.")
.or(nameStartsWith("org.groovy."))
.or(nameStartsWith("javassist"))
.or(nameStartsWith(".asm."))
.or(nameStartsWith("sun.reflect"))
.or(ElementMatchers.isSynthetic()))))
//你想切面的包名
.type(ElementMatchers.nameStartsWith("com.github.shoothzj.agent.test"))
.transform(new AgentTransformer())
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.installOn(inst);
}
public static void agentmain(String agentArgs, Instrumentation inst) {
System.out.println("start agent main");
}
}
這個(gè)時(shí)候Transform先書寫一個(gè)空實(shí)現(xiàn)
package com.github.shoothzj.demo.agent; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.utility.JavaModule; /** * @author hezhangjian */ public class AgentTransformer implements AgentBuilder.Transformer{ @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) { return builder; } }
Step3 maven pom文件配置打包
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Premain-Class>com.github.shoothzj.demo.agent.AgentMain</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </transformer> </transformers> <artifactSet> <includes> <include>org.slf4j:slf4j-api</include> <include>org.apache.logging.log4j:log4j-api</include> <include>org.apache.logging.log4j:log4j-core</include> <include>org.apache.logging.log4j:log4j-slf4j-impl</include> <include>org.apache.logging.log4j:log4j-jcl</include> </includes> </artifactSet> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <relocations> <relocation> <pattern>org.slf4j</pattern> <shadedPattern>com.github.shoothzj.org.slf4j</shadedPattern> </relocation> <relocation> <pattern>org.apache.logging</pattern> <shadedPattern>com.github.shoothzj.org.apache.logging</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>
這里配置了打java agent的包篷朵,和打shade包規(guī)避類沖突的問(wèn)題婆排,關(guān)于打shade包,可以參考http://www.reibang.com/p/8171607ce03f
創(chuàng)建一個(gè)測(cè)試SpringBoot工程
Step1 書寫主函數(shù)
package com.github.shoothzj.demo.agent.test;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author hezhangjian
*/
@Slf4j
@SpringBootApplication
public class AgentTestMain {
public static void main(String[] args) {
SpringApplication.run(AgentTestMain.class);
}
}
Step2 修改運(yùn)行參數(shù)腮猖,加載java agent
這里我的agent赞枕,maven package后的路徑在 /Users/akka/master/maven-demo/demo-agent/target/demo-agent-0.0.1.SNAPSHOT.jar
-javaagent:/Users/akka/master/maven-demo/demo-agent/target/demo-agent-0.0.1.SNAPSHOT.jar
image-20201230215511785
Step3 運(yùn)行結(jié)果
image-20201231082704607
可以看到agent已經(jīng)正常啟動(dòng)