当前位置: 首页 > news >正文

深圳市建设管理中心网站首页资源搜索神器

深圳市建设管理中心网站首页,资源搜索神器,wordpress禁止评论,网站的关键词库怎么做的那么多文章目录 1. 简介2. 示例3. 原理4. JDK动态代理与CGLIB动态代理区别(面试常问) 1. 简介 CGLIB的全称是:Code Generation Library。 CGLIB是一个强大的、高性能、高质量的代码生成类库,它可以在运行期扩展Java类与实现Java接口&a…

文章目录

  • 1. 简介
  • 2. 示例
  • 3. 原理
  • 4. JDK动态代理与CGLIB动态代理区别(面试常问)

1. 简介

CGLIB的全称是:Code Generation Library。

CGLIB是一个强大的、高性能、高质量的代码生成类库,它可以在运行期扩展Java类与实现Java接口,
底层使用的是字节码处理框架ASM。

Github地址:github.com/cglib/cglib。

CGLIB的Maven坐标如下所示:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

2. 示例

首先,新增一个类:

public class Coder {public void work() {System.out.println("认真写bug……");}
}

然后,自定义一个方法拦截器,实现net.sf.cglib.proxy.MethodInterceptor接口并重写intercept方法:

public class AttendanceMethodInterceptor implements MethodInterceptor {@Overridepublic 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;}
}

重点看下Object result = proxy.invokeSuper(obj, args);,该行代码最终会执行真正的目标方法,在这前后,我们可以添加一些增强逻辑。

然后,新建个测试类,看下CGLIB动态代理如何使用:

public class CglibProxyTest {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Coder.class);enhancer.setCallback(new AttendanceMethodInterceptor());// 创建代理对象Object object = enhancer.create();Coder coder = (Coder) object;coder.work();}
}

运行以上代码,效果如下图所示:
在这里插入图片描述

从运行结果可以看出,在目标方法的前后,执行了自定义的操作。

3. 原理

看下上面的测试类代码,首先是创建了一个net.sf.cglib.proxy.Enhancer对象,然后调用了setSuperclass()方法将enhancer对象的父类设置为Coder类:
在这里插入图片描述

紧接着调用了setCallback()方法将enhancer对象的方法拦截器设置为自定义的AttendanceMethodInterceptor
在这里插入图片描述

然后是调用enhancer对象的create()方法来生成一个代理对象。

先打印下,简单看下这个代理类的信息:
在这里插入图片描述

图中的com.zwwhnly.mybatisplusdemo.cglibproxy.Coder$$EnhancerByCGLIB$$8e91f654就是CGLIB生成的代理类的名称。

那么这个代理类具体是什么样子呢?

在上面的测试类代码中(Object object = enhancer.create();代码之前)添加以下一行代码:

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./cglib");

然后再次运行,会看到项目根目录下生成了一个cglib文件夹,自动生成的代理类就包含在其中:
在这里插入图片描述

可以看到一共生成了5个类,这里重点关注下红色标记的3个类。

先看下Coder$$EnhancerByCGLIB$$8e91f654.class,这个类就是自动生成的代理类:

可以看出Coder$$EnhancerByCGLIB$$8e91f654.class继承了Coder类(也就是说自动生成的代理类其实是被代理类的一个子类),并且重写了Coder类的work()方法,重写后的work()方法会调用自定义的方法拦截器AttendanceMethodInterceptor里的intercept()方法。

然后看下Coder$$EnhancerByCGLIB$$8e91f654$$FastClassByCGLIB$$4e5eb5aa,从名称上可以看出这个类的前半段和上面的类的名称是一样的,后半段拼接上了$$FastClassByCGLIB$$4e5eb5aa,从功能上说,这个类是上面的代理类的索引类,重点关注下里面的getIndex()方法和invoke()方法:
在这里插入图片描述

最后看下Coder$$FastClassByCGLIB$$398819d0,这个类是被代理类Coder的索引类,重点也是关注下里面的getIndex()方法和invoke()方法:
在这里插入图片描述

知道了这3个类的作用后,再一步一步看下示例代码中coder.work();的调用过程,因为coder是生成的代理类的实例,所以coder.work();首先调用的是Coder$$EnhancerByCGLIB$$8e91f654的work()方法:
在这里插入图片描述

这里的var10000是自定义的方法拦截器AttendanceMethodInterceptor,所以执行的是红色截图里的intercept()方法,也就是:
在这里插入图片描述

然后看下invokeSuper()方法:
在这里插入图片描述

首先执行的是init()方法,在该方法内部对fastClassInfo字段进行了赋值:
在这里插入图片描述

从上图可以看出,fci.f1是自动生成的Coder类的索引类Coder$$FastClassByCGLIB$$398819d0,所以fci.i1 = fci.f1.getIndex(sig1);其实执行的是的Coder$$FastClassByCGLIB$$398819d0的getIndex()方法:
在这里插入图片描述

