美文网首页Spring
代理模式(一)

代理模式(一)

作者: 半数的年 | 来源:发表于2019-01-19 13:02 被阅读0次

1、代理模式

被代理人没有时间去做某件事情,交由代理人去做。

例子
  • 媒婆
  • 房屋中介
  • 经纪人

2、静态代理

image.png
  • 代理的动作接口 -- 就是要代理做的事情:相亲
public interface Person {
    public abstract void findLove();
}
  • 被代理人要实现动作接口-- 相亲要找什么样的女生
public class XiaoYuan implements Person {
    @Override
    public void findLove() {
        System.out.println("小元要找短头发、可爱的女生");
    }
}
  • 代理人实现动作接口帮助代理人 -- 在大把资源找到被代理人心仪的女生
public class MeiPo implements Person{

    private Person xiaoYuan;

    MeiPo(XiaoYuan xiaoYuan){
        this.xiaoYuan = xiaoYuan;
    }

    @Override
    public void findLove() {
        System.out.println("媒婆有大把资源,说出你想要的");
        xiaoYuan.findLove();
        System.out.println("媒婆把联系方式给你,你可以谈恋爱了");
    }

}
public class TestProxy {

    public static void main(String[] args) {
        Person meipo = new MeiPo(new XiaoYuan());
        meipo.findLove();  // 媒婆资源比较多,让媒婆帮忙找下合适的小姐姐

        // new XiaoYuan().findLove();  // 本来是要自己去找小姐姐谈恋爱的
    }
}

Output

媒婆有大把资源,说出你想要的
小元要找短头发、可爱的女生
媒婆把联系方式给你,你可以谈恋爱了

3、动态代理 (下面例子讲的是jdk的动态代理)

image.png
public class DynamicMeiPo implements InvocationHandler {

    private Person person;

    // 返回动态生成一个实现代理动作接口的$Proxy0.class类
    public Object newInstance(Person xiaoYuan){
        this.person = xiaoYuan;
        Class clazz = xiaoYuan.getClass();
        // 获取被代理人信息和被代理人实现的接口
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("媒婆有大把资源,说出你想要的");
        method.invoke(person,args);
        System.out.println("媒婆把联系方式给你,你可以谈恋爱了");
        return null;
    
}
  • 通过Proxy.newProxyInstance()会动态生成一个$Proxy0.class,通过下面代码会类的字节码将输出到文件。
public class TestDynamicProxy {

    public static void main(String[] args) {

        // $Proxy0.class类对象
        Person dynamicMeiPo = (Person) (new DynamicMeiPo().newInstance(new XiaoYuan()));
        dynamicMeiPo.findLove();

        // 获取$Proxy0.class类
        byte[] gengarateProxyClass = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{dynamicMeiPo.getClass()});
        try {
            FileOutputStream fos = new FileOutputStream("D:/$Proxy0.class" );
            fos.write(gengarateProxyClass);
            fos.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }
    }
}
  • 其中实现了代理要做的动作接口(Person : findLove()),$Proxy0的父类会有一个InvocationHandler h,用来接收实现InvocationHandler的DynamicMeiPo
public final class $Proxy0 extends Proxy implements Proxy0 
protected InvocationHandler h;
  • $Proxy0 这是实现Person接口的findLove()方法,当对象调用findLove(),会通过invoke(DynamicMeiPo实现的方法)
    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);
        }
    }
