动态代理的理解及入门


前言

设计模式,是软件工程的基石脉络,如同大厦的结构一样,保证了代码的重用性、可读性、可维护性。从1995年总结出来23种设计模式,一直沿用到现在。而今天要学习的动态代理,就是23种设计模式的结构型模式中的其中一种。
既然是设计模式,就要遵循一个原则:开闭原则:对扩展开放,对修改关闭

动态代理涉及到一点点反射的知识,这里也给大家准备好啦

反射的作用


一、代理模式是什么?

代理模式是指:一个对象本身不做实际的操作,而是通过其他对象来得到自己想要的结果。这样做就可以实现在目标对象实现的基础上,增强额外的功能操作,扩展目标对象的功能数量等等。

在工作的时候,改源码是程序员的大忌,不到万不得已都是不会去动源码的。若此时,客户强烈要求加功能的话,就要用到 ‘’代理模式‘’了

代理模式通常分为两类,分别是静态代理以及动态代理。

二、静态代理

静态代理就是,代理的关系在编译期间就确定了,说直白一点就是,指定某个代理对象来为自己做事。

举个例子:
这天你要结婚了,你对象是一个坤坤狂热粉,于是,你就打算请坤坤来婚礼现场表演节目,活跃气氛。但是坤坤作为大明星,不能直接联系,只能联系到坤坤的经纪人,通过经纪人的安排,你终于预约到了坤坤的表演。
在这里插入图片描述
这里的经纪人就相当于静态代理对象。他是坤坤的御用经纪人,并且他只经营坤坤一个人,帮助坤坤处理合作、谈业务等工作,而坤坤本身只需要专注于两年半的练习就可以了。坤坤本身不需要知道自己的金主是谁,也不需要知道自己在什么地方表演。这一切都是经纪人帮忙打点好的。

放到代码中演示:

首先,创建一个明星接口,这个接口有一个skill方法,说明只要是明星就必须有点技能。

public interface Star {
    void skill();
}

然后,创建坤坤对象,实现明星接口

public class GeGe implements Star {
    private String name;

    public GeGe() {
    }

    public GeGe(String name) {
        this.name = name;
    }

    @Override
    public void skill() {
        System.out.println(name+"在唱歌");
        System.out.println(name+"在跳舞");
        System.out.println(name+"在说唱");
    }
}

接下来,创建经纪人类,来帮助坤坤完成接单和变演完给粉丝送篮球

代理类也有一个保存用户的方法,但是这个方法属于代理类,这个方法不会真的保存用户,而是起到一个过渡作用,其内部有一个真实对象,进行用户保存。

public class StarProxy implements Star {
    private Star star;

    public StarProxy(Star star) {
        this.star = star;
    }

    @Override
    public void skill() {
        System.out.println("接受预约");
        star.skill();
        System.out.println("表演完给粉丝送篮球");
    }
}

最后,结婚当天

public class Marry {
    public static void main(String[] args) {
        GeGe gege = new GeGe("坤坤");

        StarProxy starProxy = new StarProxy(gege);
        starProxy.skill();
    }
}

运行结果:
在这里插入图片描述
有同学可能对经纪人类有疑惑,为啥经纪人也要实现接口,不实现接口直接用组合方式也可以实现接受预约以及变演完送篮球的功能。

从功能角度来说:
首先,客户并不关心自己联系的是张三,还是李四,还是经纪人。只要最后坤坤能在结婚当天上台表演,就是达到目的了。从功能角度来说,就算不通过接口,只是类的调用也可以完成这个目的。但是这样的话,客户就只能联系经纪人来约坤坤,客户与经纪人的耦合性就太高了。假如,经纪人当天手机坏了,坤坤就一天都接不到单。但是如果代理类与真实对象有共同的实现类接口,那么客户只需要对接口操作,什么意思呢?说通俗一点,就是可以有很多方法来实现这个目的,而不是仅限于联系一个人。

从扩展性角度来说:
为了更方便扩展,使用接口最合适,减少了客户与经纪人的耦合性。

