<重要>James带你透彻分析三大代理模式

Java开源邮件服务器james源码 Java开源邮件服务器apache-james-2.3.2源代码 立即下载


关于代理的实战课,我有专讲过
AOP实现插件热插拔实战,点这也可以看到录播

1.代理模式

Java最经典的设计模式代理模式(Proxy), 在我们开发及框架源码中无处不在,其实说白了, 就是我们使用另外一种方式来访问A对象的方法, 其本质还是访问了A对象的方法, 只是对A对象方法访问的时候做了些扩展, 把A对象封装成代理对象AA, 即通过AA代理对象来访问目标对象. 这样就可以在A对象的基础上,实现其它的额外附加功能;

AA对象也叫做代理对象, 在不动A对象的前提下, 实现了对A对象的扩展, 程序开发过程中, 不能经过动别人的代码,用代理对别人的代码进行扩展.

A目标对象, AA为A的代理对象proxy, 如下图:

在这里插入图片描述

注意: 代理对象AA与目标对象A.其实就是AA对A对象的调用前后加了扩展,加了图上的第2 第4步

1.1.快速掌握静态代理

我们先要搞清什么是静态代理?

看看代码操作吧, 首先我们需要定义接口或父类,然后目标对象与代理对象需要继承相同父类或实现相同的接口.

废话不多说, 翠花, 上代码!!!

先建接口:IOrderDao.java

/**
 * 接口
 */
public interface IOrderDao {

    void createOrder();
}

目标对象:OrderDao.java

/**
 * 接口实现
 * 目标对象
 */
public class OrderDao implements IOrderDao {
    public void createOrder() {
        System.out.println("----创建订单成功!----");
    }
}

对OrderDao进行代理, 即对其进行包装(也要代理对象)

新建 OrderDaoProxy.java

/**
 * 代理对象,静态代理,与目标对象实现相同的接口或继承相同的父类
 */
public class OrderDaoProxy implements IOrderDao{
    //接收从外部传进来的目标对象
    private IOrderDao target;
    public OrderDaoProxy(IOrderDao target){
        this.target=target;
    }

    public void createOrder() {
        System.out.println("James下订单前,记录日志...");
        target.createOrder();//真正的执行从外部传进来的目标方法
        System.out.println("James下订单后,记录日志...");
    }
}

我们测试一下,新建类:JamesApp.java

/**
 * test
 */
public class JamesApp {
    public static void main(String[] args) {
        //一定要创建目标对象
        OrderDao target = new OrderDao();

        //看到没?我执行的是proxy的createOrder,加了些日志扩展,但真正还是调了目标对象的createOrder
        OrderDaoProxy proxy = new OrderDaoProxy(target);

        proxy.createOrder();//执行的是代理的方法
    }
}

执行结果如下

James下订单前,记录日志...
----创建订单成功!----
James下订单后,记录日志...

看到没, 订单创建成功, 但在前后都被记录了日志,这就是代理对象对目标对象进行增强了.

静态代理总结下:
1.优点: 不修改目标对象的任何一行代码, 完成了对目标对象的扩展.
2.缺点: 代理对象会随着目标对象的修改, 也要做相应的修改,比如目标对象加了个订单查询 orderQuery方法,OrderDaoProxy代理类也要做代码开发, 才能完成这个方法的扩展, 很明显, 不方便 .

那么如何解决这个问题呢? 很明显啦 ,动态代理嘛

1.2.JDK动态代理

那么动态代理有哪些优点呢?
1.首先代理对象肯定是不需要实现接口或继承同一父类, 不然又回到了静态代理模式
2.代理对象它内部调用JDK的接口,可以动态在我们内存中生成代理对象, 这个代理对象和上面讲代理对象的作用是一样的, 对目标对象进行增强, 进行扩展, 只是实现方式更灵活更方便

OK, 那么如何调用JDK API来生成代理对象呢?
代理类所在包:java.lang.reflect.Proxy
很简单, 调用JDK的newProxyInstance方法即可对目标对象生成对应的代理对象, 语法格式如下:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

newProxyInstance静态方法,需要专稿三个参数:

  • ClassLoader loader,:目标对象使用的类加载器, target.getClass().getClassLoader()
  • Class<?>[] interfaces,:目标对象实现接口类型,使用泛型方式类型,target.getClass().getInterfaces()
  • InvocationHandler h: 当执行目标对象的方法时,会先调用InvocationHandler的invoke方法, 同时把当前执行目标对象的方法作为参数传入

废话不多说, 翠花, 上代码, 一看就懂:

新建IOrderDao接口:

package com.enjoy.james;

public interface IOrderDao {

    void createOrder();

    void queryOrder();

    void cancelOrder();
}

目标对象OrderDao实现类:

