初遇代理模式之静态代理和动态代理

news/2024/5/19 6:40:04 标签: java, 反射, 设计模式

静态代理和动态代理的一点点小理解

Java小白最近初次接触静态代理和动态代理感觉有点绕,就先写一下自己的理解吧。
以后有了更深的理解再修改。

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

目前只接触了静态代理和通过反射实现的动态代理
1.静态代理:代理类和被代理类直接被写死了,即只能代理实现了同一接口的目标类,比较单一。

java">//作为被代理类和代理类的公共接口
interface BreadFactory {
    void produce();
}

//被代理类
class KFCBreadFactory implements BreadFactory {
    @Override
    public void produce() {
        System.out.println("生产面包!!!");
    }
}

//代理类
class BreadProxyFactory implements BreadFactory {

    private BreadFactory factory;//用被代理类实例化,所以下面构造方法传进去的是该接口的实现类

    public BreadProxyFactory(BreadFactory factory) {
        this.factory = factory;
    }
    @Override
    public void produce() {
    	//还可以写一些附加操作
        //主要操作:被代理类要实现的目的
        factory.produce();

    }
}

public class StaticProxyTestDemo {
    public static void main(String[] args) {
        //创建被代理类的对象
        KFCBreadFactory kfc = new KFCBreadFactory();
        //创建代理类的对象,用被代理类对象作为参数传入
        BreadProxyFactory proxy = new BreadProxyFactory(kfc);

        proxy.produce();
    }
}

执行结果
在这里插入图片描述

通过上面代码可以发现,实现被代理类的需求时,并没有直接调用被代理类对象的方法,而是通过代理类间接调用的代理类。想要生产面包,其实是由代理类代为进行生产的,被代理类本身其实并不直接生产。就比如服装品牌,它其实不自己制造服装,而是委托给代工厂进行生产。又或者说生活中找中介租房子,你就是被代理对象的,中介就是代理对象,你不用直接去找房子,你只需要把需求告诉给中介,他会帮你处理。而通过代理的好处就是可以在不改变被代理类原有代码结构的基础上,可以在代理过程种加上一些其他操作,就是功能增强的意思。

2.动态代理:通过反射去造被代理类的代理类对象,传什么被代理类对象进去,就通过反射造需要的代理类对象,即动态获取代理类对象。
①首先,被代理类还是和静态代理一样。
②而代理类对象就是通过反射动态获取,即使用java.lang.reflect包下的Proxy类和InvocationHandler接口实现动态生成代理对象。
通过调用Proxy类中的**newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)**创建代理对象
**该方法中第一个参数为类的加载器:**因为代理类是要代理被代理类,所以他们的类加载器相同,所以代理的类加载器就可以通过
传入的被代理类对象的基础上通过反射的方法获取,即:被代理类对象.getClass().getClassLoader()
**第二个参数为接口数组:**由于被代理类可能实现了不止一个接口,所以用的数组作为参数,由静态代理例子可知,代理类是要完成
被代理类的所有需求的,那么代理类就一定要实现被代理类实现了的所有接口。也是通过传入的被代理类对象的基础由反射的方式获取
即:被代理类对象.getClass().getInterface()
第三个参数为InvocationHandler接口实现类的对象: InvocationHandler接口中只有一个抽象方法
在这里插入图片描述
该方法是,当我们通过代理类对象调用被代理类方法时,就会自动调用该invoke()方法,然后通过调用该方法中method调用的另外一个
invoke()方法去调用被代理类的方法。
可以看到该抽象方法有三个参数
第一个参数 :一般用不到,无需赋值
第二个参数:是调用的方法,无需赋值。
在这里插入图片描述
该方法有两个参数
第一个参数:是被代理类对象,需要我们自己传入。可以选择在InvocationHandler实现类中提供一个Object类型的参数来接收被代理类对象,赋值操作可以由该实现类的构造方法完成,也可单独写个方法,通过该实现类对象调用完成。
第二个参数:是个可变形参,是我们需要调用的方法中的参数,即为三个参数的invoke()方法中的第三个参数来确定

第三个参数 目标类中的方法的参数,jdk提供

java">//公共接口
interface Bread{
    void produce();
}

//被代理类
class KFCBread implements Bread{

    @Override
    public void produce() {
        System.out.println("生产KFC面包");
    }
}

//公共接口
interface Book {
    void price(double pri);
}

//被代理类
class MathBook implements Book {

    @Override
    public void price(double pri) {
        System.out.println("价格为:" + pri);
    }
}