从实际角度来说:
一个接口可以有无数多个实现类,也就是说,只要坤坤愿意,随时都可以换经纪人,并且不会影响自己,假如上一个经纪人跟坤坤吵一架后就和坤坤分道扬镳了,后续有很多金主爸爸想要联系坤坤,都联系到上一个经纪人了,坤坤直接退役。

静态代理优缺点:
1、优点:以后我们需要增加什么功能的时候,直接增加一个代理类就可以了。这样就实现了不改变源码的情况下,对新功能的增加。
2、缺点:重复的代码多,一旦需要更新一个小功能,就要新建一个新的代理类,而每一个代理类都有相似的方法,重复性很高,浪费空间。

三、动态代理

静态代理有代码冗余的缺点,呐,有没有什么方法,可以实现代理的同时,只用一个类就可以完成呢?
动态代理就这样产生了~

动态代理就是,代理的关系在运行期间才确定了,说直白一点就是,自己也不知道是谁在帮我做事。

在这里插入图片描述
此时要是有客户找坤坤,不论这个人是粉丝也好、是金主爸爸也罢,坤坤本身都不需要知道这个人是谁,也不需要知道谈合作的人是谁。这样做,坤坤就只需要 练习 -> 表演 -> 走人 ;剩下的就交由代理公司了。

还是上面的例子,我们对代理类进行修改:

//代理类实现处理器接口
public class StarProxy implements InvocationHandler {
    private Star star;

    public StarProxy(Star star) {
        this.star = star;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("接受预约");
        Object obj = method.invoke(star, args);
        System.out.println("表演完给粉丝送Basketball");
        return obj;
    }
}

代理类实现了处理器接口,因此创建代理对象的时候调用这个处理器,就可以完成对原有功能的填充啦~

处理器接口有一个invoke() 方法,这个方法有三个参数,分别是:

Object proxy : 创建出来的代理对象 (一般用不上)

Method method : 代表外面代理对象的方法

Object[ ] args : 代表外面代理对象方法的参数

method.invoke( ) 在反射的获取成员方法中有讲解~

测试也做了一点小改动,代码如下:

public class Marry {
    public static void main(String[] args) {
        GeGe gege = new GeGe("坤坤");

        //创建代理公司对象
        StarProxy starProxy = new StarProxy(gege);

        //真实对象的类加载器
        ClassLoader classLoader = gege.getClass().getClassLoader();
        //真实对象实现的接口
        Class<?>[] interfaces = gege.getClass().getInterfaces();
        //调用处理器
        Star star = (Star) Proxy.newProxyInstance(classLoader, interfaces, starProxy);
        star.skill();
    }
}

创建代理对象就需要用到Proxy类的静态方法:newProxyInstance()

这个方法需要有三个参数,分别是:

参数一:真实对象的类加载器

参数二:真实对象实现的接口

参数三:处理器对象

前两个参数都可以利用反射来获得,第三个参数就是我们的代理类。因为代理类实现了处理器接口。当我们创建代理对象的时候,就会调用处理器,在处理器类里面我们完成了对原有方法的升级。

测试结果如下:

在这里插入图片描述
学习使用动态代理,就必须用到Proxy的newProxyInstance() 方法,详记它的三个参数及用法,就可以啦~

有需要深入了解的伙伴可以new出来以后,点进去看看源码是怎么实现的。


总结

充电时刻

代理模式分为静态代理,和动态代理
静态代理
①由程序员创建或者由第三方开发工具自动生成。在程序运行之前,代理类的class文件就已经生成存在了。
②每次更新就需要重新写一个静态代理类。
③静态代理从一开始就知道自己要帮哪个类扩充功能。

