动态代理

上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理。

这里再简单总结一下

  • 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象。
  • 静态代理是在程序发布之前,我们就必须写好代理类的
  • 动态代理在程序发布之前,并没有写好代理类,而是发布之后,动态创建代理对象的

这篇文章主要介绍两种动态代理,jdk代理和cglib代理

jdk代理

实现

  • 通过实现 InvocationHandler 接口创建自己的调用处理器
  • 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类
  • 通过反射机制获得动态代理类的构造函数
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入

代码

 Sale saleProxy=(Sale)Proxy.newProxyInstance( jiajun.getClass().getClassLoader(), jiajun.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("===before===");
Object obj = method.invoke(jiajun, args);
System.out.println("===after==="); return obj; }
}); saleProxy.sale();
saleProxy.rent();

原理

  • 生成一个代理类,这个代理类继承Proxy类并且实现了我们定义的接口,代理对象调用方法的时候,调用这个代理对象的一个成员InvocationHandler(上面我们传入了一个InvocationHandler实现对象)的方法,也就是我们添加了before和after后的方法。

cglib代理

实现

  • 实现CGLib包提供的MethodInterceptor接口,实现intercept方法,用CGLib中的Enhancer的creat方法创建代理对象

代码

class CGLibProxy implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println("Before:" + method);
Object object = proxy.invokeSuper(obj, arg);
System.out.println("After:" + method);
return object;
}
}
public class Test2 {
public static void main(String[] args) {
CGLibProxy cgLibProxy=new CGLibProxy();
Jiajun jiajunProxy=(Jiajun)Enhancer.create(Jiajun.class,cgLibProxy);
jiajunProxy.buy();
jiajunProxy.sale();
}
}

原理

  • 通过asm字节码生成框架生成代理类Class的二进制字节码
  • 通过Class.forName加载二进制字节码,生成Class对象
  • 通过反射机制获取实例构造,并初始化代理类对象

jdk代理 vs cglib代理

  • jdk代理只能代理接口,不能代理没有接口的类。
  • cglib代理可以代理没有接口的类

总结

  • 动态代理相对于静态代理更加灵活,减少了代码量也提高了可维护性。
  • 动态代理有两种,一种是jdk代理,通过创建一个继承Proxy类并实现接口的代理对象。一种是cglib代理,通过asm生成代理类class的字节码,再生成Class对象,最后通过反射创建代理对象。
  • jdk代理只适合基于接口的代理,cglib可以代理没有实现接口的目标对象。

我觉得分享是一种精神,分享是我的乐趣所在,不是说我觉得我讲得一定是对的,我讲得可能很多是不对的,但是我希望我讲的东西是我人生的体验和思考,是给很多人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引发自己内心的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)

总结两种动态代理jdk代理和cglib代理的更多相关文章

  1. spring的AOP动态代理--JDK代理和CGLIB代理区分以及注意事项

    大家都知道AOP使用了代理模式,本文主要介绍两个代理模式怎么设置以及区别,对原文一些内容进行了引用后加入了自己的理解和更深入的阐述:   一.JDK代理和CGLIB代理的底层实现区别* JDK代理只能 ...

  2. Java中jdk代理和cglib代理

    代理模式 给某一个对象提供一个代理,并由代理对象控制对原对象的引用.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 在Java中代理模式从实 ...

  3. jdk代理和cglib代理

    1.jdk静态代理(静态代理和动态代理) 本质:在内存中构建出接口的实现类. 缺陷:只能对实现接口的类实现动态代理, 使用cglib可以对没有实现接口的类进行动态代理. 2.cglib动态代理     ...

  4. jdk代理和cglib代理源代码之我见

    以前值是读过一遍jdk和cglib的代理,时间长了,都忘记入口在哪里了,值是记得其中的一些重点了,今天写一篇博客,当作是笔记.和以前一样,关键代码,我会用红色标记出来. 首先,先列出我的jdk代理对象 ...

  5. Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)

    第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation ...

  6. 设计模式---JDK动态代理和CGLIB代理

    Cglig代理设计模式 /*测试类*/ package cglibProxy; import org.junit.Test; public class TestCglib { @Test public ...

  7. JDK动态代理和 CGLIB 代理

    JDK动态代理和 CGLIB 代理 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期期间创建一个接口的实现类来完成对目标对象的代理. 代码示例 接口 public interface ...

  8. Java动态代理和CGLib代理

    本文参考 在上一篇"Netty + Spring + ZooKeeper搭建轻量级RPC框架"文章中涉及到了Java动态代理和CGLib代理,在这篇文章中对这两种代理方式做详解 下 ...

  9. 静态代理、动态代理和cglib代理

    转:https://www.cnblogs.com/cenyu/p/6289209.html 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处 ...

随机推荐

  1. 开涛spring3(8.1) - 对ORM的支持 之 8.1 概述

    8.1  概述 8.1.1  ORM框架 ORM全称对象关系映射(Object/Relation Mapping),指将Java对象状态自动映射到关系数据库中的数据上,从而提供透明化的持久化支持,即把 ...

  2. VR全景智慧城市:360全景市场需要背景及其优势~

    VR元年已过,VR项目.VR创业潮转为理性,VR行业分为两个方向:硬件和内容. VR全景,又被称为3D实景,是一种新兴的富媒体技术,其与视频,声音,图片等传统的流媒体大的区别是"可操作,可交 ...

  3. XCode 8.3 Automatically manage signing 问题

    记录iOS证书问题 无意中选择了Personal team,后台自动生成bundle identifier:com.xxx.project,导致不能在Organization team创建,而且在de ...

  4. PHP 获取系统信息,PHP 获取服务器详细信息

    获取系统类型及版本号:    php_uname()                                   (例:Windows NT COMPUTER 5.1 build 2600)只 ...

  5. gulp报错

    这个问题网上搜索到的答案不一定能够解决问题,有可能是node版本问题,需要升级 到最新版就可以了....

  6. 基于redis实现tomcat8及以上版本的tomcat集群的session持久化实现(tomcat-redis-session-manager二次开发)

    前言: 本项目是基于jcoleman的tomcat-redis-session-manager二次开发版本 1.修改了小部分实现逻辑 2.去除对juni.jar包的依赖 3.去除无效代码和老版本tom ...

  7. C#简单构架之EF进行读写分离+多数据库(Mysql/SqlService)

    最近因为项目需要,研究了下EF的读写分离,所以做了一个demo进行测试,下面是项目的结构 表现层view 主要提供Web.WebApi等表现层的解决方案 公共层public 主要提供项目公共类库,数据 ...

  8. Python中如何调用Linux命令

    一.使用os模块 In [1]: import os #导入os模块 In [2]: os.system('ls') anaconda-ks.cfg epel-release-7-5.noarch.r ...

  9. 我的第一个Java程序

    我的第一个Java程序: class Test{    public static void main(String[] args)    {    System.out.println(" ...

  10. [0] DDD领域驱动设计(三) 之 聚合(根)、实体、值对象

    1.      聚合根.实体.值对象的区别? 从标识的角度: 聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法: 从是否只读的角度 ...