大话设计模式之代理模式(二)与JDK动态代理原理

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/yjy91913/article/details/79570362

什么是代理模式?

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

动态代理与静态代理对比
这里写图片描述

静态代理实现模式

Father 是Son的代理人
Person接口

public interface Person {

    void findLove();

    void job();

    void buy();
}
public class Son implements Person {

    @Override
    public void findLove() {
        System.out.println("相亲");
    }

    @Override
    public void job() {
        System.out.println("干活");
    }

    @Override
    public void buy() {
        System.out.println("购物");
    }
}
public class Father {

    private Son son;

    //静态代理缺点
    //只能给儿子找对象,不能帮女儿找
    public void findLove(){
        System.out.println("根据你的要求物色");
        this.son.findLove();
        System.out.println("双方父母是否同意");
    }

    //静态代理,有多少方法 就得做多少代理
    //在代理之前 所有东西都是已知的
    public void job() {
        System.out.println("根据你的要求物色");
        this.son.job();
        System.out.println("双方父母是否同意");
    }

    public void buy() {
        System.out.println("根据你的要求物色");
        this.son.buy();
        System.out.println("双方父母是否同意");
    }

}

静态代理的缺点就是 在代理之前 所有东西都是已知的 对象是固定的 方法也是固定的

JDK动态代理实现模式

        /**
         * 原理
         * 1.拿到被代理对象的引用,并且获取其接口通过反射获取
         * 2.通过JDK的Proxy类,重新生成新的类,同时实现被代理类所实现的所有接口
         * 3.动态的生成java代码,在Proxy把新加的业务逻辑方法,去调用(在代码中体现)
         * 4.编译新生成的java代码.class
         * 5.再重新加载JVM运行
         *
         * 以上就叫字节码重组
         * JDK有规范 只要是$开头一般都是自动生成
         *
         * 通过反编译可以查看源代码
         */

先写一个Demo
先写一个代理类,他是一个媒婆 代理了Man (Man实现了Person接口

public class JDKMeiPo implements InvocationHandler{

    private Person target;

    public Object getInstance(Person target){
        this.target = target;
        Class clazz = target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        if("findLove".equalsIgnoreCase(method.getName())){
            System.out.println("我是媒婆,我要给你找对象");
            Object invoke = method.invoke(this.target, args);
            System.out.println("如果合适就准备办事");
            return invoke;
        }else {
            Object invoke = method.invoke(this.target, args);
            return invoke;
        }
    }
}

这个就是测试类,可以这是 我们的person已经是一个被代理过后的增强类

public class JDKProxyTest {

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

        Person person = (Person) new JDKMeiPo().getInstance(new Man());
        person.findLove();
        System.out.println(person.getClass());

    //从JVM拿到临时生成的解码文件,把这个字节码文件储存起来
        byte[] $proxy0s = ProxyGenerator.generateProxyClass("$proxy0", new Class[]{person.getClass()});
        FileOutputStream os = new FileOutputStream("E:\\$proxy0.class");
        os.write($proxy0s);

    }
}

这个文件我们可以通过反编译,内容如下:
这个就是JDK生成的字节码文件:

import com.sun.proxy..Proxy0;
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 Proxy0 {
    private static Method m1;
    private static Method m5;
    private static Method m3;
    private static Method m2;
    private static Method m6;
    private static Method m11;
    private static Method m13;
    private static Method m0;
    private static Method m8;
    private static Method m12;
    private static Method m7;
    private static Method m10;
    private static Method m4;
    private static Method m9;

    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 InvocationHandler getInvocationHandler(Object var1) throws IllegalArgumentException {
        try {
            return (InvocationHandler)super.h.invoke(this, m5, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void findLove() throws  {
        try {
            super.h.invoke(this, m3, (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 Class getProxyClass(ClassLoader var1, Class[] var2) throws IllegalArgumentException {
        try {
            return (Class)super.h.invoke(this, m6, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

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

    public final void notifyAll() throws  {
        try {
            super.h.invoke(this, m13, (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);
        }
    }

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

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

    public final Object newProxyInstance(ClassLoader var1, Class[] var2, InvocationHandler var3) throws IllegalArgumentException {
        try {
            return (Object)super.h.invoke(this, m7, new Object[]{var1, var2, var3});
        } catch (RuntimeException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final void wait(long var1) throws InterruptedException {
        try {
            super.h.invoke(this, m10, new Object[]{Long.valueOf(var1)});
        } catch (RuntimeException | InterruptedException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final boolean isProxyClass(Class var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m4, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void wait(long var1, int var3) throws InterruptedException {
        try {
            super.h.invoke(this, m9, new Object[]{Long.valueOf(var1), Integer.valueOf(var3)});
        } catch (RuntimeException | InterruptedException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m5 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getInvocationHandler", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("com.sun.proxy.$Proxy0").getMethod("findLove", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m6 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getProxyClass", new Class[]{Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;")});
            m11 = Class.forName("com.sun.proxy.$Proxy0").getMethod("getClass", new Class[0]);
            m13 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notifyAll", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m8 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[0]);
            m12 = Class.forName("com.sun.proxy.$Proxy0").getMethod("notify", new Class[0]);
            m7 = Class.forName("com.sun.proxy.$Proxy0").getMethod("newProxyInstance", new Class[]{Class.forName("java.lang.ClassLoader"), Class.forName("[Ljava.lang.Class;"), Class.forName("java.lang.reflect.InvocationHandler")});
            m10 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[]{Long.TYPE});
            m4 = Class.forName("com.sun.proxy.$Proxy0").getMethod("isProxyClass", new Class[]{Class.forName("java.lang.Class")});
            m9 = Class.forName("com.sun.proxy.$Proxy0").getMethod("wait", new Class[]{Long.TYPE, Integer.TYPE});
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

以上代码可以得出这个新的临时的类是按照我们需求加强的

猜你喜欢

转载自blog.csdn.net/yjy91913/article/details/79570362
今日推荐