博客
关于我
【奇淫巧技】Java动态代理(JDK和cglib)
阅读量:658 次
发布时间:2019-03-15

本文共 3046 字,大约阅读时间需要 10 分钟。

JAVA动态代理

代理模式概述

代理模式是Java中的常用设计模式之一,其特点是代理类与委托类具有相同的接口,代理类主要负责为委托类提供额外功能,如预处理、过滤、转发消息以及事后处理等。在这种模式中,代理类和委托类之间通常存在关联关系,一个代理类与一个委托类关联,一般情况下,代理类不会直接实现服务,而是通过调用委托类的方法来提供服务。这样一来,程序开发过程中便可以通过不同的代理类灵活配置功能,例如事务处理、日志记录等,从而提高系统的可扩展性和维护性。

按照代理的创建时期,代理类分为两种:

  • 静态代理:静态代理是程序运行前即已经存在的.class文件形式,由程序员手动创建或由工具自动生成。这种形式的优点是运行效率较高,因为代理类的源代码在编译后静态加载,没有动态生成的开销。
  • 动态代理:动态代理则是在程序运行时通过反射机制动态生成代理类字节码。这种形式的优点是灵活高效,可以根据实际需求动态生成不同的代理实例,同时能在程序运行时进行修改和扩展。
  • 在实际应用开发中,单独使用静态代理往往会产生代理类数量过多的问题,因为每个代理类只能为一个接口服务。面对这种情况,一个更灵活且高效的选择便是使用动态代理。接下来我们将详细探讨Java的动态代理实现方式。


    JDK动态代理

    InvocationHandler接口

    JDK动态代理的核心是通过InvocationHandler接口来实现动态代理的逻辑。InvocationHandler接口声明了一个方法:

    public interface InvocationHandler {    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}

    这个方法的作用是指定如何对代理对象主动生成方法调用。在实际应用中,我们可以通过实现InvocationHandler接口,动态代理拦截并调整方法调用行为。

    Proxy类

    Proxy 类是一个生成动态代理的工具类,主要提供了以下功能:

  • 综合多个接口或类生成一个动态代理类。
  • 动态代理类的行为由指定的InvocationHandler接口的实现来决定。
  • Proxy类的关键方法为:

    public static Object newProxyInstance(ClassLoader loader, Class
    [] interfaces, InvocationHandler h) throws IllegalArgumentException

    其参数说明如下:

    • ClassLoader loader: 拟定的类加载器。
    • Class<?>[] interfaces: 需要被代理的接口类。
    • InvocationHandler h: 拦截方法调用的处理逻辑。

    注意事项:

    • 在调用Proxy.newProxyInstance方法时,需要提供一个正确的ClassLoader实例。在Java中,一个主要的ClassLoader类型包括:

      • Bootstrap ClassLoader: 默认由JVM提供,通常用于核心库类的加载。
      • Extension ClassLoader: 负责扩展库的类加载,通常位于jre\lib\ext目录。
      • AppClassLoader: 默认的类路径加载器,用于应用自身的jar文件中的类加载。
    • 如果不特别指定ClassLoaderProxy.newProxyInstance方法会使用目标类的ClassLoader,这样可以确保绑定类型妥当。

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

    相比于静态代理,动态代理具有以下优势:

  • 灵活性:可以动态生成不同功能的代理类,不受静态代理类绑定的限制。
  • 可扩展性:能够通过反射机制动态修改代理逻辑,支持事务处理、日志记录、权限控制等多种场景。
  • 减少代码冗余:避免了手动编写大量重复代理代码的繁琐性,从而降低开发成本。

  • Cglib动态代理

    除了JDK动态代理,我们还可以使用Cglib动态代理,它旨在代理没有实现接口的具体类。Cglib采用类继承的方式对目标类进行代理,这样 对于实现了final方法的类也能有效生成代理实例。

    Cglib的实现原理

    Cglib通过生成目标类的子类来实现动态代理,并覆盖目标类中需要 proxy 的方法。这样做的优点是可以直接操作目标类的字段和方法,而缺点是不能代理final修饰的方法。

    使用Cglib的步骤

  • 引入Cglib相关的jar包。
  • 编写一个MethodInterceptor类,实现Cglib回调接口。
  • 使用Enhancer工具生成动态代理类。
  • 例如,以下是Cglib动态代理的核心代码:

    public class MethodInterceptor implements MethodInterceptor {    private Object target;    public Object getInstance(Object target) {        this.target = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("事物处理开始");        proxy.invokeSuper(obj, args);        System.out.println("事物处理结束");        return null;    }}

    使用示例

  • 要实现的实际类为:
    public class BookImpl {    public void addBook() {        System.out.println("增加图书");    }}
  • 使用Cglib生成代理类:
    MethodInterceptor interceptor = new MethodInterceptor();BookImpl book = interceptor.getInstance(new BookImpl());book.addBook();
  • 执行结果会输出"增加图书",表明成功完成了对目标类的代理操作。

  • 动态代理的适用场景

    动态代理技术在以下场景下表现出色:

  • 事务处理:通过动态代理可以包装事务逻辑,简化并支持回滚机制。
  • 权限控制:在敏感操作前嵌入权限检查逻辑。
  • 日志记录:在方法执行过程中记录日志信息。
  • 性能监控:统计时间开销,监控方法执行情况。

  • 通过以上内容,我们可以看到,动态代理技术为Java程序的核心逻辑功能增添了强大的灵活性和可扩展性,能够适应复杂的双层业务需求。无论是通过JDK动态代理实现规范化接口代理,还是采用Cglib动态代理实现实例代理,都能为现代Java应用提供优雅而高效的解决方案。

    转载地址:http://iwyqz.baihongyu.com/

    你可能感兴趣的文章
    CSS入门总结
    查看>>
    使用 TortoiseGit 时,报 Access denied 错误
    查看>>
    基于 HTML5 WebGL 的污水处理厂泵站自控系统
    查看>>
    django-表单之模型表单渲染(六)
    查看>>
    c++之程序流程控制
    查看>>
    spring-boot-2.0.3之redis缓存实现,不是你想的那样哦!
    查看>>
    有道云笔记 同步到我的博客园
    查看>>
    李笑来必读书籍整理
    查看>>
    Hadoop(十六)之使用Combiner优化MapReduce
    查看>>
    《机器学习Python实现_10_06_集成学习_boosting_gbdt分类实现》
    查看>>
    CoreCLR源码探索(八) JIT的工作原理(详解篇)
    查看>>
    andriod 开发错误记录
    查看>>
    C语言编译错误列表
    查看>>
    看明白这两种情况,才敢说自己懂跨链! | 喵懂区块链24期
    查看>>
    CentOS5 Linux编译PHP 报 mysql configure failed 错误解决办法
    查看>>
    pycharm新建文件夹时新建python package和新建directory有什么区别?
    查看>>
    python中列表 元组 字典 集合的区别
    查看>>
    Android DEX加固方案与原理
    查看>>
    iOS_Runtime3_动态添加方法
    查看>>
    Leetcode第557题---翻转字符串中的单词
    查看>>