一:实际代码
1.1 GdBusiness.java的内容
package com.aop.transform;
public class GdBusiness {
public boolean deposit(){
System.out.println("存款业务执行");
return true;
}
public void withdrawals(){
System.out.println("取款业务执行");
}
}
1.2 MyClassFileTransformer.java的内容
package com.aop.transform;
import javassist.*;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
/**
* 字节码转换器
*/
public class MyClassFileTransformer implements ClassFileTransformer {
/**
* 字节码加载到jvm前会进入这个方法
* @param loader
* @param className
* @param classBeingRedefined
* @param protectionDomain
* @param classfileBuffer
* @return
* @throws IllegalClassFormatException
*/
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
//如果加载GdBusiness类才拦jue
if(!"com/aop/transform/GdBusiness".equals(className)){
return null;
}
if(className!=null&&className.indexOf("/")!=-1){
className=className.replaceAll("/",".");
}
try{
//通过包名获取类文件
CtClass cc=ClassPool.getDefault().get(className);
//获得指定方法名的方法
CtMethod m=cc.getDeclaredMethod("deposit");
//在方法执行前插入代码
m.insertBefore("System.out.println(\"存款业务执行前:1.欢迎您来存款...\");");
//在方法执行后插入代码
m.insertAfter("System.out.println(\"存款业务执行后:2.您存款结束...\");");
return cc.toBytecode();
}catch(NotFoundException e){
e.printStackTrace();
}catch(CannotCompileException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
return null;
}
/**
* 在main 函数执行前,执行的函数
* @param options
* @param ins
*/
public static void premain(String options, Instrumentation ins){
//注册我自己的字节码转换器
ins.addTransformer(new MyClassFileTransformer());
}
}
1.3Test.java的内容
package com.aop.transform;
public class Test {
public static void main(String[] args){
new GdBusiness().deposit();
new GdBusiness().withdrawals();
}
}
1.4 MANIFEST.MF的内容
Manifest-Version: 1.0
Premain-Class: com.aop.transform.MyClassFileTransformer
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Can-Set-Native-Method-Prefix: true
META-INF/MANIFEST.MF内容:
说明:Premain-Class用来允许jar文件作为一个java代理运行
1.5 通过pom.xml 下载 javassist-3.25.0-GA.jar
<!-- asm start-->
<dependency>
<artifactId>asm-commons</artifactId>
<groupId>org.ow2.asm</groupId>
<version>${asm.version}</version>
</dependency>
<dependency>
<artifactId>asm-util</artifactId>
<groupId>org.ow2.asm</groupId>
<version>${asm.version}</version>
</dependency>
<!-- asm end-->
下载到了 /Users/lichunmei/.m2/repository/org/javassist/javassist/3.25.0-GA/javassist-3.25.0-GA.jar
而后把它copy到/Users/lichunmei/Documents/workspace/study/jar-test/
二:运行测试步骤
/**
*agent的方式挂载
1.生成class可以运行一个带main的方法。
把 生成的class 全部放到 /Users/lichunmei/Documents/workspace/study/jar-test/target/com/aop/transform/下
2.各文件放置的位置请看下面tree查出来的结构。
3.打包成aop.jar
--> 到target里打jar包
把class放到这里来了 /Users/lichunmei/Documents/workspace/study/jar-test/target/
jar -cvfm agent-aop.jar META-INF/MANIFEST.MF com
打完后copy到jar-test/目录下
/Users/lichunmei/Documents/workspace/study/jar-test/tree 的目录结构
├── agent-aop.jar
├── javassist-3.25.0-GA.jar
└── target
├── META-INF
│ └── MANIFEST.MF
└── com
└── aop
└── transform
├── GdBusiness.class
├── MyClassFileTransformer.class
├── Test.class
4.运行
jar-test> java -javaagent:agent-aop.jar -cp javassist-3.25.0-GA.jar com.aop.transform.Test
objc[8798]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/bin/java (0x10e9154c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10e9da4e0). One of the two will be used. Which one is undefined.
存款业务执行前:1.欢迎您来存款...
存款业务执行
存款业务执行后:2.您存款结束...
取款业务执行
*/