欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jdk动态代理实现原理

程序员文章站 2022-03-10 13:00:43
...
jdk的动态代理即使用反射来实现,具体由Proxy、InvocationHandler等类来实现的。

具体调用过程比较难理解,但是如果看到生成的代理类就不难理解了。

代码如下:

接口类:Calculator.java
package com.yangjianzhou.javaBasics;

/**
 * Created by yangjianzhou on 16-5-8.
 */
public interface Calculator {

    public int  add(int operator1 , int operator2);

}



实现类:CalculatorImpl.java
package com.yangjianzhou.javaBasics;

/**
 * Created by yangjianzhou on 16-5-8.
 */
public class CalculatorImpl implements Calculator {

    @Override
    public int add(int operator1, int operator2) {
        System.out.println("operator1 + operator2 = " + (operator1 + operator2));
        return operator1 + operator2;
    }
}



代理类:CalculatorProxy.java
package com.yangjianzhou.javaBasics;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by yangjianzhou on 16-5-8.
 */
public class CalculatorProxy {

    public void executeProxy(){

        Calculator calculator = new CalculatorImpl();
        LogHandler logHandler = new LogHandler(calculator);
        Calculator proxy = (Calculator) Proxy.newProxyInstance(calculator.getClass().getClassLoader() , calculator.getClass().getInterfaces(),logHandler);
        proxy.add(2,3);
    }
}

class LogHandler implements InvocationHandler{

    Object obj ;

    public LogHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.doBefore();
        Object object = method.invoke(obj , args);
        this.doAfter();
        return object;
    }

    public void doBefore(){
        System.out.println("log before method");
    }

    public void doAfter(){
        System.out.println("log after method");
    }
}



测试代码:TestProxy.java
package com.yangjianzhou.javaBasics;

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;

/**
 * Created by yangjianzhou on 16-5-8.
 */
public class TestProxy {

    public static void main(String[] args) throws Exception {

        CalculatorProxy calculatorProxy = new CalculatorProxy();
        calculatorProxy.executeProxy();
        byte[] classCode = ProxyGenerator.generateProxyClass("com.yangjianzhou.javaBasics.", new Class[]{Calculator.class});
        FileOutputStream fileOutputStream = new FileOutputStream("/tmp/proxy.class");
        fileOutputStream.write(classCode);
        fileOutputStream.close();
    }
}




反编译proxy.class得到的java代码如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.yangjianzhou.javaBasics;

import com.yangjianzhou.javaBasics.Calculator;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class  extends Proxy implements Calculator {
    private static Method m1;
    private static Method m0;
    private static Method m3;
    private static Method m2;

    public (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 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);
        }
    }

    public final int add(int var1, int var2) throws  {
        try {
            return ((Integer)super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1), Integer.valueOf(var2)})).intValue();
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    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);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m3 = Class.forName("com.yangjianzhou.javaBasics.Calculator").getMethod("add", new Class[]{Integer.TYPE, Integer.TYPE});
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}



因此,调用proxy.add(2,3),实际上就是调用LogHandler的invoke方法