重学设计模式——代理模式之手写JDK动态实现

重学Android基础系列篇(三):架构动态编程技术原理 本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~ 阅读详情

代理模式

为其他对象提供一种代理以控制对这个对象的访问。

最重要的三要素:

  • 有执行者、被代理人
  • 对被代理人来说,这件事是一定要去做,但是自己因为某些原因暂时不能去做,只能通过代理来做
  • 代理能获取到被代理人的资料(拿到被代理人的引用)
动态代理

动态代理通过反射机制动态地生成代理者的对象,我们在code的时候不必要关心代理谁,代理谁我们将在执行阶段来决定。JDK为我们已提供了很方便的动态代理接口InvocationHandler。

先来定义一个场景,我要去申请专利,这个时候就可以通过专利代理人来进行专利申请。那么我就是被代理者,专利代理人就是代理。

业务接口

public interface Person {
    void apply();
}

业务实现类

public class Apkcore implements Person {
    @Override
    public void apply() {
        System.out.println("apkcore开始申请专利");
    }
}

业务处理类(专利代理人)

public class PatentAgent implements InvocationHandler {

    private Person mPersion;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(mPersion, args);
        after();
        return result;
    }

    private void after() {
        System.out.println("申请提交成功了");
    }

    private void before() {
        System.out.println("准备申请专利的材料");
    }
}

测试类

    public static void main(String[] args) {
        PatentAgent patentAgent = new PatentAgent();
        Person person = (Person) patentAgent.getInstance(new Apkcore());
        person.apply();
    }

可以看到生成的结果为:

准备申请专利的材料
apkcore开始申请专利
申请提交成功了

到此,使用JDK给我们提供的InvocationHandler实现动态代理就已经完成了。

动态代理的实现原理

我们可以打印一下测试中得到的person对象

        PatentAgent patentAgent = new PatentAgent();
        Person person = (Person) patentAgent.getInstance(new Apkcore());
        System.out.println(person.getClass());
        person.apply();

可以看到输出结果为class com.sun.proxy.$Proxy0

我们在生成的class中,是不能找到这个$Proxy0的,它只是JVM在内存中生成的动态代理类。

