Java深入分析动态代理

目录
  • 代理模式
  • 静态代理
  • 动态代理
  • JDK动态代理
  • CGLIB动态代理
  • JDK代理与CGLIB代理的区别

"代理"这个词相信大家并不陌生,简单来说就是代替厂家来售卖商品,代理替代厂家售卖商品,顾客找代理购买商品。也就是说:1)顾客和厂家之间是不可见的,顾客不知道背后的厂家是谁。2)代理可以对顾客进行“定位”,更精确的售卖给需要的客户群体。

代理模式

代理模式:为其他对象提供一种代理以控制对这个对象的访问,也就是创建一个代理对象作为客户端和目标对象之间的中介,主要目的就是保护目标对象或增强目标对象

通过使用代理模式,通常有以下两个优点:

\1) 可以隐藏被代理类的实现

\2) 可以实现客户与被代理类间的解耦,在不修改被代理类代码的情况下能够做一些额外的处理

静态代理

所谓的动态代理,就是通过声明一个明确的代理类来访问源对象,一个代理只能服务于一种产品,当有n种产品时,就需要n个代理,这样就不利于业务的发展。

举例:我们有两个接口,Mouse和Keyboard,每个接口都有一个实现类

实现类中的代码如下:

public class LogitechMouse implements Mouse{
    @Override
    public void sell() {
        System.out.println("出售罗技鼠标");
    }
}
public class HHKBKeyboard implements Keyboard{
    @Override
    public void sell() {
        System.out.println("出售HHKB键盘");
    }
}

现在我们要做的就是让代理在调用sell()前输出一句售前了解,调用后输出一句售后服务

那我们只需写两个代理类MouseProxyKeyboardProxy

public class MouseProxy implements Mouse {
    private Mouse mouse;

    public MouseProxy(Mouse mouse) {
        this.mouse = mouse;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        mouse.sell();
        System.out.println("售后服务");
    }
}
public class KeyboardProxy implements Keyboard{
    private Keyboard keyboard;
    public KeyboardProxy(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        keyboard.sell();
        System.out.println("售后服务");
    }
}

最终执行为:

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        MouseProxy mouseProxy = new MouseProxy(logitechMouse);
        mouseProxy.sell();
        Keyboard hhkbKeyboard = new HHKBKeyboard();
        KeyboardProxy keyboardProxy = new KeyboardProxy(hhkbKeyboard);
        keyboardProxy.sell();
    }
}

输出:
售前了解
出售罗技鼠标
售后服务
售前了解
出售HHKB键盘
售后服务

静态代理的代码非常简单易懂,这种模式虽好,但是也有明显的缺点:

  • 会存在大量冗余的代理类,这里只有两个接口,如果有n个接口,那么就要定义n个代理类。
  • 不易维护,一旦接口更改,代理类和被代理类都要更改。

那么这个时候就可以使用动态代理来解决了

动态代理

代理类在程序运行时创建代理的方式叫动态代理,也就是说代理类并不是在java代码中定义的,而是在运行的时候动态生成的

JDK动态代理

JDK从1.3版本就开始支持动态代理类的创建。主要核心类只有2个:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler

还是上面的例子,用JDK动态代理如下:

public class JDKProxy implements InvocationHandler {
    private Object object;
    public JDKProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, args);
        System.out.println("售后服务");
        return invoke;
    }
}

当我们调用代理类对象的方法时,这个“调用”会转送到invoke方法中,

代理类对象作为proxy参数传入,

参数method标识了我们具体调用的是代理类的哪个方法,

args为这个方法的参数。

这样一来,我们对代理类中的所有方法的调用都会变为对invoke的调用,这样我们可以在invoke方法中添加统一的处理逻辑(也可以根据method参数对不同的代理类方法做不同的处理)。因此我们可以在中介类的invoke方法中实现输出售前了解,再调用被代理类的方法,再输出售后服务。

执行代码

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        JDKProxy jdkProxy = new JDKProxy(logitechMouse);
        Mouse mouse= (Mouse)Proxy.newProxyInstance(jdkProxy.getClass().getClassLoader(), new Class[]{Mouse.class}, jdkProxy);
        mouse.sell();
        HHKBKeyboard hhkbKeyboard = new HHKBKeyboard();
        JDKProxy jdkProxy1 = new JDKProxy(hhkbKeyboard);
        Keyboard keyboard = (Keyboard)Proxy.newProxyInstance(jdkProxy1.getClass().getClassLoader(), new Class[]{Keyboard.class}, jdkProxy1);
        keyboard.sell();
    }
}

