Java——JDK动态代理

这篇具有很好参考价值的文章主要介绍了Java——JDK动态代理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.动态代理


1.1什么是动态代理?

动态代理(理解) 基于反射机制

举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不会根据法律等争取自己权益的最大化,此时就可以请律师帮助自己不仅完成对案件的陈述,还能争取权益最大化。那么Java中也是一样,如果要对功能进行增强就可以使用动态代理。

我们知道Spring是通过JDK或者CGLib实现动态代理的,今天我们讨论一下JDK实现动态代理的原理。

1.2动态代理的实现方式有几种?

  1. JDK动态代理
  2. CGLB动态代理

1.3动态代理的概念和优点

相比于静态代理(在静态代理中,对于类的每一个接口,我们都要单独写一个代理类),动态代理在创建代理对象上更加的灵活。

有需求,有问题,才会有解决方法和改进创新。那么产生动态代理的问题根源或者需求是什么呢?在静态代理中,由于每个接口都需要我们单独的写一个代理类,比较麻烦,因此我们就想,我们能不能写一个类,我们只需要把委托对象(目标对象),还有全部接口(共同行为,其实委托对象中就已经包含接口了)作为参数传给这个类的方法,然后这个方法就可以给我们返回一个我们想要的代理对象呢,并且这个代理对象可以给我们代理全部的共同行为,像是租房,结婚等?

  • 动态代理类的字节码在程序运行时由JAVA反射机制动态产生。会根据需要,通过反射机制,在程序运行期动态的为目标对象(委托对象)创建代理对象,无需程序员手动编写代理对象所属类的代码。
  • 动态代理不仅简化了编程工作,而且提高了软件系统的可扩展性,因为反射机制的使用使得可以生成任意类型的代理对象。
  • 动态代理的实现方式有两种,分别是:JDK动态代理和CGLIB动态代理。
  • 动态代理的目标对象是不固定的(也就是说把任何一个目标对象或者说是委托对象作为参数传递给生成代理对象的对象的方法,都会给我们返回一个我们想要的代理对象);使用动态代理以后,会在应用程序执行的时候,动态的创建目标对象代理对象依然会增强目标对象的行为;

2.JDK动态代理的概念和特点

先说一个需要注意的点:JDK动态代理的目标对象必须要有接口实现,也就是说:委托类必须要继承接口。

在JDK中,有一个Proxy类(名词,代理人)。Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态的生成实现类(对这个类的其他方法我了解的也不是很多,我们可以看JDK的在线API文档,百度搜一下好像挺多的)。这个类提供的有一个静态方法:newProxyInstance()方法。这个方法的目的就是给我们的目标对象(委托对象)返回一个代理对象。

newProxyInstance()方法需要有三个参数:

  1. 类加载器(ClassLoader对象)
  2. 接口集合(一个Interface对象的数组,就是需要代理对象代理那些共同行为,也是委托对象继承的共同行为接口)
  3. 一个InvocationHandler接口对象(当然可以是它的一个实现类对象)。这个接口中有一个invoke()方法。invoke()方法起到的作用很大,当代理对象调用共同行为方法的时候,invoke()方法就会被自动调用执行。

下面粘贴一张图片:

jdk动态代理,java,开发语言

2.1动态代理的介绍

jdk动态代理,java,开发语言

  1.  动态代理是指代理类对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的,java源文件。
  2. 动态代理其实就是jdk运行期间,动态创建class字节码并加载到JVM。
  3. 动态代理的实现方式常用的有两种:使用JDK代理,与通过CGLlB动态代理。

2.2动态代理的实现

  1. jdk动态代理(理解):使用java反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
  2. cglib动态代理(了解): cglib是第三方的工具库,创建代理对象
  • cglib的原理是继承,cglib通过继承目标类,创建它的子类,在子类中
    重写父类中同名的方法,实现功能的修改。
  • 因为cglib是继承,重写方法,所以要求目标类不能是fina1的,方法也不能是final的。cglib的要求目标类比较宽松,只要能继承就可以了。cglib在很多的框架中使用,
    比如mybatis,spring框架中都有使用

jdk动态代理,java,开发语言

2.3CGLB动态代理

CGLB动态代理即Code Generation Library,是一个开源的第三方工具库,其原理是继承,去生成目标类的子类对象,这样对子类的功能进行增强。但是要求:目标类不能用final修饰,目标类中的方法也不能被final修饰。

2.4动态代理的效率

CGLB动态代理的效率要大于JDK动态代理的效率。

3.为什么使用JDK动态代理?

