什么是静态代理和动态代理,两者的区别(笔记)「建议收藏」

什么是静态代理和动态代理,两者的区别(笔记)「建议收藏」文章目录1.什么是代理?2.静态代理3.动态代理4.总结:1.什么是代理?​ 代理:就是让代理角色帮助真实角色完成一件事情;​ 举例:过年回家让朋友代买火车票,朋友帮你买火车票的过程就是代理2.静态代理​ 什么是静态代理:静态代理相当于是多写了一个代理类,在调用的时候调用的是代理类,在代理类中的处理还是原生的处理逻辑,不过在前后添加上需要添加的代码。缺点:需要为每一个被代理的对象都创建一个代理类。​ 特点:​ 代理角色和真实角色都需要实现同一个接口,​ 真实角色专注于自己的.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1.什么是代理?

​ 代理: 就是让代理角色帮助真实角色完成一件事情;

​ 举例:过年回家让朋友代买火车票,朋友帮你买火车票的过程就是代理

2.静态代理

​ 什么是静态代理:

静态代理相当于是多写了一个代理类,在调用的时候调用的是代理类,在代理类中的处理还是原生的处理逻辑,不过在前后添加上需要添加的代码。
缺点:需要为每一个被代理的对象都创建一个代理类。

​ 特点:

​ 代理角色和真实角色都需要实现同一个接口,

​ 真实角色专注于自己的事情,

​ 代理角色目的就是帮助真实角色完成一件事情

​ 多线程的实现方式2:实现一个接口Runnable 使用的就是”静态代理”的思想

现在我们用代码模拟一下结婚和婚庆公司演示静态代理

代码:

// 定义一个接口结婚的接口
interface  Mary{ 
   
    void mary() ;
}

//每个人都要结婚
class You implements Mary{ 
   //真实角色

    @Override
    public void mary() { 
   
        System.out.println("要结婚了,很开心...");
    }
}


//婚庆公司---代理角色
class WeddingCompany implements Mary{ 
   
    //声明一个接口Mary类型变量
    private Mary mary ;
    public WeddingCompany(Mary mary){ 
    //形式参数是一个接口,需要接口实现类对象
        this.mary = mary ;
    }

    @Override
    public void mary() { 
   
        //代理角色需要帮助真实角色完成一件 "结婚这件事情"
        System.out.println("结婚之前,需要布置婚礼现场....");
        mary.mary() ;
        System.out.println("结婚之后,给婚庆公司付尾款....");
    }
}

public class StaticProxyDemo { 
   
    public static void main(String[] args) { 
   

        //没有使用静态代理之前
        //接口多态或者是具体类new 具体类
        Mary mary = new You() ;
        mary.mary() ;
        System.out.println("-----------------------------------------");
        //使用静态代理
        You you = new You() ;
        //创建代理角色
        WeddingCompany weddingCompany = new WeddingCompany(you) ;
        weddingCompany.mary();
    }
}

输出结果:

要结婚了,很开心…

—————————————–

结婚之前,需要布置婚礼现场…
要结婚了,很开心…
结婚之后,给婚庆公司付尾款…

3.动态代理

什么是动态代理?

Java标准库提供了动态代理功能,允许在运行期动态创建一个接口的实例; 动态代理是通过 Proxy 创建代理对象,然后将接口方法“代理”给 InvocationHandler 完成的。

代码:

针对用户访问的数据接口

public interface UserDao { 
   
    /** * 添加功能 */
    void add() ;

    /** * 修改功能 */
    void update() ;

    /** * 查询功能 */
    void select() ;

    /** * 删除功能 */
    void delete() ;
}

针对用户数据访问接口的实现

public class UserDaoImpl implements UserDao { 
   
    @Override
    public void add() { 
   
        System.out.println("添加功能");
    }

    @Override
    public void update() { 
   
        System.out.println("修改功能") ;
    }

    @Override
    public void select() { 
   
        System.out.println("查询功能");
    }

    @Override
    public void delete() { 
   
        System.out.println("删除功能");
    }
}

版本2:对业务方法 add,update,select.delete进行增强

public class UserDaoImpl2 implements UserDao { 
   
