干了20年工程,我第一次觉得工地可以这么“透明”
2026/7/28 18:24:52
JavaAgent 只在项目启动时运行一次并且是java文件编译成class文件后才运行。所以不会影响到class文件。
JavaAgent 是寄生项目。即需要依赖一个正常项目才能运行
packagecom.annie;importjava.lang.instrument.Instrumentation;publicclassAgent{// JavaAgent启动时调用的方法publicstaticvoidpremain(String args,Instrumentation instrumentation){System.out.println("传入的参数为: "+args);System.out.println("JavaAgent启动了...");}}到这里一个JavaAgent项目就基本启动完成了。我们在创建一个普通项目(项目类型无所谓)
-javaagent:C:\Users\13100\Documents\IdeaProjects\BaseJava\out\artifacts\JavaAgent_jar\JavaAgent.jar=Hello<!-- https://mvnrepository.com/artifact/org.javassist/javassist --><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.25.0-GA</version></dependency>packagecom.annie;importjavassist.ClassPool;importjavassist.CtClass;importjavassist.bytecode.AnnotationsAttribute;importjavassist.bytecode.AttributeInfo;importjavassist.bytecode.ClassFile;importjavassist.bytecode.ConstPool;importjavassist.bytecode.annotation.Annotation;importjava.io.ByteArrayInputStream;importjava.io.IOException;importjava.lang.instrument.ClassFileTransformer;importjava.lang.instrument.IllegalClassFormatException;importjava.lang.instrument.Instrumentation;importjava.security.ProtectionDomain;importjava.util.List;publicclassAgent{// JavaAgent启动时调用的方法publicstaticvoidpremain(String args,Instrumentation instrumentation){System.out.println("传入的参数为: "+args);System.out.println("JavaAgent启动了...");// instrumentation 中包含了项目中的全部类。每加载一次.class文件就运行一次instrumentation.addTransformer(newClassFileTransformer(){@Overridepublicbyte[]transform(ClassLoader loader,String className,Class<?>classBeingRedefined,ProtectionDomain protectionDomain,byte[]classfileBuffer)throwsIllegalClassFormatException{// 这里我只捕捉自己写 TestController 类if(className.equals("com/annie/controller/TestController")){// 接下来就是javassist的使用我会粗略的写下备注。不会详解。// 获取一个 class 池。ClassPool classPool=ClassPool.getDefault();try{// 创建一个新的 class 类。classfileBuffer 就是当前class的字节码CtClass ctClass=classPool.makeClass(newByteArrayInputStream(classfileBuffer));ClassFile classFile=ctClass.getClassFile();ConstPool constPool=classFile.getConstPool();// 从这里取出原本类中的注解 建议DEBUG看下attributes中的数据List<AttributeInfo>attributes=classFile.getAttributes();AnnotationsAttribute attributeInfo=(AnnotationsAttribute)attributes.get(1);// 导包是javassist的包// 添加新的注解Annotation annotation=newAnnotation("org.springframework.web.bind.annotation.RequestMapping",constPool);attributeInfo.addAnnotation(annotation);// 返回新的字节码returnctClass.toBytecode();}catch(Exceptione){e.printStackTrace();}}returnnewbyte[0];}});}}packagecom.annie.controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.lang.annotation.Annotation;@RestControllerpublicclassTestController{@RequestMapping("/test")publicStringtest(){// 利用反射查看Class注解。Class<?extendsTestController>aClass=this.getClass();Annotation[]declaredAnnotations=aClass.getDeclaredAnnotations();StringBuffer sb=newStringBuffer();// 查看类上全部注解for(Annotation annotation:declaredAnnotations){sb.append(annotation.toString()+"\n");}returnsb.toString();}}将javaAgent.jar 和 javaassist.jar 放入到一个文件夹中。
运行命令
java -javaagent:JavaAgent.jar -jar web-test-0.0.1-SNAPSHOT.jar项目就启动成功。注意一点这个jar包就是你bulid出来的JAR
扩展内容
github
个人博客