package com.enjoy.james;

public class OrderDao implements IOrderDao {

    public void createOrder() {
        System.out.println("订单创建成功.......");
    }

    public void queryOrder() {
        System.out.println("订单查询成功.......");
    }

    public void cancelOrder() {
        System.out.println("订单取消成功.......");
    }
}

一定要有代理工厂类:ProxyFactory.java

后面使用的时候, 直接向工厂申请,通过ProxyFactory类传入目标对象, 生成代理对象

package com.enjoy.james;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 创建动态代理对象的步骤
 * 注:动态代理不需要实现接口,但是需要指定接口类型
 */
public class ProxyFactory {

    //维护一个目标对象
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    //对目标对象包装成代理对象
    public Object genProxyBean() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("James订单操作前,记录日志...");
                        //运用反射执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("James订单操作前,记录日志...");
                        return returnValue;  //返回已经扩展后的代理对象
                    }
                }
        );
    }

}

来,测试一下:

package com.enjoy.james;


public class TestJDKProxy {

    public static void main(String[] args) {
        // 目标对象
        OrderDao target = new OrderDao();

        // 给目标target对象,创建代理对象(这个对象对目标对象进行了增强)
        IUserDao proxy = (IUserDao) new ProxyFactory(target).genProxyBean();

        proxy.createOrder();

        System.out.println("===1创建订单完成===");

        proxy.queryOrder();

        System.out.println("===2查询订单完成===");

        proxy.cancelOrder();
        System.out.println("===3取消订单完成===");
    }
}

运行结果:

James订单操作前,记录日志...
订单创建成功.......
James订单操作前,记录日志...
===1创建订单完成===
James订单操作前,记录日志...
订单查询成功.......
James订单操作前,记录日志...
===2查询订单完成===
James订单操作前,记录日志...
订单取消成功.......
James订单操作前,记录日志...
===3取消订单完成===

内容总结:
  JDK的方式生成代理对象, 如果我们把代理对象生成 p r o x y 0. c l a s s 文 件 ( 怎 么 生 成 , 请 百 度 ) , 保 存 到 本 地 磁 盘 , 通 过 对 proxy0.class文件(怎么生成, 请百度),保存到本地磁盘, 通过对 proxy0.class文件(怎么生成,请百度),保存到本地磁盘,通过对proxy0.class类反编译查看, 最终是这个样子

public class $proxy0 extends Proxy implements IOrderDao

$proxy0代理对象已经继承了jdk的Proxy, 所以JDK动态代理只能以实现IOrderDao接口的方式完成

1.3.Cglib动态代理

我们不难发现, 刚以上写的静态代理和动态代理模式它们都要求: 目标对象是一定要实现一个接口,但在我们写业务代码有时候只是一个对象, 没有实现接口,那我们可以Cglib代理方式来完成代理对象

首先我们的pom.xml要引入cglib:

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
        </dependency> 

业务代码略:OrderDao和IOrderDao与上面完全一样。

首先建立Cglib代理工厂类

package com.enjoy.james;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;


public class ProxyFactoryByCglib implements MethodInterceptor {

    public ProxyFactoryByCglib() {
    }