    @Override
    public void add() { 
   
        System.out.println("权限校验") ;

        System.out.println("执行添加功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void update() { 
   
        System.out.println("权限校验") ;

        System.out.println("执行修改功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void select() { 
   

        System.out.println("权限校验") ;

        System.out.println("执行查询功能");

        System.out.println("产生日志文件");
    }

    @Override
    public void delete() { 
   

        System.out.println("权限校验") ;

        System.out.println("执行删除功能");

        System.out.println("产生日志文件") ;
    }
}
/*Proxy类下边的方法newProxyInstance * public static Object newProxyInstance(ClassLoader loader, 参数1:实现的接口的类加载器 * Class<?>[] interfaces, 参数2:基于接口的字节码文件对象数组 * InvocationHandler h) 参数3:是接口InvocationHandler :代理的处理程序 * throws IllegalArgumentException * 参数3是一个接口:自定一个类实现这个接口 * 重写这个接口中的invoke方法 * Object invoke(Object proxy,Method method,Object[] args)throws Throwable */

基于代理的处理程序

public class MyInvocation  implements InvocationHandler { 
   

    //要针对谁产生代理: ud UserDao ud = new UserDaoImpl() ;
    private Object target ;  //因为代理角色可以是任意Java类型,所以用Object
    public MyInvocation(Object target){ 
   
        this.target = target ;
    }


    //方法的返回值就是代理对象
    @Override                           //就是我们的接口的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
   
        System.out.println("权限校验") ;

        //调用接口的列表自己的方法:update(),delete(),add(),select()
        //当前实例--->真实角色
        Object obj = method.invoke(target, args); //代理角色产生

        System.out.println("产生日志文件");
        return obj;
    }
}

测试类:

public class JdkProxyDemo { 
   
    public static void main(String[] args) { 
   

        //接口多态:测试UserDao
        UserDao ud = new UserDaoImpl() ; //真实角色
        //版本1:现在需要对功能增强,这个代码不合适!
        ud.add();
        ud.update();
        ud.select();
        ud.delete();
        System.out.println("----------------------------------");

        UserDao ud2 = new UserDaoImpl2() ;
        ud2.add();
        ud2.update();
        ud2.select();
        ud2.delete();

        System.out.println("----------------Jdk动态代理------------------");

        //前提示需要一个接口:UserDao

        MyInvocation handler = new MyInvocation(ud) ;
        // public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
        UserDao proxyInstance = (UserDao) Proxy.newProxyInstance(
                ud.getClass().getClassLoader(),
                ud.getClass().getInterfaces(),
                handler);
        proxyInstance.add();
        proxyInstance.update();
        proxyInstance.select();
        proxyInstance.delete();
    }
}

输出结果:

​ 添加功能
​ 修改功能
​ 查询功能
​ 删除功能
​ ———————————-

​ 权限校验
​ 执行添加功能
​ 产生日志文件
​ 权限校验
​ 执行修改功能
​ 产生日志文件
​ 权限校验
​ 执行查询功能
​ 产生日志文件
​ 权限校验
​ 执行删除功能
​ 产生日志文件
​ —————-Jdk动态代理——————
​ 权限校验
​ 添加功能
​ 产生日志文件
​ 权限校验
​ 修改功能
​ 产生日志文件
​ 权限校验
​ 查询功能
​ 产生日志文件
​ 权限校验
​ 删除功能
​ 产生日志文件

4.总结:

​ 静态代理总结:
1)代理类的信息在jvm运⾏之前就已经⽣成,逻辑由开发者实现;
2)代理类与⽬标类的定义应该严格参照规范,定义公共接⼝并实现它,需要代理的⽅法在接⼝中都要定义好;

静态代理原理:在代理类中包含⼀个⽬标类的对象引⽤,然后在使⽤时创建⼀个⽬标类对象并且创建⼀个代理类对象,并把⽬标类对象传给代
理类对象,然后将它赋予代理类中的⽬标类对象引⽤,然后代理类所代理的⽅法中通过其所包含的⽬标类对象引⽤调⽤⽬标类的⽅法,从⽽实现通过代理调⽤⽬标类⽅法的效果。

