• 透过字节码分析Java动态代理机制。


    一、创建动态代理代码

    1、创建接口

    public interface Subject {
        void request();
    }
    

      

    2、创建接口实现类

    public class RealSubject  implements  Subject
    {
        @Override
        public void request() {
            System.out.println("From real subject");
        }
    }
    

      

    3、创建DynamicSubject类

    public class DynamicSubject implements InvocationHandler {
    
        private  Object sub;
    
        public  DynamicSubject(Object obj){
            this.sub = obj;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before calling:" + method);
            method.invoke(this.sub, args);
            System.out.println("after calling:" + method);
            return null;
        }
    }
    

      

    4、创建测试类

    public class Client {
        public static void main(String[] args) {
    
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
    
            RealSubject rs = new RealSubject();
            InvocationHandler ds = new DynamicSubject(rs);
    
            Class<?> cls = rs.getClass();
            Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), ds);
            subject.request();
    
            System.out.println(subject.getClass());
            System.out.println(subject.getClass().getSuperclass());
        }
    }
    

      输出结果:

    before calling:public abstract void com.example.jvm.bytecode.Subject.request()
    From real subject
    after calling:public abstract void com.example.jvm.bytecode.Subject.request()
    class com.sun.proxy.$Proxy0
    class java.lang.reflect.Proxy
    

      

    查看源码,动态代理类在ProxyGenerator类的generateProxyClass生成。

       public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
            ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
            final byte[] var4 = var3.generateClassFile();
            if(saveGeneratedFiles) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        try {
                            int var1 = var0.lastIndexOf(46);
                            Path var2;
                            if(var1 > 0) {
                                Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar), new String[0]);
                                Files.createDirectories(var3, new FileAttribute[0]);
                                var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                            } else {
                                var2 = Paths.get(var0 + ".class", new String[0]);
                            }
    
                            Files.write(var2, var4, new OpenOption[0]);
                            return null;
                        } catch (IOException var4x) {
                            throw new InternalError("I/O exception saving generated file: " + var4x);
                        }
                    }
                });
            }
    
            return var4;
        }
    

      可以发现saveGeneratedFiles为true时,可以将代理类保存到磁盘上。

    因此在测试类中sun.misc.ProxyGenerator.saveGeneratedFiles属性设置为true

    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");


    最终生成的.class 文件位置如下图

    打开$Proxy0.class
    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package com.sun.proxy;
    
    import com.example.jvm.bytecode.Subject;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy0 extends Proxy implements Subject {
        private static Method m1;
        private static Method m2;
        private static Method m3;
        private static Method m0;
    
        public $Proxy0(InvocationHandler var1) throws  {
            super(var1);
        }
    
        public final boolean equals(Object var1) throws  {
            try {
                return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
            } catch (RuntimeException | Error var3) {
                throw var3;
            } catch (Throwable var4) {
                throw new UndeclaredThrowableException(var4);
            }
        }
    
        public final String toString() throws  {
            try {
                return (String)super.h.invoke(this, m2, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final void request() throws  {
            try {
                super.h.invoke(this, m3, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        public final int hashCode() throws  {
            try {
                return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        static {
            try {
                m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
                m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
                m3 = Class.forName("com.example.jvm.bytecode.Subject").getMethod("request", new Class[0]);
                m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    

      

  • 相关阅读:
    Hive的mysql安装配置
    Linux下的MySQL安装
    Hive的安装与基础指令
    浅谈数据库和数据仓库
    Hive的学习之路(理论篇)
    Spring---bean的命名
    Spring---单例模式(Singleton)的6种实现
    Spring---加载配置文件的几种方法(org.springframework.beans.factory.BeanDefinitionStoreException)
    Spring---配置文件概述
    Spring---Bean生命周期
  • 原文地址:https://www.cnblogs.com/linlf03/p/11109977.html
Copyright © 2020-2023  润新知