动态代理
①动态代理是通过反射机制动态生成的。
②动态代理可以代理对象接口的所有实现类
③动态代理一开始不知道自己要帮哪个类扩充功能,只有执行的时候调用了才知道
④使用动态代理需要使用Proxy的newProxyInstance() 方法来动态创建代理类。

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
### 回答1: 如果你想入门 Kafka,可以从以下几步开始: 1. 了解 Kafka 的基本概念。Kafka 是一个分布式流平台,它可以处理大量的数据流,并提供实时的数据存储、批量处理和转移。 2. 安装 Kafka。要使用 Kafka,首先需要安装它。可以从 Apache Kafka 官网下载最新版本,并按照说明进行安装。 3. 创建一个 Kafka 集群。Kafka 是分布式的,通常需要至少三台机器才能搭建一个集群。可以使用预先配置好的虚拟机映像或者 Docker 镜像来快速搭建 Kafka 集群。 4. 使用 Kafka 的命令行工具。Kafka 提供了许多命令行工具,可以用来创建、删除 topic,发送和接收消息等。这些工具可以帮助你快速的熟悉 Kafka 的基本用法。 5. 开发应用程序。在你对 Kafka 有了一定的了解之后,就可以开始开发应用程序了。Kafka 提供了多种语言的客户端库,可以轻松的集成到你的应用中。 希望这些提示能帮助你入门 Kafka。 ### 回答2: 要入门Kafka,首先需要了解一些基础知识和步骤。 首先,了解Kafka的基本概念和术语,比如topic(主题)、producer(生产者)、consumer(消费者)、partition(分区)等。这些是Kafka的核心组件和概念,对于入门非常重要。 其次,学习Kafka的安装和配置。Kafka可以在本地或云端部署,在入门阶段,建议在本地环境上进行安装和配置。官方网站上提供了详细的安装和配置文档,按照步骤进行操作即可。 第三,尝试使用Kafka的命令行工具。Kafka提供了一系列命令行工具,可以用来创建topic、启动producer和consumer等操作。通过使用这些工具,可以快速了解Kafka的基本功能和用法。 第四,编写简单的Kafka应用程序。使用Kafka提供的Java或其他编程语言的客户端,编写一个简单的生产者和消费者程序。这样可以更加深入地了解Kafka的API和功能,加强对Kafka的理解。 最后,深入学习Kafka的高级特性。一旦熟悉了基本的使用方法和编程接口,可以进一步学习和实践Kafka的高级特性,比如消息的压缩、事务处理、数据分区和复制等。 总之,通过学习Kafka的基本概念和术语,安装和配置Kafka环境,使用命令行工具,编写简单的应用程序,并深入研究Kafka的高级特性,可以帮助入门Kafka并逐渐掌握其使用和部署。 ### 回答3: 要入门Kafka,首先需要了解Kafka的基本概念和工作原理。Kafka是一个分布式流处理平台,它架构简单、高性能、可扩展,用于解决大规模数据流处理和消息队列的问题。 入门Kafka的步骤如下: 1. 学习Kafka的基本概念:了解Kafka的重要概念,如Producer(生产者)、Consumer(消费者)、Topic(主题)、Partition(分区)、Offset(偏移量)等。 2. 安装和配置Kafka:从官方网站下载Kafka,并按照官方文档进行安装和配置。配置文件包括Zookeeper的地址、Kafka的监听端口等。 3. 运行Kafka集群:启动Zookeeper服务,然后启动Kafka集群。可以使用默认的配置文件,也可以根据需求进行修改。 4. 创建消息Topic:使用Kafka提供的命令行工具或编程语言的Kafka客户端创建消息Topic,指定主题名称、分区数和副本因子等。 5. 发送和接收消息:使用Kafka的命令行工具或编程语言的Kafka客户端编写生产者和消费者程序,发送和接收消息。可以通过Kafka的REST代理接口进行操作。 6. 监控和管理Kafka集群:使用Kafka提供的管理工具,如Kafka Manager、Kafka Monitor等,监控和管理Kafka集群的健康状况、性能指标和故障恢复等。 7. 深入学习和实践:学习Kafka的高级特性和用法,如流处理、事务支持、数据压缩等。可以通过阅读官方文档、参加培训课程或实际项目实践来提升自己的技能。 总结起来,要入门Kafka,就是通过学习其基本概念和工作原理,安装和配置Kafka,创建消息Topic,发送和接收消息,监控和管理Kafka集群,并进行深入学习和实践。随着实践的深入,你会逐渐掌握Kafka的高级特性和用法,从而成为一名熟练的Kafka开发者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值