java基础之Java的动态代理如何实现

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

目录

Java实现动态代理的两种方式

两种动态代理的区别

JDK 的动态代理是基于接口的代理。

CGLIB 是基于继承的代理。

总结

补充

静态代理和动态代理的区别

动态代理的用途

Spring AOP的实现方式

JDK 动态代理代码示例

Cglib动态代理代码示例


Java实现动态代理的两种方式

  1. JDK动态代理:Java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。
  2. Cglib动态代理:Cglib (Code Generation Library )是一个第三方代码生成类库,运行时在内存中动态生成一个子类对象从而实现对目标对象功能的扩展。

两种动态代理的区别

JDK 的动态代理是基于接口的代理。

它要求被代理的类必须实现一个或多个接口。在运行时,JDK 动态代理会根据被代理类实现的接口生成一个代理对象,该代理对象实现了被代理类的接口,并将方法的调用转发给真正的被代理类。JDK 动态代理的优点是简单易用,缺点是只能代理实现了接口的类。

CGLIB 是基于继承的代理。

它可以代理没有实现任何接口的类。在运行时,CGLIB 会动态生成一个被代理类的子类(Cglib包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它需要你对JVM内部结构包括class文件的格式和指令集都很熟悉。),并重写父类中的方法,从而实现代理功能。CGLIB 的优点是可以代理没有实现接口的类,缺点是生成的代理类需要继承被代理类,并且无法代理 final 类型的方法。它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。

总结

使用JDK动态代理的对象必须实现一个或多个接口;而使用cglib代理的对象则无需实现接口,达到代理类无侵入。

JDK 的动态代理和 CGLIB 都有各自的优点和缺点,具体使用哪种方式取决于具体的需求和场景。如果被代理的类已经实现了接口,那么可以优先考虑使用 JDK 的动态代理;如果被代理的类没有实现接口,或者需要对类的所有方法进行代理,那么可以考虑使用 CGLIB。

补充

静态代理和动态代理的区别

最大的区别就是静态代理是编译期确定的,但是动态代理却是运行期确定的。

同时,使用静态代理模式需要程序员手写很多代码,这个过程是比较浪费时间和精力的。一旦需要代理的类中方法比较多,或者需要同时代理多个对象的时候,这无疑会增加很大的复杂度。

反射是动态代理的实现方式之一。

动态代理的用途

Java的动态代理,在日常开发中可能并不经常使用,但是并不代表他不重要。Java的动态代理的最主要的用途就是应用在各种框架中。因为使用动态代理可以很方便的运行期生成代理类,通过代理类可以做很多事情,比如AOP,比如过滤器、拦截器等。

在我们平时使用的框架中,像servlet的filter、包括spring提供的aop以及struts2的拦截器都使用了动态代理功能。我们日常看到的mybatis分页插件,以及日志拦截、事务拦截、权限拦截这些几乎全部由动态代理的身影。

Spring AOP的实现方式

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。

CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

JDK 动态代理代码示例

public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        // TODO Auto-generated method stub
        System.out.println("--------------------add----------------------");
    }
}

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         // 在方法调用前进行性能监控
        PerformanceMonior.begin(target.getClass().getName()+"."+method.getName());
       
         // 通过反射调用目标对象的方法
        Object result = method.invoke(target, args);
       
        // 在方法调用后结束性能监控
        PerformanceMonior.end();
        

        return result;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);
    }
}

public static void main(String[] args) {
    UserService service = new UserServiceImpl();
    MyInvocationHandler handler = new MyInvocationHandler(service);
    UserService proxy = (UserService) handler.getProxy();
    proxy.add();
}

代码整体解读:

说人话就是我们通过jdk的动态代理,对用户服务的新增用户方法,追加了一个性能监控功能,通过传入原对象,得到代理对象(传入原对象,我拦截开启性能监控功能,我再把方法的调用转发(本质就是反射机制调用)给原对象,原对象方法执行结束,我结束性能监控)。文章来源地址https://www.toymoban.com/news/detail-772766.html

