jdk代理实现代码:
public class JdkProxyC implements InvocationHandler { private Object target; public JdkProxyC(Object target) { this.target = target; } public Object getProxy() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { /** * ClassLoader loader, * Class<?>[] interfaces, * InvocationHandler h */ ClassLoader loader = this.target.getClass().getClassLoader(); Class<?>[] interfaces = this.target.getClass().getInterfaces(); InvocationHandler handler = this; //实现 InvocationHandler 接口的类 Object instance = Proxy.newProxyInstance(loader, interfaces, handler); return instance; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理前----->"); Object obj = method.invoke(this.target, args); System.out.println("代理后----->"); return obj; } public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { //设置开启代理类.class文件的输出 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true"); UserServer o = (UserServer) new JdkProxyC(new UserServerImpl()).getProxy();//必须转成接口 o.proxyMethod(); } }View Code
ProxyGenerator.generateProxyClass()接口输出jdk代理类的字节码,里面的 saveGeneratedFiles 开关:
private static final boolean saveGeneratedFiles = java.security.AccessController.doPrivileged( new GetBooleanAction( "jdk.proxy.ProxyGenerator.saveGeneratedFiles"));
是"jdk.proxy.ProxyGenerator.saveGeneratedFiles“值的由来,默认是false, 在main函数中设置 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true"); 开启这个开关,就会输出代理类的 .class文件,方便查看代理过程
cglib代理实现代码:
public class CglibProxy implements MethodInterceptor, CallbackFilter { private Object target; public CglibProxy(Object target) { this.target = target; } public Object getProxy() { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass());//设置类、接口 enhancer.setCallback(this);// 实现 MethodInterceptor 接口的类 //设置Callback[] callbacks 数组 //enhancer.setCallbacks(callbacks); //实现 CallbackFilter接口 方法返回CallbackFilter数组下标 //enhancer.setCallbackFilter(this); return enhancer.create();//返回 创建代理类 } /** * @param o 增强对象 * @param method 调用方法 * @param objects 方法参数 * @param methodProxy 调用父类方法的代理 * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("代理前----->"); //一下三种方式均可调用方法,通过代理类源码,可以分析其不同 // method.invoke(this.target, objects); // methodProxy.invoke(this.target, objects);//target速度更快 // methodProxy.invokeSuper(o, objects);//o:代理对象 System.out.println("代理后----->"); return null; } @Override public int accept(Method method) { return 0;//默认返回0 } public static void main(String[] args) { UserServerImpl proxy = (UserServerImpl) new CglibProxy(new UserServerImpl()).getProxy(); proxy.proxyMethod(); } }View Code
cglib代理类的对应 .class文件的输出需要如下配置,没有“VM选项的”,需要点击“修改选项”选中“添加VM选项”,然后增加 -Dcglib.debugLocation=F:\WorkSpaceJava\spring_ioc_configration\jdk\cglib 等号后边是你想要输出的代理类字节文件的路径
cglib代理类的生成是通过asm进行字节码生成的。 字节码操作的另一项技术是 javassist
asm 需要依赖的包:
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm --> <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm</artifactId> <version>9.5</version> </dependency>
asm 通过字节码生成Person字节码类示例:
public class TestAsm { public static void main(String[] args) throws IOException { ClassWriter classWriter = new ClassWriter(0); // 通过visit方法确定类的头部信息 classWriter.visit(Opcodes.V1_8,// java版本 Opcodes.ACC_PUBLIC,// 类修饰符 "Person", // 类的全限定名 null, "java/lang/Object", null); //创建构造函数 MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>","()V",false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); // 定义test方法 MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "test", "()V", null, null); methodVisitor.visitCode(); methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); methodVisitor.visitLdcInsn("hello world!"); methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V",false); methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitMaxs(2, 2); methodVisitor.visitEnd(); classWriter.visitEnd(); // 使classWriter类已经完成 // 将classWriter转换成字节数组写到文件里面去 byte[] data = classWriter.toByteArray(); File file = new File("F:\\WorkSpaceJava\\spring_ioc_configration\\jdk\\asm\\Person.class"); FileOutputStream fout = new FileOutputStream(file); fout.write(data); fout.close(); } }View Code
生成Person字节码类:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // public class Person { public Person() { } public void test() { System.out.println("hello world!"); } }
javassist需要依赖的包:
<!-- https://mvnrepository.com/artifact/org.javassist/javassist --> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.2-GA</version> </dependency>
javassist通过字节码生成Person字节码类示例:
public class TestJavassist { public static void main(String[] args) throws NotFoundException, CannotCompileException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { ClassPool pool = ClassPool.getDefault(); // 1. 创建一个空类 CtClass cc = pool.makeClass("com.test.Person"); // 2. 新增一个字段 private String name; // 字段名为name CtField param = new CtField(pool.get("java.lang.String"), "name", cc); // 访问级别是 private param.setModifiers(Modifier.PRIVATE); // 初始值是 "beijing" cc.addField(param, CtField.Initializer.constant("beijing")); // 3. 生成 getter、setter 方法 cc.addMethod(CtNewMethod.setter("setName", param)); cc.addMethod(CtNewMethod.getter("getName", param)); // 4. 添加无参的构造函数 CtConstructor cons = new CtConstructor(new CtClass[]{}, cc); cons.setBody("{name = \"beijing\";}"); cc.addConstructor(cons); // 5. 添加有参的构造函数 cons = new CtConstructor(new CtClass[]{pool.get("java.lang.String")}, cc); // $0=this / $1,$2,$3... 代表方法参数 cons.setBody("{$0.name = $1;}"); cc.addConstructor(cons); // 6. 创建一个名为printName方法,无参数,无返回值,输出name值 CtMethod ctMethod = new CtMethod(CtClass.voidType, "printName", new CtClass[]{}, cc); ctMethod.setModifiers(Modifier.PUBLIC); ctMethod.setBody("{System.out.println(name);}"); cc.addMethod(ctMethod); //这里会将这个创建的类对象编译为.class文件 cc.writeFile("F:\\WorkSpaceJava\\spring_ioc_configration\\jdk\\javassist"); // 这里不写入文件,直接实例化 // Object person = cc.toClass().newInstance(); // // 设置值 // Method setName = person.getClass().getMethod("setName", String.class); // setName.invoke(person, "dadududu"); // // 输出值 // Method execute = person.getClass().getMethod("printName"); // execute.invoke(person); } }View Code
生成Person字节码类:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // package com.test; public class Person { private String name = "beijing"; public void setName(String var1) { this.name = var1; } public String getName() { return this.name; } public Person() { this.name = "beijing"; } public Person(String var1) { this.name = var1; } public void printName() { System.out.println(this.name); } }
标签:target,Object,代理,class,cglib,new,public,asm,name From: https://www.cnblogs.com/ruber/p/17509584.html