​ 动态代理总结:
1) 动态代理是指 在java程序运⾏过程(程序已经启动在运⾏了)由jvm⽣成代理类的class信息,该class信息⽣成后是直接处于内存中的,并没有写⼊磁盘保存起来;然后通过反射⽅式实例化代理类对象,因为代理类的class信息已经存在于内存中,所以可以通过反射⽅式实例化。
这个应该怎么理解呢?
​ 可以跟上⾯讲过的静态代理对⽐下,静态代理是需要开发⼈员⾃⼰实现代理类的逻辑的,且代理类的class信息是在程序运⾏之前就已经可以获取到的.java⽂件经过编译后可以得到.class⽂件;
​ ⽽动态代理是不需要开发⼈员⾃⼰实现代理类的,也就是说使⽤动态代理⽅式的话,项⽬代码中是不存在代理类的.java⽂件的,既然代理类未由开发者实现,那么程序经过编译之后肯定也不会有代理类的.class⽂件,
​ 也就是说经过编译之后程序未启动运⾏之前,关于代理类的信息我们⼀⽆所知,它是在程序运⾏过程中需要⽤到的时候才会由jvm动态⽣成的,⽽且⽣成之后也只存在于内存中,不会写到磁盘保存成.class⽂件,更加不会保存为.java⽂件;
​ 在程序重启或者说发⽣了gc,这个代理类的class信息从内存中被卸载之后,关于这个代理类的信息就没有了,只有当代码再次访问到代理对象时,才⼜会重新⽣成代理类的class信息。
2)动态代理与静态代理的区别是什么?
​ 上⾯已经讲述,不再赘述。
3)为什么需要引⼊动态代理?
​ 这就不得不说到静态代理的弊端,我们引⼊新事物,必定是因为旧事物存在不合理之处,所以才引⼊新的事物来弥补它的缺陷。
​ 那静态代理有什么缺陷呢?
​ 我们知道静态代理是需要开发者⾃⼰实现代理类逻辑的,也就是说要对某个类进⾏代理的话,需要实现这个类相应的代理类;
​ 如果⽬标类的数量很多的话,代理类的实现也必然得很多,可能会造成代码量过于庞⼤,可能会增加代码的冗余度…
​ 再者,如果⽬标类需要代理的⽅法很多的话,代理类需要对这些⽅法⼀⼀实现代理逻辑,代理类的实现也将会很庞⼤。

考虑到这些问题,催⽣了动态代理这种⽅式,它相⽐于静态代理来说,由于不需要开发者⾃⼰再实现代理类了,所以在实际⼤型项⽬中可能代码量会⼤⼤减少。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180165.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • android签名命令行,Android系统签名位置及命令

    android签名命令行,Android系统签名位置及命令app需要使用系统的权限在AndroidManifest.xml中声明了系统全下申明了系统权限android:sharedUserId=”android.uid.system”1.找到平台签名文件“platform.pk8”和“platform.x509.pem”文件位置android/build/target/product/security/2.签名工具“signapk.jar”位置…

  • GD32 RT-Thread Nano+FinSH组件

    GD32 RT-Thread Nano+FinSH组件一、FinSH组件的命令执行流程图二、执行环境1.芯片:GD32F10x2.串口: #defineFINSH_UART USART1 #defineFINSH_UART_CLK RCU_USART1 #defineFINSH_TX_PIN GPIO_PIN_2 …

  • mysql主从复制周期_Mysql主从复制[通俗易懂]

    mysql主从复制周期_Mysql主从复制[通俗易懂]Mysql主从复制背景:Mysql可以实现主从复制,在学习了Mysql主从复制后,将一些如何主从复制过程记录下来,供以后复习使用。准备:在做Mysql的主从复制前需要做一些准备工作:1、同步时间做主从的服务器的时间需要同步,不然会出问题。命令:ntpdateip(ntpdate命令需要先安装ntpdate)2、版本一致做主从的Mysql服务需要版本一致,或者从服务器的版本高于主服务器。主从复制…

  • 圆形目标中心点在tof相机坐标系下的三维坐标的计算(1)

    圆形目标中心点在tof相机坐标系下的三维坐标的计算(1)将tof相机得到的深度图像转换为灰度图像,然后对灰度图像进行双边滤波,去除噪声的同时使边缘得到较好的保持,然后对滤波后的灰度图像进行hough圆变换,得到圆心在图像中的像素坐标,然后利用tof相机的点云数据,求得圆心在tof相机坐标系下的三维坐标。程序如下:#include”opencv2/core/core.hpp”#include”opencv2/highgui/highgui.h

  • 数字图像处理的基本概念_数字图像处理有什么用

    数字图像处理的基本概念_数字图像处理有什么用数字图像基本概念与彩色图像,(可以用来应付期末考)

  • 延迟方法_延时偏方亲测真实有效

    延迟方法_延时偏方亲测真实有效1.performSelector-(void)performSelector:(SEL)aSelectorwithObject:(id)anArgumentafterDelay:(NSTime

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号