那么我们可以把这个类用一个文件写出来。

        //获取字节码内容
        byte[] data = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Persion.class});
        FileOutputStream os = null;
        try {
            String path = "$Proxy0.class";
            File file = new File(path);
            if (file.exists()) {
                file.delete();
            }
            os = new FileOutputStream("$Proxy0.class");
            os.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

可以在根目录下生成$Proxy0.class文件,打开这个文件

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

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

    //这是person.apply方法调用的地方
    public final void apply() throws  {
        try {
            //是调用了父类的h的invoke方法
            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就是apply方法,另外三个都是Object的方法,可以忽略不看
            m3 = Class.forName("com.apkcore.proxy.blog.Person").getMethod("apply");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

可以看到,主要就看apply方法,这是我们调用的方法super.h在父类Proxy中

protected InvocationHandler h;

而我们在PatentAgent中,使用Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this)这个this就是PatentAgent,它是个InvocationHandler的实现类,所以可以知道,super.h.invoke其实就是调用了PatentAgent中的invoke方法,而invoke的第二个参数m3就是m3 = Class.forName("com.apkcore.proxy.blog.Person").getMethod("apply");,所以我们在PatentAgent中调用method.invoke(mPersion, args)就相当于mPerson.apply方法。

动态代理的过程:

  • Proxy通过传递给它的参数(interface/invocationHandler)生成代理类$Proxy0
  • Proxy通过传递给它的参数(ClassLoade)来加载生成的代理类$Proxy0的字节码文件
手写JDK动态代理

我们先看源码中InvocationHandler

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

所以我们可以模仿着实现自己的InvocationHandler

public interface MyInvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}

那么对应的,我们的动态代理PatentAgent要改为

public class MyPatentAgent implements MyInvocationHandler {

    private Person mPersion;

    public Object getInstance(Person persion) {
        this.mPersion = persion;
        Class clazz = persion.getClass();
        return MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(mPersion, args);
        after();
        return result;
    }

    private void after() {
        System.out.println("申请提交成功了");
    }

    private void before() {
        System.out.println("准备申请专利的材料");
    }
}

其中的ClassLoader与Proxy都使用自己的而不是JDK提供的。

public class MyProxy {
    public static Object newProxyInstance(MyClassLoader classLoader, Class[] interfaces, MyPatentAgent h) {
        return null;
    }
}

public class MyClassLoader extends ClassLoader{
}
生成java文件并保存

由上面的知识我们可以知道,我们要先在运行时生成一个$Proxy0这样的java文件

public class MyProxy {

    private static final String ln = "\r\n";

    public static Object newProxyInstance(MyClassLoader classLoader, Class[] interfaces, MyPatentAgent h) {
        if (h == null) {
            throw new NullPointerException();
        }
        //1.生成源代码$MyProxy0这个源文件
        //为了实现方便,默认只代理一个接口
        String proxySrc = generateSrc(interfaces[0]);
        //2.保存到文件
        String filePath = MyProxy.class.getResource("").getPath();
        File f = new File(filePath + "$MyProxy0.java");
        FileWriter fw = null;
        try {
            fw = new FileWriter(f);
            fw.write(proxySrc);
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    private static String generateSrc(Class interfaces) {
        Method[] methods = interfaces.getMethods();
        StringBuilder sb = new StringBuilder();
        sb.append("package ")
                .append(MyProxy.class.getPackage().getName()).append(";").append(ln)
                .append("import java.lang.reflect.Method;").append(ln)
                .append("public class $MyProxy0 implements ").append(interfaces.getName()).append("{").append(ln)
                .append("MyInvocationHandler h;").append(ln)
                .append("public $MyProxy0(MyInvocationHandler h) {").append(ln)
                .append("this.h = h;").append(ln)
                .append("}").append(ln);

        for (Method method : methods) {
            sb.append("public ")
                    //使用最简单的不传参的方法
                    .append(method.getReturnType().getName()).append(" ").append(method.getName())
                    .append(" () {").append(ln)
                    .append("try {").append(ln)
                    .append("Method m = ").append(interfaces.getName()).append(".class.getMethod(\"").append(method.getName()).append("\",new Class[]{});").append(ln)
                    .append("this.h.invoke(this,m,null);").append(ln)
                    .append("}catch(Throwable throwable){ }").append(ln)
                    .append("}").append(ln);
        }
        sb.append("}");

        return sb.toString();
    }
}

append手写代码的时候,可以边写边生成,查看哪里写得有问题

调用

    public static void main(String[] args) {
        MyPatentAgent patentAgent = new MyPatentAgent();
//        Person person = (Person)
                patentAgent.getInstance(new Apkcore());
//        System.out.println(person.getClass());
//        person.apply();

    }
}

来进行文件的生成,生成的文件在

然后把这个java文件复制到我们的工程中,可以查看我们是否写漏或者写错。

生成的$MyProxy0文件内容如下

package com.apkcore.proxy.blog.custom;

import java.lang.reflect.Method;

public class $MyProxy0 implements com.apkcore.proxy.blog.Person {
    MyInvocationHandler h;

    public $MyProxy0(MyInvocationHandler h) {
        this.h = h;
    }

    public void apply() {
        try {
            Method m = com.apkcore.proxy.blog.Person.class.getMethod("apply", new Class[]{});
            this.h.invoke(this, m, null);
        } catch (Throwable throwable) {
        }
    }
}
把java文件编译成class文件

JavaCompiler:jdk用来编译java的源程式,提供在运行期动态编译java代码为字节码的功能

            //3.编译源代码,并生成class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(f);

            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();

运行测试代码,就会在编译目录下生成一个class文件。如图

将class文件中的内容,加载到JVM中

现在我们已经得到了我们所需要的class文件,只需要把它加载到jvm中即可

            //4.将class文件中的内容动态加载到JVM中
            //5.返回被代理的代理对象
            Class proxyClass = classLoader.findClass("$MyProxy0");
            Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);
            return constructor.newInstance(h);

整个MyProxy的代码如下

public class MyProxy {

    private static final String ln = "\r\n";

    public static Object newProxyInstance(MyClassLoader classLoader, Class[] interfaces, MyPatentAgent h) {
        if (h == null) {
            throw new NullPointerException();
        }
        //1.生成源代码$MyProxy0这个源文件
        //为了实现方便,默认只代理一个接口
        String proxySrc = generateSrc(interfaces[0]);
        //2.保存到文件
        String filePath = MyProxy.class.getResource("").getPath();
        File f = new File(filePath + "$MyProxy0.java");
        FileWriter fw = null;
        try {
            fw = new FileWriter(f);
            fw.write(proxySrc);
            fw.flush();

            //3.编译源代码,并生成class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(f);

            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();

            //4.将class文件中的内容动态加载到JVM中
            //5.返回被代理的代理对象
            Class proxyClass = classLoader.findClass("$MyProxy0");
            Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);
            return constructor.newInstance(h);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private static String generateSrc(Class interfaces) {
        Method[] methods = interfaces.getMethods();
        StringBuilder sb = new StringBuilder();
        sb.append("package ")
                .append(MyProxy.class.getPackage().getName()).append(";").append(ln)
                .append("import java.lang.reflect.Method;").append(ln)
                .append("public class $MyProxy0 implements ").append(interfaces.getName()).append("{").append(ln)
                .append("MyInvocationHandler h;").append(ln)
                .append("public $MyProxy0(MyInvocationHandler h) {").append(ln)
                .append("this.h = h;").append(ln)
                .append("}").append(ln);

        for (Method method : methods) {
            sb.append("public ")
                    //使用最简单的不传参的方法
                    .append(method.getReturnType().getName()).append(" ").append(method.getName())
                    .append(" () {").append(ln)
                    .append("try {").append(ln)
                    .append("Method m = ").append(interfaces.getName()).append(".class.getMethod(\"").append(method.getName()).append("\",new Class[]{});").append(ln)
                    .append("this.h.invoke(this,m,null);").append(ln)
                    .append("}catch(Throwable throwable){ }").append(ln)
                    .append("}").append(ln);
        }
        sb.append("}");

        return sb.toString();
    }
}

可以知道,我们现在只需要在MyClassLoader中findClasss进行加载

public class MyClassLoader extends ClassLoader{

    private File baseDir;

    public MyClassLoader() {
        this.baseDir = new File(MyClassLoader.class.getResource("").getPath());
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String className = MyClassLoader.class.getPackage().getName()+"."+name;
        if (null!=baseDir) {
            File classFile = new File(baseDir,name.replaceAll("\\.","/")+".class");
            if (classFile.exists()){
                FileInputStream in = null;
                ByteArrayOutputStream out = null;
                try {
                    //先把class文件转化为字节流
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] buff = new byte[1024];
                    int len;
                    while ((len = in.read(buff)) != -1) {
                        out.write(buff, 0, len);
                    }
                    //使用defineClass把字节流传jvm中
                    return defineClass(className, out.toByteArray(), 0, out.size());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (null != in) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (null!=out){
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return super.findClass(name);
    }
}

运行测试代码

    public static void main(String[] args) {
        MyPatentAgent patentAgent = new MyPatentAgent();
        Person person = (Person)
                patentAgent.getInstance(new Apkcore());
        System.out.println(person.getClass());
        person.apply();

    }

class com.apkcore.proxy.blog.custom.$MyProxy0
准备申请专利的材料
apkcore开始申请专利
申请提交成功了

这时我们发现,在我们的编译目录下是有$MyProxy0.,java和.class两个文件存在的,我们也可以在使用完之后增加一个删除语句,分别在MyProxy和MyClassLoader的finally语句中加入文件delete()方法就行了

总结

通过手写了JDK的动态代理,对代理模式的动态代理认识又加深了一步,原理就是拿到被代理对象的引用,然后获取它的接口,jdk代理重新生成一个类,同时实现我们给的代理对象所实现的接口,把被代理的对象引用也拿到了,重新动态生成一个class字节码,然后编译。


参考

手写jdk动态代理


我的掘金

下面是我的公众号,欢迎大家关注我

两万字吐血总结,代理模式及手写实现动态代理(aop原理,基于jdk动态代理) 代理模式及手实现动态代理(aop原理)一、代理模式1. 定义2. 示例(1)静态代理(2)动态代理3. 通用类图4. 代理模式的优点二、jdk动态代理实现原理1. jdk动态代理源码分析(通过该示例学会阅读源码的方法)2.jdk动态代理生成的代理类的源码3.总结三、手写实现jdk动态代理 一、代理模式 熟悉代理模式的可以直接点击目录第二章,jdk动态代理实现原理,本文的精髓所在,通过这个例子,教大家如何去学习源码。 1. 定义 代理模式(Proxy Pattern) 是一个使用频率非常高的设计模式,其定义如下: Provide a surrogate or placeholder for an 立即下载

相关推荐

基于CNN对抗嵌入的图像隐写——CNN-Based Adversarial Embedding for Image Steganography

CNN-Based Adversarial Embedding for Image Steganography https://ieeexplore.ieee.org/abstract/document/8603808 这篇论文发表在TIFS( IEEE TRANSACTIONS ON INFORMATION FORENSICS AND SECURITY),TIFS是网络与信息安全领域的国际两大顶级期刊之一,中国计算机学会(CCF)推荐的A类期刊,SCI一区TOP期刊,目前影响因子有7多了。 1 概

weixin_48654804的博客 2279

手写JDK动态代理

JDK动态代理,手写JDK动态代理,JDK动态代理源码分析

qiumin的博客 406

实战解析:从Innovus到Calibre的LVS错误排查全流程

本文详细解析了从Innovus到Calibre的LVS错误排查全流程,涵盖物理验证关键步骤与工具链协同。通过实战案例分享,重点解决器件不匹配、连接性错误等常见问题,并提供GDS导出规范、网表修正策略等实用技巧,帮助工程师高效完成芯片设计物理验证。

9o8p7i6u5y的博客 1036

JDK动态代理实现原理以及手写实现JDK动态代理

JDK动态代理是采用字节重组,重新生成对象来替代原始对象,以达到动态代理的目的。在理清楚JDK动态代理的过程后,手写实现JDK动态代理过程。

积跬步,至千里。 866

如何使用安路TD与Modelsim进行联合仿真?

1)安装安路FPGA开发软件;(本次实验使用版本:TD_5.6.3_Release)2)安装Modelsim仿真软件;(本次实验使用版本:Modelsim SE-64 10.1c)3)FPGA开发板;(本次实验使用型号:EG4X20BG256)4)LED点灯例程;

qq_17313923的博客 3214

【超简单】一文入门在Ubuntu系统使用GitHub

Github是基于git的代码仓库,对于开发项目的科研者或者工程师,代码仓库都是不可多得的版本控制与多端编程工具,今天这篇文章带你轻松Github入门,简单的项目本文的操作足矣。

a13337649640的博客 5236

【设计模式】——纯手写实现JDK动态代理

前言 在【设计模式】——代理模式(静态)以及【设计模式】——代理模式(动态)中,我们已经基本了解了什么是代理模式,以及什么是静态代理,什么是动态代理。 JDK动态代理以及Cglib动态代理其实底层实现原理都是字节码的重组,不过各自对应的代理场景不同,本文我们重点研究jdk动态代理。 通过前文的了解,我们已经知道在JDK动态代理中是JDK动态的帮我们生成一个名为$Proxy0的代理类,那么,我.........

我爱吃土豆 6569

ISCE+Mintpy进行SBASInSAR处理(持续更新)

通过调用pairs_misregistration方法,利用safe_dict中的数据信息,对每对SLC数据进行配准误差的计算和分析,以确定数据之间的精确差异,为后续的时间序列处理提供基础。给定同一地区的两景SAR影像,经过配准之后,对应像元进行共轭相乘得到相位差,并形成干涉图,但是从干涉图中得到的相位差实际上是主值,即在(-π,π)呈周期性变化,为了还原其真实的相位差,必须在主值的基础上加或减整数倍的相位周期2π,把被卷叠的相位展开,才能顺利地反演出地面目标的高程和形变。

Cyy2511250589的博客 3735

从简入繁详解代理模式(手写JDK动态代理)

1简单概要 代理模式:指为其他对象提供一种代理来控制对这个对象的访问。 代理模式主要有两个目的: ①保护目标对象; ②增强目标对象。 它的类图如下: 2分类与详解 2.1 静态代理 举个栗子:儿子正在找对象,而父母希望儿女早点找到另一半,于是在儿子找对象的同时帮他物色: interface Person{ void findLove(); } public class Son implements Person { public void findLo...

dms2017的博客 1083

YOLOv8实战教程:从模型训练到改进的全流程指南

回顾这段YOLOv8的实战历程,从最初的模型训练到后来的各种改进尝试,我深刻体会到目标检测技术的魅力与挑战。YOLOv8作为一款优秀的框架,不仅易用性强,而且具备很强的可扩展性,让我能在其基础上不断创新。未来,我计划在以下几个方向继续探索:一是将YOLOv8与多模态技术结合,尝试实现图像与文本的联合目标检测;二是深入研究自监督学习在YOLOv8中的应用,减少对标注数据的依赖;三是探索YOLOv8在更广泛场景的部署,如机器人、自动驾驶等。

LXY_LOVE36的博客 279

手把手教你学Simulink——基于Simulink的CLLC谐振变换器双向对称控制

本文介绍了一种基于Simulink的CLLC谐振变换器双向对称控制方法。针对CLLC拓扑的多阶谐振特性,采用固定频率、50%占空比、仅调节相位差的对称控制策略,实现了宽电压范围调节和全负载ZVS软开关。详细阐述了Simulink建模步骤,包括功率级搭建、相位差生成逻辑和双向切换实现,并通过仿真验证了稳态性能和双向无缝切换能力。该方法解决了传统PFM控制的不足,具有控制简单、效率高、易于工程实现的优势,适用于车载充电和储能系统等双向功率应用场景。

MHD0815的博客 302

JDK动态代理

个人理解: 就是当你写了一个接口,里面有方法,然后写了实现类实现方法,完成方法逻辑,然后有一天,想对这个方法进行修改,但是不想改源码,所以有两种方式可以实现。第一种是静态代理,创建一个类继承实现类,然后对方法进行修改,这样太局限,因为只能针对特定的类增强方法,有100个实现类就要创建100个子类去实现。第二种方式是动态代理,可以动态地生成代理类,这是可以接受的。 这篇文章记录的JDK动态代理 2.创建代理类 需要实现InvocationHandler接口,重写invoke方法,这里可以对方法进行增强。 3

weixin_46666822的博客 1万+

芒果YOLOv11改进175:DCNv4卷积,全网首发纯Pytorch实现代码,无需cuda编译|即插即用,一键运行:高效可变形卷积网络:重新思考视觉应用的动态和稀疏算子

芒果YOLOv11改进:DCNv4卷积,全网首发纯Pytorch实现代码,无需cuda编译|即插即用,一键运行:高效可变形卷积网络:重新思考视觉应用的动态和稀疏算子

包括YOLOv5、YOLOv7、YOLOv8等模型改进 1296

聊聊JDK动态代理和CGlib动态代理,AOP代理机制是怎么回事?代理模式详解

摘要: 代理模式通过引入代理对象间接访问目标对象,控制访问并扩展功能。分为静态代理(手动增强方法,灵活性差)和动态代理(运行时生成代理类)。静态代理需为每个目标类单独创建代理类,动态代理则更灵活,包括JDK动态代理(基于接口)和CGLIB动态代理(直接代理类)。示例展示了静态代理的实现步骤,动态代理通过运行时动态生成字节码实现高效扩展。

先做到 再看见 2072

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

重学设计模式之代理模式

设计模式实战之代理模式一、代理模式1、定义2、举例3、作用二、代理模式分类1、静态代理2、动态代理1)jdk 动态代理1)cglib 动态代理三、代理总结1、静态代理2、动态代理3、实现原理 一、代理模式 1、定义 代理的含义:给某个具体对象提供一个代理对象,并由代理对象控制对原对象的引用。 类似我们生活中常见的中介。 2、举例 举个栗子:我想买辆二手车我需要做对事情: 1、寻找二手车卖家。 2、...