(1)、jdk动态代理原理
  • 1、生成代理对象类文件$Proxy0.java代码内容
    /**
     * 动态生成代理对象的代码内容
     *
     * @param interfaces
     * @return
     */
    private static String generateSrc(Class interfaces) {
        StringBuffer src = new StringBuffer();
        src.append("package com.xiaoyuan.aop.myproxy;" + LN);
        src.append("import java.lang.reflect.Method;" + LN);
        src.append("import java.lang.reflect.Proxy;" + LN);
        // 实现代理动作接口
        src.append("public final class $Proxy0 implements " + interfaces.getName() + " {" + LN);
        src.append("YInvocationHandler h;" + LN);

        src.append("public $Proxy0(YInvocationHandler h){" + LN);
        src.append("this.h = h;" + LN);
        src.append("}" + LN);
        // 代理动作接口的方法
        for (Method method : interfaces.getMethods()) {
            src.append("public final " + method.getReturnType() + " findLove()  {" + LN);
            src.append("try {" + LN);
            src.append("Method m3 = Class.forName(\"" + interfaces.getName() + "\").getMethod(\"" + method.getName() + "\");" + LN);
            src.append("h.invoke(this, m3, (Object[])null);" + LN);
            src.append("} catch (Throwable var3) {" + LN);
            src.append("System.out.println(\"出现错误\");" + LN);
            src.append("}" + LN);
            src.append("}" + LN);
        }
        src.append("}");
        return src.toString();
    }
image.png
  • 2、生成java文件
// 2、生成java文件
String filePath = YProxy.class.getResource("").getPath();
File f = new File(filePath + "$Proxy0.java");
FileWriter fos = new FileWriter(f);
fos.write(src);
fos.close();
  • 3、编译成生成$Proxy0.class
// 3、编译成生成$Proxy0.class
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null,manager,null,null,null,iterable);
task.call();
manager.close();
  • 3、$Proxy0.class加载到JVM中并返回类实例
    protected Class<?> findClass(String name) {
        String className = YClassLoader.class.getPackage().getName() + "." + name;
        if (baseDir != null){
            // 拿到$Proxy0.class的文件位置
            File classFile = new File(baseDir, name.replaceAll("\\." , "/") + ".class");
            if (classFile.exists()){
                FileInputStream fis = null;
                try {
                    // 读取该文件到输出流out上
                    fis = new FileInputStream(classFile);
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    byte[] buff = new byte[1024];
                    int len;
                    while ((len = fis.read(buff) )!= -1){
                        out.write(buff, 0 ,len);
                    }
                    // 最后加载到jvm上
                    return defineClass(className, out.toByteArray(), 0, out.size());
                } catch (java.io.IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
  • 4、类实例通过反射生成实例对象返回
// 4、生成实例对象返回
Constructor c = proxyClass.getConstructor(YInvocationHandler.class);
return c.newInstance(h);
(2)、cglib动态代理原理

相关文章

  • 第4章 结构型模式-代理模式

    一、代理模式简介 二、代理模式3个角色 三、代理模式的优点 四、代理模式的实例(游戏代练)

  • 代理模式

    一、什么是代理模式 代理模式(Proxy pattern):代理模式又叫委托模式,是为某个对象提供一个代理对象,并...

  • 理解代理模式

    原创博客地址 简介 代理模式,也叫做委托模式,分为:静态代理动态代理 代理模式也是平时比较常用的设计模式之一,代理...

  • 大话设计模式之代理模式

    代理模式 代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式...

  • GeekBand-C++设计模式-Week2

    代理模式 代理模式的定义 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。代理模式的英文叫做...

  • JAVA代理与动态代理

    代理模式简介 代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就...

  • 设计模式

    单例模式 模板方法模式 工厂模式 代理模式 静态代理 JDK动态代理

  • Android--代理模式和Retrofit源码浅析

    一、代理模式 因为Retrofit用到了动态代理模式,所以先说说代理模式。 1、代理模式的定义 为其他对象提供一种...

  • Android--代理模式和Retrofit源码浅析

    一、代理模式 因为Retrofit用到了动态代理模式,所以先说说代理模式。 1、代理模式的定义 为其他对象提供一种...

  • Java设计模式之代理模式

    代理模式 模式介绍 代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用...

网友评论

    本文标题:代理模式(一)

    本文链接:https://www.haomeiwen.com/subject/masadqtx.html