3.1代码案例:

  1. 请看如下例子,一个音乐人的本质会唱歌、会跳舞、会rap等,但是观众进入演唱会所时首先要交门票,最基本的实现方法是直接对方法进行改造,添加对应的功能。
    package com.zhao.service.impl;
    
    import com.zhao.service.Actor;
    
    public class CXK implements Actor {
    
    
        @Override
        public void sing(int money) {
    
            System.out.println("听"+money);
        }
    
        @Override
        public String dance() {
            System.out.println("吹灰舞");
    
            return "发放签名";
        }
    
        @Override
        public void rap() {
    
            System.out.println("练习时长两年");
        }
    }
    
  2. 这样操作发现出现了大量重复的代码,如果有十处、一百处需要同样的处理那么代码需要重复十次、一百次。当然我们可以把这些功能封装成一个增强方法,然后在功能方法中进行调用,但是也出现了方法的十处、一百处的调用操作,一旦增强方法名字改变,就需要完成所有调用处代码的修改。或者有一天不需要这些增强操作了,就再次需要在这十处、一百处删除方法调用。所以这种操作不适用于大型的项目开发的需求,此时我们就必须使用Java的动态代理机制。

在Java开发中如果一个类中的方法在基本功能之外需要进行功能扩充或者功能增强,如:事务控制、权限判断、日志记录等等操作,此时可以使用动态代理机制。