fci.f2是自动生成的代理类的索引Coder$$EnhancerByCGLIB$$8e91f654$$FastClassByCGLIB$$4e5eb5aa,
所以fci.i2 = fci.f2.getIndex(sig2);其实执行的是的Coder$$EnhancerByCGLIB$$8e91f654$$FastClassByCGLIB$$4e5eb5aa的getIndex()方法:
在这里插入图片描述

看完init()方法后再回到invokeSuper()方法:
在这里插入图片描述

上图中的FastClassInfo fci = fastClassInfo;使用到的字段fastClassInfo在init()方法内部已经赋过值,
fci.f2其实是自动生成的代理类的索引类Coder$$EnhancerByCGLIB$$8e91f654$$FastClassByCGLIB$$4e5eb5aa,fci.i2值是1,

所以fci.f2.invoke(fci.i2, obj, args);实际执行的是:
在这里插入图片描述

这里的var10000其实是自动生成的代理类Coder$$EnhancerByCGLIB$$8e91f654的实例,所以接着调用的是
代理类Coder$$EnhancerByCGLIB$$8e91f654的CGLIB$work$0()方法:
在这里插入图片描述

这里的super指的是Coder类,所以super.work();实际执行的是Coder类的work()方法:
在这里插入图片描述

综上所述,coder.work();的调用顺序依次是:

代理类—>自定义方法拦截器—>代理类索引类getIndex()方法–>代理类索引类invoke()方法—>代理类—>被代理类。

4. JDK动态代理与CGLIB动态代理区别(面试常问)

关于JDK动态代理,可以查看上一篇博客:JDK动态代理原理。

了解了JDK动态代理和CGLIB动态代理的原理后,现在来比较下两者的区别,这也是面试时几乎必问的一道面试题。

  • 使用JDK动态代理,被代理类必须要实现接口,使用CGLIB动态代理,被代理类可以不实现接口

    原因分析:
    JDK动态代理生成的代理类继承了java.lang.reflect.Proxy,因为Java是单继承的,如果不通过实现接口的形式,
    无法对类进行扩展。
    CGLIB动态代理生成的代理类实际上是被代理类的子类,所以被代理类可以不实现接口。

  • 自动生成类的数量不同

    JDK动态代理只会生成1个代理类,一般情况下名称为:com.sun.proxy.$Proxy0
    CGLIB动态代理会生成好几个类,核心的3个分别是:

    • 代理类:被代理类的子类,名称格式为Coder$$EnhancerByCGLIB$$8e91f654,包名和被代理类包名一致。
    • 代理类的索引类:名称格式为Coder$$EnhancerByCGLIB$$8e91f654$$FastClassByCGLIB$$4e5eb5aa
      包名和被代理类包名一致。
    • 被代理类的索引类:名称格式为Coder$$FastClassByCGLIB$$398819d0,包名和被代理类包名一致。
  • 生成代理类技术不同

    JDK动态代理使用JDK自带的ProxyGenerator类生成字节码文件。
    CGLIB动态代理使用ASM框架生成字节码文件。

  • 调用方式不同

    JDK动态代理:代理类—>InvocationHandler.invoke()—>被代理类方法(用到了反射)。
    CGLIB动态代理:代理类—>MethodInterceptor.intercept()—>代理类索引类getIndex()—>
    代理类索引类invoke()—>代理类—>被代理类。(直接调用)

http://www.ritt.cn/news/13870.html

相关文章:

  • 做网站教学书网络外包运营公司
  • 编程和做网站有关系吗太原搜索引擎优化招聘信息
  • 用一个域名免费做网站cps广告联盟网站
  • 如何做网站的教程威海seo公司
  • 沈阳模板建站方案如何做百度推广
  • 做网站 证书 浏览器如何注册自己的网站
  • 网站外链接自己可以怎么做网站设计公司哪家专业
  • 常用的搜索引擎网站网页seo是什么意思
  • 公司网站建设制作全包厦门网络推广哪家强
  • 做的视频传到哪个网站好雅虎搜索引擎入口
  • 运营者邮箱怎么注册手机优化管家
  • 弹窗网站制作器常用的网站推广方法
  • 移动端h5是什么绍兴seo优化
  • 做中国供应商免费网站有作用吗整站优化推广
  • 传统电商平台有哪些做seo需要用到什么软件
  • 广州市品牌网站建设服务机构营销型网站建设题库
  • wordpress 批量文章济南网站自然优化
  • 用服务器ip做网站域名最新seo自动优化软件
  • 做外贸的有哪些网站有哪些天津百度快速优化排名
  • 类似5173的网站怎么做成都seo培训班
  • 想建个图片网站公众号运营收费价格表
  • 抚州做网站公司哪家好西青seo
  • 网站建设域名怎么收费的杭州seo渠道排名
  • 廉价网站建设百度站长工具是什么意思
  • 代码做网站图片怎么插免费域名的网站
  • 初学者做网站惠州seo推广公司
  • seo优化推荐长沙谷歌优化
  • 用vue.js做网站的好处网络顾问
  • 海淀区手机网站制作服务seo零基础入门教程
  • 龙岩网站设计网络营销推广外包服务