性能优于JDK代理,CGLib如何实现动态代理

按照代理的创建时期,代理类可以分为两种。
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

动态代理三种方式

动态代理实现有三种方式,jdk动态代理(基于接口),cglib动态代理(基于继承),javassist(hibernate中使用这种方式)实现动态代理。

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢?
这就需要CGLib了。

cglib如何实现代理

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。

CGLib原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

cgLib动态代理实例

下面演示一个动态代理的实例。

cglib 是基于asm 字节修改技术。导入 cglib 会间接导入 asm, ant, ant-launcher 三个jar 包。

<!-- cglib 动态代理依赖 begin -->
 <dependency>
   <groupid>cglib</groupid>
   <artifactid>cglib</artifactid>
   <version>3.2.5</version></dependency>
   <!-- cglib 动态代理依赖 stop -->

CGLIB的核心类:

  • net.sf.cglib.proxy.Enhancer – 主要的增强类
  • net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
  • net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
  • Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
public class HelloService {

    public HelloService() {
        System.out.println("HelloService&#x6784;&#x9020;");
    }

    public void sayHello() {
        System.out.println("HelloService:sayHello");
    }

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;

方法拦截器 实现 MethodInterceptor 接口:

public class HelloServiceInterceptor implements MethodInterceptor{

    /**
     * sub&#xFF1A;cglib&#x751F;&#x6210;&#x7684;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;
     * method&#xFF1A;&#x88AB;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x65B9;&#x6CD5;
     * objects&#xFF1A;&#x65B9;&#x6CD5;&#x5165;&#x53C2;
     * methodProxy: &#x4EE3;&#x7406;&#x65B9;&#x6CD5;
     */
    @Override
    public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("======&#x63D2;&#x5165;&#x524D;&#x7F6E;&#x901A;&#x77E5;======");
        Object object = methodProxy.invokeSuper(sub, objects);
        System.out.println("======&#x63D2;&#x5165;&#x540E;&#x7F6E;&#x901A;&#x77E5;======");
        return object;
    }

测试类,生成CGLIB代理对象调用目标方法:

public class CglibTest {
    public static void main(String[] args) {
        // &#x901A;&#x8FC7;CGLIB&#x52A8;&#x6001;&#x4EE3;&#x7406;&#x83B7;&#x53D6;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x7684;&#x8FC7;&#x7A0B;
        Enhancer enhancer = new Enhancer();
        // &#x8BBE;&#x7F6E;enhancer&#x5BF9;&#x8C61;&#x7684;&#x7236;&#x7C7B;
        enhancer.setSuperclass(HelloService.class);
        // &#x8BBE;&#x7F6E;enhancer&#x7684;&#x56DE;&#x8C03;&#x5BF9;&#x8C61;
        enhancer.setCallback(new HelloServiceInterceptor());
        // &#x521B;&#x5EFA;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;
        HelloService proxy= (HelloService)enhancer.create();
        // &#x901A;&#x8FC7;&#x4EE3;&#x7406;&#x5BF9;&#x8C61;&#x8C03;&#x7528;&#x76EE;&#x6807;&#x65B9;&#x6CD5;
        proxy.sayHello();
    }
}

Cglib 总结

  • CGlib可以传入接口也可以传入普通的类,接口使用实现的方式,普通类使用会使用继承的方式生成代理类.

  • 由于是继承方式,如果是 static方法,private方法,final方法等描述的方法是不能被代理的

  • 做了方法访问优化,使用建立方法索引的方式避免了传统JDK动态代理需要通过Method方法反射调用.

  • 提供callback 和filter设计,可以灵活地给不同的方法绑定不同的callback。编码更方便灵活。

  • CGLIB会默认代理Object中equals,toString,hashCode,clone等方法。比JDK代理多了clone。

Original: https://www.cnblogs.com/binyue/p/12268163.html
Author: 邴越
Title: 性能优于JDK代理,CGLib如何实现动态代理

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/544237/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 一次IOS通知推送问题排查全过程

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 发现问题 在上周一个将要下班的夜晚,测试突然和我打招呼,说IOS推送的修复更新上线后存在问题,后台报…

    Java 2023年6月7日
    080
  • IDEAL启动项目的时候报java.lang.NoClassDefFoundError: javax/servlet/Filter错误