Java的JDK中Proxy类可以实现基于接口的动态代理,实现步骤示例如下:

  1. 因为Proxy类必须基于接口进行动态代理,所以首先创建接口,定义接口的规范,即功能方法的定义。
    package com.zhao.service;
    /**
     * 演员接口
     * 
     */
    public interface Actor {
       //唱歌
        void sing(int money);
        //跳舞
        String dance();
        //rap
        void rap();
    }
    
  2. 定义实现接口的子类,实现接口定义的方法,此方法只需要把核心功能实现即可,其他增强的操作可以在代理类中实现。
    package com.zhao.service.impl;
    
    import com.zhao.service.Actor;
    
    public class CXK implements Actor {
    
    
        @Override
        public void sing(int money) {
    
            System.out.println("听"+money);
        }
    
        @Override
        public String dance() {
            System.out.println("吹灰舞");
    
            return "发放签名";
        }
    
        @Override
        public void rap() {
    
            System.out.println("练习时长两年");
        }
    }
    
  3. 定义代理类,在代理类中对被代理对象进行方法增强。
    package com.zhao.advice;
    
    import com.zhao.service.Actor;
    import com.zhao.service.impl.CXK;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class JJGS {
        public static void main(String[] args) {
            //1.创建被代理类的对象----具体的人物cxk
            Actor cxk=new CXK();
            //2.创建代理对象--- 具体某人为上面cxk
            /**
             * ClassLoader loader:类的加载器---联系方式
             * Class<?>[] interfaces:类的接口类型---被代理人的类型
             * InvocationHandleer h:处理---我要帮你干什么
             */
            Actor jjr=(Actor) Proxy.newProxyInstance(CXK.class.getClassLoader(), CXK.class.getInterfaces(), new InvocationHandler() {
                /**
                 *
                 *  Object proxy:被代理对象的引用,系统会自动创建被代理对象的一个映射
                 * Method method:被代理对象的方法
                 * @param args
                 *Object[] args:被代理对象方法的参数
                 * 返回值是被代理对象执行后的返回值
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //被代理对象方法的执行,并获得返回值
                    Object result=null;
                    result=method.invoke(cxk,args);
    
                    System.out.println("演出后的增强:结算费用并纳税");
                    return result;
                }
            });
    
            //3.执行功能
    //        jjr.sing(5000);
            String dance = jjr.dance();
            System.out.println(dance);
    
        }
    }
    

  测试结果:

jdk动态代理,java,开发语言文章来源地址https://www.toymoban.com/news/detail-698510.html

3.2基于子类的CGLib动态代理,可以使用Enhancer类完成直接对某个类进行动态代理。具体操作步骤如下:

  1. 创建被代理的类,并且定义功能方法,只需要完成核心功能即可。
    package com.zhao.service.impl;
    
    public class Actor {
        public void sing(int money) {
    
            System.out.println("听" + money);
        }
    
        public String dance(int money) {
            System.out.println("吹灰舞"+money);
    
            return "发放签名";
        }
    
        public void rap(int money) {
    
            System.out.println("练习时长两年"+money);
        }
    }
    
  2. 定义代理类,使用Enhancer创建代理对象,对被代理对象进行方法增强。
    package com.zhao.advice;
    import com.zhao.service.impl.Actor;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class JJGss {
        public static void main(String[] args) {
            //1.被代理的对象
            Actor actor=new Actor();
            //2.使用CGLIb的Enhancer类创建代理对象
            Actor proxyActor = (Actor) Enhancer.create(Actor.class, new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    String methodName=method.getName();
                    String money=args[0];
                    Object result=null;
                    if(methodName.equals("danceAct")){
                        System.out.println("对方法执行前进性代理增强...");
                        result=method.invoke(actor,money);
                        System.out.println("对方法执行后进性代理增强...");
    
                        return result;
                    }
                    return result;
                }
            });
    
            //
            proxyActor.dance(3000);
        }
    }
    

到了这里,关于Java——JDK动态代理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java中的静态代理、jdk动态代理以及CGLIB 动态代理

    代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能 那以下文章主要谈三种代理模式, 分别是静态代理,jdk的动态代理,cglib的动

    2024年02月11日
    浏览(44)
  • [Java]静态代理、动态代理(基于JDK1.8)

    【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18002823 出自【进步*于辰的博客】 参考笔记一,P83;笔记二,P75.4。 目录 1、概述 2、静态代理的两种形式 2.1 面向接口 2.2 面向继承 3、动态代理的两种形式 3.1 JDK动态代理

    2024年03月09日
    浏览(39)
  • 代理模式 静态代理和动态代理(jdk、cglib)——Java入职第十一天

            一个类代表另一个类去完成扩展功能,在主体类的基础上,新增一个代理类,扩展主体类功能,不影响主体,完成额外功能。比如买车票,可以去代理点买,不用去火车站,主要包括静态代理和动态代理两种模式。 代理类中包含了主体类 无法根据业务扩展,每一次

    2024年02月10日
    浏览(51)
  • 【面试精讲】Java动态代理是如何实现的?JDK Proxy 和 CGLib 有什么区别?

    Java动态代理是如何实现的?JDK Proxy 和 CGLib 有什么区别? 一、Java动态代理的实现 1、使用JDK Proxy实现动态代理 2、使用CGLib实现动态代理 二、JDK Proxy 与 CGLib 的区别 三、Spring中的动态代理 四、 Lombok代理原理 总结 本文深入探讨了Java动态代理的实现机制,分别介绍了使用JDK

    2024年03月14日
    浏览(46)
  • JDK动态代理和CGLIB动态代理

    JDK动态代理和CGLIB动态代理 ① JDK动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口。JDK动态代理的核心是InvocationHandler接口和Proxy类,在获取代理对象时,使用Proxy类来动态创建目标类的代理类(即最终真正的代理类,这个类继承自Proxy并实现了我们定义的

    2024年02月07日
    浏览(45)
  • 【动态代理】JDK动态代理与cglib动态代理源码解析

    UserService ,接口类 UserServiceImpl ,实现类 使用代理,测试效果。 控制台输出: Proxy#newProxyInstance ,生成代理类的实例。 核心在于 getProxyClass0 ,生成代理类的类信息 使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例 WeakCache#get ProxyClassFactory#apply ,实现了

    2024年02月04日
    浏览(45)
  • cglib动态代理、jdk动态代理及spring动态代理使用

    NickelBeforeAdvice.java方法执行之前 NickelAfterReturningAdvice.java方法执行之后 NickelAroundadvice.java环绕方法 NickelThrowAdvice.java抛异常方法 UserService.java抛异常方法 SpringProxtFactoryTest.java测试方法 NickelStaticMethodMatherPointcut.java方法匹配的方法 NickelPointcutAdvisor.java切面方法 SpringProxtFactoryTest.j

    2024年02月15日
    浏览(51)
  • 代理模式:静态代理+JDK/CGLIB 动态代理

    代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法

    2024年02月13日
    浏览(37)
  • 【spring】jdk动态代理和cglib动态代理的区别

    一、说明 1.spring aop中的动态代理主要有两种方式,jdk动态代理和cglib动态代理 2.从实现接口、继承父类的角度讨论区别 3.从限制角度讨论区别 4.从性能上讨论区别 二、区别 1.jdk动态代理只提供接口类的代理,如果目标类不是接口,只能用cglib代理 2.jdk动态代理会在运行时为目

    2024年02月16日
    浏览(44)
  • 通俗易懂 快速理解 JDK动态代理 和 cglib动态代理

    动态代理的实现方案有两种, JDK动态代理 和 CGLIB动态代理 ,区别在于JDK自带的动态代理,必须要有接口,而CGLIB动态代理有没有接口都可以。 JDK动态代理 :JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求 代理对象和目标对象实现同样的接口 (兄

    2024年02月08日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包