    /**
     * 1、代理对象;
     * 2、委托类方法;
     * 3、方法参数;
     * 4、代理方法的MethodProxy对象。
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println(method.getName()+"方法开始调用");
        Object obj = methodProxy.invokeSuper(o, objects);
        System.out.println(method.getName()+"方法结束调用");
        return obj;
    }
}

开始测试:

package com.enjoy.james;

import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;


public class TestCglib {

    public static void main(String[] args) {
        //将动态代理类保存到磁盘D:/cglib下,方便我们反编译查看它的结构
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:/cglib");
		
        ProxyFactoryByCglib cglibProxy = new ProxyFactoryByCglib();
        
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(OrderDao.class);
        //设置回调对象
        enhancer.setCallback(cglibProxy);
		
        OrderyDao proxy = (OrderyDao) enhancer.create();
        
        proxy.createOrder();
        System.out.println("===1订单创建===");
        
        proxy.queryOrder();
        System.out.println("===2订单查询===");
        
        proxy.cancelOrder();
        System.out.println("===3订单取消===");
    }
}

**测试结果: **

createOrder()方法开始调用

订单创建成功…

createOrder()方法开始调用

=1订单创建=

queryOrder()方法开始调用

订单查询成功…

queryOrder()方法开始调用

=2订单查询=

cancelOrder()方法开始调用

订单取消成功…

cancelOrder()方法开始调用

=3订单取消=

使用总结:
  若目标对象有实现接口,我们可以用JDK代理; 若目标对象没有实现接口,则用Cglib代理;若目标对象实现了接口,并且强制用cglib, 最终还是会使用cglib代理.

【AI Infra】Perfetto性能分析工具指南 Perfetto是一款开源性能分析工具,提供系统级和应用级的活动数据追踪功能。其界面分为四个区域:左侧操作区(包含Trace查看、SQL查询、预置分析等功能)、上方信息区、中间图形化展示区以及下方详细信息区。工具支持快捷键操作(w/s缩放、a/d移动、m标记等),并能高效处理大体积Trace文件。通过Timeline分析可发现性能瓶颈,如案例中update_actor耗时过高的问题,最终定位到CPU offloading导致的MemcpyH2D操作耗时过长,提出了优化方案。Perfetto相比Systrac 阅读详情

相关推荐

MAX30102传感器实战:从寄存器配置到Arduino心率血氧监测

本文详细介绍了MAX30102传感器在Arduino平台上的实战应用,从寄存器配置到心率血氧监测的全过程。通过清晰的代码示例和实用技巧,帮助开发者快速实现脉搏血氧仪功能,包括I2C通信、FIFO数据处理及算法实现,适用于健康监测和可穿戴设备开发。

weixin_29182481的博客 511

java的三种代理模式

1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。下面借用卖房子例子进行说明。 在某种情况下,客户类不能直接引用目标对象,需要通过代理对象去引用。一般的代理模式都会有一个接口,代理对象和目标对象共同实现这个接口。静态代理(继承,实现接口)和.

weixin_45060598的博客 4343

告别夜间噪点!用瑞芯微RV1126B的AI-ISP,手把手教你打造0.01Lux超低光摄像头

本文详细介绍了如何利用瑞芯微RV1126B芯片的AI-ISP技术,打造0.01Lux超低光摄像头,解决夜间噪点问题。通过AI算法与图像信号处理的深度融合,RV1126B的3TOPS边缘算力实现了像素级AI降噪和语义感知增强,显著提升低光环境下的图像质量。文章包含硬件选型、软件配置和实战调优指南,助力开发者在AIoT领域实现高性能视觉应用。

weixin_33725722的博客 565

Java代理的几种实现方式

Java代理的几种实现方式

pengfei1990的博客 1749

OFDM基本原理

OFDM基础介绍,包括OFDM的核心思想,数学推导了OFDM信号的调制解调过程。

伊丽莎白的学习之路 8912

告别Godot默认编辑器:手把手教你用VSCode配置C#开发环境(附中文注释避坑指南)

本文详细介绍了如何将VSCode配置为Godot引擎的C#开发环境,提升游戏开发效率。从环境准备、扩展配置到解决中文编码问题,提供完整的避坑指南和高级调试技巧,帮助开发者充分利用VSCode的智能补全和调试功能,打造高效工作流。

weixin_30596023的博客 191

Java的两大、三类代理模式

一篇了解全代理模式,静态代理、动态代理,代码实现、优缺点

程序员Forlan的博客 1552

深度解析大语言模型中的词向量

​ 在学习完语言模型中的编码器与解码器知识后,让我们继续深入学习大语言模型中一个非常关键的技术:词向量表示,以及如何通过Transformer模型实现对next token的预测。 ​

产品老A,8年互联网大厂AIPM,专注探索新型人机交互 3284

Java中的常用的代理模式

Java代理模式简介。

weixin_40056279的博客 1497

《派出你的AI同事:WorkBuddy案例实战》055:客服工单自动分类与话术生成

客服工单自动分类与话术生成 —— 《派出你的AI同事:WorkBuddy案例实战》系列文章,配图已统一为规范示意图。

LuckyHanMo的博客 285

Chrome更新出现错误代码3: 0X80070422 -- system level的解决方案

本文主要介绍了Chrome更新出现错误代码3: 0X80070422 – system level的解决方案,希望能对使用Chrome的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

【设计模式】Java 的三种代理模式

代理(Proxy)模式是一种结构型设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需要修改,可以通过代理的方式来扩展该方法。:真实类,也就是被代理类、委托类。用来真正完成业务服务功能;Proxy:代理类,将自身的请求用 Real Subject 对应的功能来实现,代理类对象并不真正的去实现其业务功能;Subject。

DreamSun的博客 2524

Kriging克里金模型实现数据回归预测Matlab代码

Kriging克里金模型实现数据回归预测Matlab代码

天天酷科研的博客 605

全网分析最透彻的三大代理模式,Java开发人员必看

1.代理模式 Java最经典的设计模式代理模式(Proxy), 在我们开发及框架源码中无处不在,其实说白了, 就是我们使用另外一种方式来访问A对象的方法, 其本质还是访问了A对象的方法, 只是对A对象方法访问的时候做了些扩展, 把A对象封装成代理对象AA, 即通过AA代理对象来访问目标对象. 这样就可以在A对象的基础上,实现其它的额外附加功能; AA对象也叫做代理对象, 在不动A对象的前提下, 实现了对A对象的扩展, 程序开发过程中, 不能经过动别人的代码,用代理对别人的代码进行扩展. A目标对象,

QAQFyl的博客 439

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

spring aop

aop,改入参

global_coding的博客 285

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java代理的三种方式

远程代理(Remote Proxy): 当某个对象位于不同的地址空间,需要通过网络进行远程访问时,可以使用远程代理。远程代理隐藏了对象存在于不同地址空间的事实,使得客户端可以像访问本地对象一样访问远程对象。虚拟代理(Virtual Proxy): 虚拟代理是一种延迟加载的代理,用于按需创建开销较大的对象。在需要时,虚拟代理才会真正创建目标对象,而在目标对象创建之前,虚拟代理可以提供一些占位信息。保护代理(Protection Proxy): 保护代理用于控制对目标对象的访问。

qq_36896711的博客 865

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

java的代理模式

java的三种代理模式简介静态代理jdk动态代理cglib实现动态代理 简介 代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 以上为百度百科对代理模式的定义;通俗一点讲,java中的代理模式就是你想要访问一个目标对象,但是不直接访问它,而是通过它的代理对象访问(因为代理对象可以对目标对象做增强操作),这就是java的代理模式。示意图如下: 在java中,有三种代理模式,分别为静态代

qq_40820916的博客 2080

java中的代理模式

java代理模式的学习:静态代理、JDK动态代理、CGLIB动态代理

weixin_39038328的博客 2101

Java基础学习: 代理模式(Proxy Pattern)

代理模式。

玉汝于成 1048

Java23种设计模式之代理模式

java面向对象23种设计模式之代理模式

m0_64332518的博客 366

Apache James

Apache James(Java Apache Mail Enterprise Server)是Apache组织的子项目之一,完全采用纯Java技术开发,实现了SMTP、POP3与NNTP等多种邮件相关协议.James也是一个邮件应用平台,可以通过Mailet扩充其功能,如Mail2SMS、Mail2Fax等。James提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储部分,可以选择

auglyboy的专栏 2554

微服务如何向Nacos进行注册及心跳检测?James带你从源码一步步深入分析

大家好, 我是James, 最近整理了一下客户端微服务向Nacos注册及心跳的源码分析, 希望对大家学习有帮助, 源码可以找我的助理要一下哈v: lzc1314592 首先下载好Nacos的源码 关于源码怎么导入到maven, 在预习资料有个文档,写的很清楚 Nacos源码分析 访问nacos 启动业务服务 然后再停掉一个服务 发现变成1了 如果客户端访问刚关闭的那台服务, 是不是会报错呢? 有可能还会调到已停的服务, 怎么处理?其实就是做了一个服务降级的处理 互联网线上一般对非核心非关键的

Jack博客 4296

Java中代理的实现方式

在Java中,有多种方式可以实现代理,包括:invoke()invoke()Enhancer这些代理方式各有特点,可以根据具体需求选择适合的方式。静态代理相对简单,但需要为每个目标类编写一个代理类;JDK动态代理适用于基于接口的代理;CGLIB动态代理适用于没有实现接口的类的代理。

ttyy1112的专栏 770

Java常见的代理模式

代理模式是一种结构性设计模式,代理对象做为一个中间层,对真实对象的操作进行拦截或者增添额外的功能,提高系统间接性和灵活性。

QPiker的博客 670

Java代理模式 动态代理举例

目录 一、代理模式是什么?Java的静态、动态代理模式 1、静态代理 2、动态代理 2.1 基于接口的动态代理(JDK官方) 2.2 基于子类的动态代理(第三方CGLib) 二、Spring AOP 怎么应用的动态代理 参考资料: 你真的完全了解Java动态代理吗?看这篇就够了 Java的三种代理模式 理解java的三种代理模式 一、代理模式是什么?Java的静态...

熬夜吃橘子的博客 910

Java代理模式快速解析:从静态代理到动态代理

本文深入探讨了代理模式的核心概念、类型划分(静态代理与动态代理)及其典型应用场景,并通过代码示例详细演示了不同实现方式。静态代理以编译时绑定的方式增强功能,而动态代理则通过运行时生成实现高灵活性,特别适用于复杂多变的需求。文章还结合实际案例,展示了代理模式在日志记录、权限控制和分布式系统中的广泛应用,帮助读者全面掌握该模式的理论与实践。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 169万+
上一篇: Seata事务操作实战,快速搞定分布式事务
下一篇: 微服务如何向Nacos进行注册及心跳检测?James带你从源码一步步深入分析
Jack爱258
博客等级 码龄10年 1288粉丝 124原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值