    今天在idea里创建一个新项目后,突然出现Filter找不到javax.servlet的jar包 解决方法: 点击file里的Project Structure或者使用快捷键ctr…

    Java 2023年5月29日
    062
  • MySQL 优化篇(二)

    分析查询语句:EXPLAIN 定位了查询慢的SQL之后,我们就可以使用EXPLAIN或DESCRIBE工具做针对性的分析查询语句。DESCRIBE 语句的使用方法与EXPLAIN语…

    Java 2023年6月8日
    071
  • Spring

    Original: https://www.cnblogs.com/Monkey9527/p/14019218.htmlAuthor: 爬蜀道的猴子Title: Spring

    Java 2023年6月7日
    054
  • Spring Boot + Web Socket 打造实时监控异常,写得太好了!

    来源:cnblogs.com/jae-tech/p/15409340.html 写在前面 此异常非彼异常,标题所说的异常是业务上的异常。 最近做了一个需求,消防的设备巡检,如果巡检…

    Java 2023年6月15日
    054
  • Java 提供的国际化支持

    参考资料 1. 缘由 1. 什么是国际化? 2. java.util.ResourceBundle 2.1 代码示例 测试 局限性 3. Spring 的国际化支持 3.1 Mes…

    Java 2023年6月13日
    098
  • 删除链表结点类问题

    删除链表结点 NO1. 删除链表倒数第 k个结点 给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针。要求:空间复杂度 (O(1)),时间复杂度 (O(n)) 如果倒数第…

    Java 2023年6月15日
    091
  • kafka-connect-kudu-sink插件

    kafka-connect-hive是基于 kafka-connect平台实现的 hive数据读取和写入插件,主要由 source、 sink两部分组成, source部分完成 h…

    Java 2023年6月6日
    082
  • html css中有哪些属性可以继承,哪些不可以继承

    css样式表继承指的是,特定的css属性向下传递到后代元素 为了看到继承的实际应用,我们将使用下面的HTML代码。 <p> <em> 继承em> p&…

    Java 2023年6月13日
    065
  • 斐波那契数列(Fibonacci)递归和非递归实现

    序列前9项为:0, 1, 1, 2, 3, 5, 8, 13, 21 要注意非递归的话就是那一个变量帮助存储当前下一项的值,然后依次挪动两个指针往下即可 注意如果n太大 会溢出 O…

    Java 2023年5月30日
    090
  • 基于阿里云的JavaEE系统框架介绍

    基于阿里云的系统框架展望 1) CDN 用于缓存静态文件等等。七牛和阿里的都还可以。 七牛要做的久一点,各种图片处理的接口要完善一些 阿里的CDN要稍微好一点点,但是没有不安全的访…

    Java 2023年5月29日
    068
  • JVM调优篇

    点赞再看,养成习惯,微信搜索「 小大白日志」关注这个搬砖人。 文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。 基础概念 一般JVM调优,重点在于调整JVM堆大小…

    Java 2023年6月8日
    077
  • 分布式ID生成方案

    分布式ID策略 为什么要用分布式ID? 在我们业务数据量不大的时候,单库单表完全可以支撑现有业务,数据再大一点搞个 MySQL 主从同步读写分离也能对付。 但随着数据日渐增长,主从…

    Java 2023年6月15日
    062
  • 美团动态线程池实践思路开源项目(DynamicTp),线程池源码解析及通知告警篇

    大家好,这篇文章我们来聊下动态线程池开源项目(DynamicTp)的通知告警模块。目前项目提供以下通知告警功能,每一个通知项都可以独立配置是否开启、告警阈值、告警间隔时间、平台等,…

    Java 2023年6月14日
    081
  • 如何在servlet取得spring beans (autowired)(转)

    在应用中一般普通的JavaPojo都是由Spring来管理的,所以使用autowire注解来进行注入不会产生问题,但是有两个东西是例外的,一个是 Filter,一个是Servlet…

    Java 2023年5月30日
    064
  • IDEA 无法显示 Run Dashboard 的解决方法

    前言 最近开始接触微服务的项目,项目很多有时候本地调测需要启动多个项目,看到同事都是使用dashboard管理项目,服务和端口排列的整整齐齐。但是我dashboard里面啥都没有,…

    Java 2023年6月5日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球