JDK动态代理

JDK动态代理

1.动态代理

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。

2.类图

在这里插入图片描述

其中Proxy$0是生成的代理类。

3.实现

1.接口Subject和Subject2
interface Subject {
    String Do();
    void unDo();
}
public interface Subject2 {
    int add(int a,int b);
}
2.RealSubject
public class RealSubject implements Subject,Subject2{

    public String Do() {
        return "Hello Word";
    }

    public void unDo() {
        System.out.println("undo");
    }

    public int add(int a, int b) {
        return a+b;
    }
}
3.InvocationHandlerImpl
public class InvocationHandlerImpl implements InvocationHandler {

    Object object;

    public InvocationHandlerImpl(Object object) {
        this.object = object;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在代理真实对象前我们可以添加一些自己的操作
        System.out.println("在调用之前,我要干点啥呢?");

        System.out.println("Method:" + method);

        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        Object returnValue = method.invoke(object, args);

        //在代理真实对象后我们也可以添加一些自己的操作
        System.out.println("在调用之后,我要干点啥呢?");

        return returnValue;
    }
}
4.Main
public class Main {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(realSubject);
        ClassLoader loader = realSubject.getClass().getClassLoader();
        Class[] interfaces = realSubject.getClass().getInterfaces();
        Subject2 proxy = (Subject2) Proxy.newProxyInstance(loader,interfaces,invocationHandler);

        System.out.println(proxy.add(2,4));
    }
}

结果:
在这里插入图片描述

4.原理

//通过该方法生成代理类的字节码。
//proxyName为代理类的类名。
//interfaces为被代理类的实现的接口数组。
//accessFlags为代理类的类访问控制符(public , final等)
if (proxyPkg == null) {
        // if no non-public proxy interfaces, use com.sun.proxy package
    	//ReflectUtil.PROXY_PACKAGE==com.sun.proxy
        proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }

/*
 * Choose a name for the proxy class to generate.
 */
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
    proxyName, interfaces, accessFlags);

最终调用下面的方法生成代理类字节码:

private byte[] generateClassFile() {
    //添加下述的3个Object.class方法
    this.addProxyMethod(hashCodeMethod, Object.class);
    this.addProxyMethod(equalsMethod, Object.class);
    this.addProxyMethod(toStringMethod, Object.class);
    Class[] var1 = this.interfaces;
    int var2 = var1.length;

    int var3;
    Class var4;
    for(var3 = 0; var3 < var2; ++var3) {
        var4 = var1[var3];
        Method[] var5 = var4.getMethods();
        int var6 = var5.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            Method var8 = var5[var7];
            //添加代理接口中的方法
            this.addProxyMethod(var8, var4);
        }
    }

    Iterator var11 = this.proxyMethods.values().iterator();

    List var12;
    while(var11.hasNext()) {
        var12 = (List)var11.next();
        checkReturnTypes(var12);
    }

    Iterator var15;
    try {
        this.methods.add(this.generateConstructor());
        var11 = this.proxyMethods.values().iterator();

        while(var11.hasNext()) {
            var12 = (List)var11.next();
            var15 = var12.iterator();

            while(var15.hasNext()) {
                ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
                //为代理类添加属性(m0,m1,m2.....)
                this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                //添加方法
                this.methods.add(var16.generateMethod());
            }
        }

        this.methods.add(this.generateStaticInitializer());
    } catch (IOException var10) {
        throw new InternalError("unexpected I/O Exception", var10);
    }

    if (this.methods.size() > 65535) {
        throw new IllegalArgumentException("method limit exceeded");
    } else if (this.fields.size() > 65535) {
        throw new IllegalArgumentException("field limit exceeded");
    } else {
        //添加常量池
        this.cp.getClass(dotToSlash(this.className));
        this.cp.getClass("java/lang/reflect/Proxy");
        var1 = this.interfaces;
        var2 = var1.length;

        for(var3 = 0; var3 < var2; ++var3) {
            var4 = var1[var3];
            this.cp.getClass(dotToSlash(var4.getName()));
        }

        this.cp.setReadOnly();
        ByteArrayOutputStream var13 = new ByteArrayOutputStream();
        DataOutputStream var14 = new DataOutputStream(var13);
		//写入字节数组
        try {
            var14.writeInt(-889275714);
            var14.writeShort(0);
            var14.writeShort(49);
            this.cp.write(var14);
            var14.writeShort(this.accessFlags);
            var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
            var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
            var14.writeShort(this.interfaces.length);
            Class[] var17 = this.interfaces;
            int var18 = var17.length;

            for(int var19 = 0; var19 < var18; ++var19) {
                Class var22 = var17[var19];
                var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
            }

            var14.writeShort(this.fields.size());
            var15 = this.fields.iterator();

            while(var15.hasNext()) {
                ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
                var20.write(var14);
            }

            var14.writeShort(this.methods.size());
            var15 = this.methods.iterator();

            while(var15.hasNext()) {
                ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
                var21.write(var14);
            }

            var14.writeShort(0);
            return var13.toByteArray();
        } catch (IOException var9) {
            throw new InternalError("unexpected I/O Exception", var9);
        }
    }
}

5.反编译生成的代理类字节码

1.代码
//将代理类的字节码数组,写入一个class文件中。
public class GeneratorProxyClass {
    public static void main(String[] args) throws Exception{
        RealSubject realSubject = new RealSubject();
        Class[] interfaces = realSubject.getClass().getInterfaces();
        String proxyName = "MyProxyClass";//为我们生成的代理类叫一个名字
        //调用上面的ProxyGenerator.generateProxyClass()方法生成代理类字节码
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, 17);
		//将字节码写入该文件
        File file = new File("MyProxyClass.class");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(proxyClassFile);
        fos.flush();
        fos.close();
    }
}
2.查看反编译后类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import Designpattern.JDK_Proxy.Subject;
import Designpattern.JDK_Proxy.Subject2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
//该类继承Proxy,实现了接口。
public final class MyProxyClass extends Proxy implements Subject, Subject2 {
    //类的静态属性,会在该类加载是被赋值。
    private static Method m1;
    private static Method m4;
    private static Method m2;
    private static Method m5;
    private static Method m3;
    private static Method m0;
	//构造函数,组和了一个InvocationHandler
    public MyProxyClass(InvocationHandler var1) throws  {
        super(var1);
    }
	//super.h为父类Proxy组和进去的InvocationHandler对象。
    /*
    public class Proxy implements java.io.Serializable {

    protected InvocationHandler h;
   	....
    }
    */
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void unDo() throws  {
        try {
            super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 int add(int var1, int var2) throws  {
        try {
            return (Integer)super.h.invoke(this, m5, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final String Do() throws  {
        try {
            return (String)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);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
	//静态方法,类初始化的时候为静态属性赋值。
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m4 = Class.forName("Designpattern.JDK_Proxy.Subject").getMethod("unDo");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m5 = Class.forName("Designpattern.JDK_Proxy.Subject2").getMethod("add", Integer.TYPE, Integer.TYPE);
            m3 = Class.forName("Designpattern.JDK_Proxy.Subject").getMethod("Do");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值