可以看到无论多少个接口,只需要一个代理类就可以了。

CGLIB动态代理

代理类:

public class CGLIBProcy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    private Object object;
    public CGLIBProcy(Object object) {
        this.object = object;
    }
    public Object getProxy(){
        //设置需要创建子类的类
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
    // o: cglib 动态生成的代理类的实例
    // method:实体类所调用的都被代理的方法的引用
    // objects 参数列表
    // methodProxy:生成的代理类对方法的代理引用
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, objects);
        System.out.println("售后处理");
        return invoke;
    }
}

执行代码:

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        CGLIBProcy cglibProcy = new CGLIBProcy(logitechMouse);
        Mouse proxy = (Mouse)cglibProcy.getProxy();
        proxy.sell();
        cglibProcy = new CGLIBProcy(new HHKBKeyboard());
        Keyboard keyboard = (Keyboard)cglibProcy.getProxy();
        keyboard.sell();
    }
}

JDK代理与CGLIB代理的区别

  • JDK动态代理实现接口,CGLIB动态继承思想
  • JDK动态代理(目标对象存在接口时)执行效率高于CIGLIB
  • 如果对象有接口实现,选择JDK代理,如果没有接口实现选择CGILB代理

到此这篇关于Java深入分析动态代理的文章就介绍到这了,更多相关Java动态代理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java的动态代理和静态代理详解

    目录 0.代理模式 1.静态代理 2.加深理解 3.动态代理 动态代理的例子 总结 0.代理模式 为什么要学习代理模式?这是SpringAOP的底层[SpringAOP和SpringMVC] 代理模式的分类: 静态代理 动态代理 1.静态代理 静态代理中,我们对目标对象的每个方法的增强都是手动完成的(后面会具体演示代码_),非常不灵活(比如接口一旦新增加方法,目标对象和代理对象都要进行修改)且麻烦(_需要对每个目标类都单独写一个代理类). 实际应用场景非常非常少,日常开发几乎看不到使用静态代理的

  • Java实例讲解动态代理

    JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理. 区别:JDK代理只能对实现接口的类生成代理:CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类. 强制使用CGlib <!-- proxy-target-clas

  • 深入理解Java动态代理与静态代理

    目录 前言 一.静态代理 静态代理的使用 与装饰者模式的区别 二.动态代理 JDK 动态代理 CGlib 动态代理实现 前言 学习 Spring 的过程中,不可避免要掌握代理模式.这篇文章总结一下代理模式.顾名思义,代理,就是你委托别人帮你办事,所以代理模式也有人称作委托模式的.比如领导要做什么事,可以委托他的秘书去帮忙做,这时就可以把秘书看做领导的代理.下面将以这个例子来讲解.代理模式又分为静态代理和动态代理. 一.静态代理 静态代理的使用 静态代理,代理类和被代理的类实现了同样的接口,代理类

  • Java 静态代理与动态代理解析

    目录 一.代码实践 静态代理 动态代理 二.常见的动态代理场景 Retrofit中的动态代理 使用动态代理实现onClick注入 三.源码探索Jdk中的动态代理 生成代理类 四.总结 静态代理: 由我们开发者自己手动创建或者在程序运行前就已经存在的代理类,静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类. 动态代理: 在程序运行时,运用java反射机制动态创建而成,静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道,通常动态代理实现方式是通过实现 j

  • 带你重新认识Java动态代理

    目录 什么是动态代理? 动态代理的常用两种方式: 1.基于接口的动态代理 2.基于类的动态代理 基于子类的动态代理 总结: 什么是动态代理? 动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术.在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法.可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作(也可以对原方法的参数进行操作). 代理类在程序运行期间,创建的代理对象称之为动态代理对象.这种情况下,创建的

  • 一文了解Java动态代理的原理及实现

    代理是指:某些场景下对象会找一个代理对象,来辅助自己完成一些工作,如明星的经纪人.买房的人找房产中介等. 代理主要是对对象的行为额外做一些辅助操作. 如何创建代理对象: Java中代理的代表类是:Java.lang.reflect.Proxy Proxy提供了一个静态方法,用于为对象产生一个代理对象返回 主类: public class Test { public static void main(String[] args) { //1.创建一个类,对象类必须实现接口 star s=new s

  • Java实现动态代理的实例代码

    目录 前言 静态代理 动态代理 CGLib实现动态代理 总结 前言 动态代理在Java中有着广泛的应用,比如Spring AOP.Hibernate数据查询.测试框架的后端mock.RPC远程调用.Java注解对象获取.日志.用户鉴权.全局性异常处理.性能监控,甚至事务处理等. 代理,指的是使用代理对象代替对其它对象的访问,简单点说,你求职时找的中介就是代理,那么在Java中,代理如何体现呢? 静态代理 我们首先需要知道,何为静态代理?静态代理指的是在编译期就对目标对象的方法进行增强,例如: p

  • Java动态代理的示例详解

    目录 定义 分类 案例 需求 方案一:jdk动态代理 方案二:cglib动态代理 分析 总结 定义 动态代理指的是,代理类和目标类的关系在程序运行的时候确定的,客户通过代理类来调用目标对象的方法,是在程序运行时根据需要动态的创建目标类的代理对象. 分类 jdk动态代理 cglib动态代理 案例 需求 苹果公司通过苹果代理商来卖手机 方案一:jdk动态代理 定义抽象接口 /** * 售卖手机的接口(代理模式--抽象角色) * @author:liyajie * @createTime:2022/2

  • Java实现JDK动态代理的原理详解

    目录 概念 案例 静态代理 JDK动态代理模式 原理分析 真相大白 概念 代理:为控制A对象,而创建出新B对象,由B对象代替执行A对象所有操作,称之为代理.一个代理体系建立涉及到3个参与角色:真实对象(A),代理对象(B),客户端. 其中的代理对象(B)起到中介作用,连通真实对象(A)与客户端,如果进一步拓展,代理对象可以实现更加复杂逻辑,比如对真实对象进行访问控制. 案例 需求:员工业务层接口调用save需要admin权限,调用list不需要权限,没权限调用时抛出异常提示. 静态代理 /**

  • Java深入分析动态代理

    目录 代理模式 静态代理 动态代理 JDK动态代理 CGLIB动态代理 JDK代理与CGLIB代理的区别 "代理"这个词相信大家并不陌生,简单来说就是代替厂家来售卖商品,代理替代厂家售卖商品,顾客找代理购买商品.也就是说:1)顾客和厂家之间是不可见的,顾客不知道背后的厂家是谁.2)代理可以对顾客进行“定位”,更精确的售卖给需要的客户群体. 代理模式 代理模式:为其他对象提供一种代理以控制对这个对象的访问,也就是创建一个代理对象作为客户端和目标对象之间的中介,主要目的就是保护目标对象或增

  • Java JDK动态代理(AOP)的实现原理与使用详析

    本文主要给大家介绍了关于Java JDK动态代理(AOP)实现原理与使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式UML图: 简单结构示意图: 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对

  • Java CGLib动态代理机制(全面解析)

    一.首先说一下JDK中的动态代理: JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的 但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高. 二.使用CGLib实现: 使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高.唯一需要注意的

  • java实现动态代理方法浅析

    一些Java项目中在mybatis与spring整合中有MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 有鉴于此,本文浅析了java的动态代理. 本文使用动态代理模拟处理事务的拦截器. 接口: public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } 实现类: public class

  • 详解java JDK 动态代理类分析(java.lang.reflect.Proxy)

    详解java JDK 动态代理类分析(java.lang.reflect.Proxy) /** * JDK 动态代理类分析(java.lang.reflect.Proxy使用) * * @author 张明学 * */ public class ProxyStudy { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 动态代理类:通用指定类加载器,和接

  • Java JDK 动态代理的使用方法示例

    本文主要和大家分享介绍了关于Java JDK 动态代理使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 前言 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的代理使用CGLIB来实现. JDK的动态代理,就是在程序运行的过程中,根据被代理的接口来动态生成代理类的class文

  • 详解java中动态代理实现机制

    代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterfa

  • java 中动态代理机制的实例讲解

    java 中动态代理机制的实例讲解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)

  • JAVA使用动态代理对象进行敏感字过滤代码实例

    这篇文章主要介绍了JAVA使用动态代理对象进行敏感字过滤代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package com.hopetesting.web.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.BufferedReader; import java.io.FileNotFoundExcepti

  • 实例讲解Java中动态代理和反射机制

    反射机制 Java语言提供的一种基础功能,通过反射,我们可以操作这个类或对象,比如获取这个类中的方法.属性和构造方法等. 动态代理:分为JDK动态代理.cglib动态代理(spring中的动态代理). 静态代理 预先(编译期间)确定了代理者与被代理者之间的关系,也就是说,若代理类在程序运行前就已经存在了,这种情况就叫静态代理 动态代理 代理类在程序运行时创建的代理方式.也就是说,代理类并不是在Java代码中定义的,而是在运行期间根据我们在Java代码中的"指示"动态生成的. 动态代理比

随机推荐