D_19901719576的博客 645

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

CodeGuide 重学设计模式实战:用代理模式手写 MyBatis-Spring 核心,搞懂 DAO 接口为何无需实现类

> 本篇文章是 CodeGuide 仓库《重学 Java 设计模式》系列中代理模式实战章节的深度展开。文章以「模拟 mybatis-spring 中定义 DAO 接口,使用代理类方式操作数据库」这一场景为主线,完整复现自定义注解、代理类工厂、Bean 定义注册的完整实现,并结合仓库内 MyBatis 源码分析、JDK 动态代理原理、手写 MyBatis 专栏等资料,讲清楚「接口没有实现类为什么能执

gitblog_00739的博客 269

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

重学设计模式(三、设计模式-代理模式)

当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问。使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。

小仙儿 875

代理模式深度解析:3步看懂MapperFactoryBean动态生成DAO的原理

> 🎯 本文带你深入 [itstack-demo-design](https://link.gitcode.com/i/534844481655c272bd3d206612f8e7e9) 项目中的**代理模式实战案例**,通过 3 个核心文件看懂 **MapperFactoryBean** 如何利用 JDK 动态代理**自动生成 DAO 实现类**,彻底告别手写"贫血实现类"的枯燥重复。 [!

gitblog_01174的博客 322

动态代理设计模式

参考资料: 1.重学设计模式书籍 2.https://www.cnblogs.com/tera/p/13911819.html 3.参考 :http://www.mayikt.com/front/couinfo/194/0 设计模式代理设计模式Proxy 1.代理模式 代理模式控制对象的行为, 对对象行为增加(装饰者模式也可以对象的行为进行增加).属于结构行模式 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qUTG66dk-1635928910217)(…\jdk-pr.

KevinLoveJava 211

重学设计模式之代理模式一 静态代理

当Bean 有实现接口时 ,Spring 就会用JDK 的动态代理。2.在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。​ 1.代理模式能将代理对象与真实被调用的目标对象分离。​ 代理对象在客户端和目标对象之间起到中介的作用。为其他对象提供一种代理,以控制对这个对象的访问。1.代理模式会造成系统设计中类的数目增加。6.Spring 代理选择-扩展。​ 3.保护目标对象。​ 4.增强目标对象。​ 1、保护目标对象。​ 2、增强目标对象。...

热爱码农的平民博客 250

重学设计模式之跟Mybatis学动态代理应用

重学设计模式之跟Mybatis学动态代理应用一、本文主旨二、抛出问题1、Mybatis 开发为何通过接口就可以执行sql?1、MapperProxy2、MapperProxyFactory2、SqlSessionTemplate 是如何实现线程安全的?三、总结 一、本文主旨 在上一篇,重新学习了代理模式的基本使用。本篇,我通过Mybatis源码中的动态代理使用,加强对代理模式应用的理解和掌握。代理...

D_19901719576的博客 508

重学设计模式之 动态代理二

动态代理代码实现以及mybatis 当中如何生成实现类

热爱码农的平民博客 198

重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

一、前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不到前进的方向。这个时候你特别希望能有人告诉你,你还欠缺些什么朝着哪个方向努力。而导致这一问题的主要原因是由于日常的业务开发太过于复制过去,日复一日的重复。没有太多的挑战,也没参与过较大体量的业务场景,除了这些开发场景因素外,还有缺少组内的技术氛围和技术分享,没有人做传播和布道者,也缺少自己对各项技术学习的热情,从而导致一直游荡在瓶颈之下,难以提升。 小公司与大公司,选择哪个? 刨除掉薪资以外你会选择什么,是不有人建

gg7894125的博客 353

设计模式在jdk中的应用

前言 最近重学设计模式,而且还有很多源码要看。所以就想一举两得。从源码中寻找设计模式。顺便还可以看看源码。。。本文只是寻找设计模式在java中的应用。优缺点就不细说了。而且也不可能将jdk中所有涉及设计模式的例子都举出来。希望大家积极评论。来补全这一块 工厂模式 jdk中的应用 java.sql包线程池 解释和代码 线程池中有线程创建工厂...

weixin_33782386的博客 285

重学 Spring(上)

在没有spring 之前,我们生成一个对象是这样子的问题:如果我们的userServiceImpl修改为UserserviceImplNew怎么办,这个地方就需要修改了,耦合度太高的问题,我们引入一个BeanFactory进行修改,让BeanFactory帮我我们生成userservice,这样不就可以解耦了吗,至少在controller中解耦了(即我们的测试类中)

HHH的博客 2210

《重学 Java 设计模式》实战代码库全解析:22 个真实业务场景 + 源码级设计模式学习路线

> 本文以开源仓库 [README.md](https://link.gitcode.com/i/daaf61a3a331d76d7ce65874e926d5ab) 为线索,系统梳理《重学 Java 设计模式》实战项目 itstack-demo-design 的整体架构、22 个真实业务场景的模块划分,以及从「场景痛点 → 模式选型 → 源码实现 → 测试验证」的完整学习路径。读完本文,你将掌握该

gitblog_00408的博客 194
上一篇: 关于链表的常见算法题(二)
下一篇: MQTT的极速搭建与验证
ApkCore
博客等级 码龄12年 8粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值