//InvocationHandler实现类
class MyInvocation implements InvocationHandler {

    public Object obj;

    public MyInvocation(Object obj) {
        this.obj = obj;
    }

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

        System.out.println("其他操作");

        Object invo = method.invoke(obj, args);

        return invo;
    }
}

//代理类生成类
class ProxyFactoryx {

    public static Object proxyInstancex(Object obj) {
        MyInvocation mi = new MyInvocation(obj);
        //根据传入的被代理类对象通过反射生成相应的代理类对象并返回
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), mi);
    }
}
//测试类
public class ProxyTestx {
    public static void main(String[] args) {
        //被代理类对象
        MathBook mtb = new MathBook();
        //代理类对象
        Book o = (Book) ProxyFactoryx.proxyInstancex(mtb);
        o.price(39.9);
        System.out.println("-------------分割线----------------");
        //被代理对象
        KFCBread kb = new KFCBread();
        //代理类对象
        Bread bd = (Bread) ProxyFactoryx.proxyInstancex(kb);
        bd.produce();
    }
}

执行结果
在这里插入图片描述
over!


http://www.niftyadmin.cn/n/1311166.html

相关文章

CCF可以用java语言吗_CCF--出现次数最多的数--用java语言实现

题目要求&#xff1a;这道题有很多做法&#xff0c;我自己用桶排序原理实现了一遍。但在网上看到了一个挺不错的思路&#xff0c;就自己再实现一遍。这是原作者的博客地址&#xff1a;https://blog.csdn.net/gamer_gyt/article/details/44541117思路&#xff1a;整体思路&#…

求数对之差的最大值

题目 数组中的一个数字减去它右边子数组中的一个数字可以得到一个差值&#xff0c;求所有可能的差值中的最大值。 数组{1, 4, 17, 3, 2, 9} 暴力法 直接枚举i,j (j > i) 求max(a[i] - a[j]) 复杂度O(n^2) 动态规划 解法一 设mx为当前到i-1位置的最大值&#xff0c;dp[i] 为当…

java高并发秒杀 视频_JAVA高性能高并发实战课程 JAVA秒杀系统方案优化解决方案视频教程 JAVA高级优化课程...

JAVA高性能高并发实战课程 JAVA秒杀系统方案优化解决方案视频教程 JAVA高级优化课程1.JPG (37.25 KB, 下载次数: 1)2019-6-5 09:23 上传2.JPG (45.86 KB, 下载次数: 1)2019-6-5 09:23 上传3.JPG (35.94 KB, 下载次数: 1)2019-6-5 09:23 上传课程目录(0)&#xff1b;目录中文件数…

base64 上传图片不完整_php 图片上传

/** base64图片上传* param string $base64_img 图片数据流* return string|bool*/public function base64img($base64_img){$up_dir dirname(__DIR__)./web/uplodes/image/;if(preg_match(/^(data:s*image/(w);base64,)/, $base64_img, $result)){$type $result[2];//判断图…

docsify框架java_使用docsify 写开源文档

PassJava-Learning项目是PassJava项目的学习教程。PassJava 项目是一款帮助Java面试的开源系统。零碎时间利用小程序查看常见面试题&#xff0c;夯实Java基础。PassJava 项目可以教会你如何搭建SpringBoot项目&#xff0c;Spring Cloud项目。采用流行的技术&#xff0c;如 Spri…

2018帮助_各省2018年成人高考入学考试录取最低省控分数线

有任何问题&#xff0c;或者需要帮助都可以加我微信&#xff0c;会尽力帮大家解答&#xff1a;lian198937也欢迎大家添加我们微信公众号&#xff0c;及时了解各种教育资讯&#xff1a;江苏明路教育其他精彩文章&#xff1a;连帅华&#xff1a;关于网络教育&#xff0c;你想知道…

java中rpn_Java GroupNotificationMessage类代码示例

import io.rong.message.GroupNotificationMessage; //导入依赖的package包/类public static TranslatedMessageContent translateMessageContent(MessageContent msgContent) {TranslatedMessageContent content null;if (msgContent null)return null;if (msgContent insta…

学习git遇到的问题

创建库时的注意事项&#xff1a; 打开git-bash&#xff0c;输入命令 $ mkdir learngit 创建版本库时&#xff0c;默认选择在git安装路径上的根目录下创建learngit文件夹。若想自定义在某盘上&#xff0c;则使用cd命令进入后再输入创建版本库的命令 fatal: pathspec readme.txt …