Cglib动态代理代码示例

public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        // TODO Auto-generated method stub
        System.out.println("--------------------add----------------------");
    }
}

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        // 设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        // 通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    // 实现MethodInterceptor接口方法
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("前置代理");
        // 通过代理类调用父类中的方法
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("后置代理");
        return result;
    }
}

public class DoCGLib {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        // 通过生成子类的方式创建代理类
        UserServiceImpl proxyImp = (UserServiceImpl)proxy.getProxy(UserServiceImpl.class);
        proxyImp.add();
    }
}

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

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

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

相关文章

  • 【Java】JDK动态代理实现原理

    代理模式 代理模式一般包含三个角色: Subject :主题对象,一般是一个接口,定义一些业务相关的基本方法。 RealSubject :具体的主题对象实现类,它会实现Subject接口中的方法。 Proxy :代理对象,里面包含一个RealSubject的引用,外部会通过这个代理对象,来实现RealSubject中方

    2024年02月08日
    浏览(42)
  • 【代理设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

    代理模式(Proxy Pattern)是一种结构型设计模式,用一个类来代理另一个类或几个类的功能。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源

    2023年04月25日
    浏览(89)
  • 【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化

    动态内存管理的函数有:malloc,calloc,ralloc,free,本文讲解动态内存函数和使用,如何进行动态内存管理,实现通讯录联系人容量的动态化,对常见动态内存错误进行总结。                           ✨  猪巴戒 :个人主页✨                 所属专栏 :《C语言进阶》

    2024年02月04日
    浏览(68)
  • Java代理模式——静态代理与动态代理

    代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被

    2024年02月13日
    浏览(47)
  • java中的静态代理、jdk动态代理以及CGLIB 动态代理

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

    2024年02月11日
    浏览(44)
  • 【Java学习笔记】 动态代理

    1、什么是动态代理? 前面已经提到了,动态代理就是【在内存】中动态生成【字节码代理类】的技术。(虽然不需要开发者书写,但是在内存层面依然存在该代理对象】 优点 : 减少了代理类的数量 并且解决了代码复用的问题。 动态代理常见的实现技术包括以下三种 JDK内

    2024年02月04日
    浏览(39)
  • Java——JDK动态代理

    动态代理(理解) 基于反射机制 举个例子,生活中一般在打官司的时候都会请代理律师,为什么要请律师呢?是因为开庭的时候大部人对于打官司没有经验,只会说出自己案件的陈述,并不会根据法律等争取自己权益的最大化,此时就可以请律师帮助自己不仅完成对案件的陈述

    2024年02月09日
    浏览(43)
  • Java动态代理、反射

    动态代理就是无侵入式的给代码增加新的功能,通过接口保证后面的对象和代理需要实现同一个接口,接口中就是被代理的所有方法,代理里面就是对象要被代理的方法。 因为一个对象觉得自己身上的功能太多,就会将一部分功能代理出去,对象中什么方法想要被代理,在代

    2024年02月11日
    浏览(50)
  • Java反射和动态代理

    反射允许对封装类的成员变量、成员方法和构造方法的信息进行编程访问 成员变量:修饰符、名字、类型、get/set值 构造方法:修饰符、名字、形参、创建对象 成员方法:修饰符、名字、形参、返回值、抛出的异常、获取注解、运行方法 获取class对象 Class.forName(“全类名”

    2024年02月03日
    浏览(56)
  • Java中的动态代理

    Java中常用的有两种动态代理方式,分别为:JDK动态代理和Cglib动态代理。 JDK动态代理是通过实现接口的方式完成动态代理。 Cglib动态代理是通过继承目标类或实现接口的方式完成动态代理。 JDK动态代理中最核心的就是Proxy类和InvocationHandler接口。 通过调用这个类中的静态方法

    2024年02月16日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包