静态和动态代理

介绍

在这里插入图片描述

代理模式涉及到三个对象

行为接口

真实对象

代理对象

行为接口
/**
 * 代理抽象角色: 定义了服务的接口
 */
public interface Massage {
    void massage();
}
真实对象
/**
 *  实实现类: Qit
 */
public class Qit implements Massage, Wash {

    @Override
    public void massage() {
        System.out.println("Qit发了个消息");
    }

    @Override
    public void wash() {

    }
}
代理对象
/**
 * 代理对象:经纪人
 */
public class Agent implements Massage {

    private final Massage massage;

    public Agent(Massage massage) {
        this.massage = massage;
    }

    //....前置处理
    public void before() {
        System.out.println("前置处理");
    }

    //....后置处理
    public void after() {
        System.out.println("后置处理");
    }

    @Override
    public void massage() {
        before();
        massage.massage();
        after();
    }
}

ok~

静态代理

public static void main(String[] args) throws Exception {
        //静态代理
        Massage message = new Qit();
        Agent agent = new Agent(message);

        agent.massage();
}
> Task :lib:MyClass.main()
前置处理
Qit发了个消息
后置处理

代理成功。我们可以看到Qit不只实现了Message接口,还实现了Wash接口,若要代理Wash接口就需要再创建一个经纪人代理对象,如何才能不增加类的同事代理多个接口呢?

动态代理

public static void main(String[] args) {
        Qit qit = new Qit();
        Object o = Proxy.newProxyInstance(MyClass.class.getClassLoader(),
                new Class[]{Massage.class,Wash.class}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//                        System.out.println(o.toString());//会导致无限进入此回调,栈溢出。
                        System.out.println("前置处理");
                        method.invoke(qit,objects);
                        System.out.println("后置处理");
                        return o;
                    }
                });

        Massage massage = (Massage) o;
        massage.massage();

        Wash wash = (Wash) o;
        wash.wash();
}
> Task :lib:MyClass.main()
前置处理
Qit发了个消息
后置处理
前置处理
后置处理
动态代理源码分析

先贴源码$Proxy

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        // Android-removed: SecurityManager calls
        /*
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
        */

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            // Android-removed: SecurityManager / permission checks.
            /*
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            */

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                // BEGIN Android-removed: Excluded AccessController.doPrivileged call.
                /*
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
                */

                cons.setAccessible(true);
                // END Android-removed: Excluded AccessController.doPrivileged call.
            }
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
}

调用newProxyInstance

只能代理接口,拷贝接口得到Class[]

final Class<?>[] intfs = interfaces.clone();

查找或生成指定的代理类

Class<?> cl = getProxyClass0(loader, intfs);

获取Class的构造方法

 final Constructor<?> cons = cl.getConstructor(constructorParams);

类的完整生命周期

在这里插入图片描述

动态代理会帮助我们在内存中生成一个Class对象

通过Proxy.class$class ProxyClassFactory生成.class也就是byte[]

byte[] var22 = ProxyGenerator.generateProxyClass(var23, var2, var17);

再由byte[]生成Class对象

return Proxy.defineClass0(var1, var23, var22, 0, var22.length);

我们通过IO流写入查看动态代理生成的.class

String name = Qit.class.getName() + "$Proxy0";
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{TestProxy.class});
FileOutputStream fos = new FileOutputStream("lib/" + name + ".class");
fos.write(bytes);
fos.close();

得到.class文件,可以看出构造时传入InvocationHandler对象,由他调用invoke方法触发回调

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.enjoy.lib;

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

public final class Massage$Proxy0 extends Proxy implements Massage {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public Massage$Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    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 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 massage() 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);
        } 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"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.enjoy.lib.Massage").getMethod("massage");
            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
发出的红包

打赏作者

Qi T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值