一、首先说一下JDK中的动态代理:

JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

二、使用CGLib实现

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

下面,将通过一个实例介绍使用CGLib实现动态代理。

1、被代理类

首先,定义一个类,该类没有实现任何接口,包含两个方法。

public class ConcreteClassNoInterface {public String getConcreteMethodA(String str){System.out.println("ConcreteMethod A ... "+str);return str;}public int getConcreteMethodB(int n){System.out.println("ConcreteMethod B ... "+n);return n+10;}
}

2、拦截器

定义一个拦截器。在调用目标方法时,CGLib会回调MethodInterceptor接口方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。

public class ConcreteClassInterceptor 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;}
}

参数:Object为由CGLib动态生成的代理类实例,Method为上文中实体类所调用的被代理的方法引用,Object[]为参数值列表,MethodProxy为生成的代理类对方法的代理引用。

返回:从代理实例的方法调用返回的值。

其中,proxy.invokeSuper(obj,arg):

调用代理类实例上的proxy方法的父类方法(即实体类ConcreteClassNoInterface中对应的方法)

在这个示例中,只在调用被代理类方法前后各打印了一句话,当然实际编程中可以是其它复杂逻辑。

3、生成动态代理类

Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(ConcreteClassNoInterface.class);
enhancer.setCallback(new ConcreteClassInterceptor());
ConcreteClassNoInterface ccni=(ConcreteClassNoInterface)enhancer.create();

这里Enhancer类是CGLib中的一个字节码增强器,它可以方便的对你想要处理的类进行扩展,以后会经常看到它。

首先将被代理类ConcreteClassNoInterface设置成父类,然后设置拦截器ConcreteClassInterceptor,最后执行enhancer.create()动态生成一个代理类,并从Object强制转型成父类型ConcreteClassNoInterface。

最后,在代理类上调用方法:

Java代码  
  1. ccni.getConcreteMethodA("shensy");
  2. ccni.getConcreteMethodB(0);

查看控制台输出:

控制台代码  
  1. Before :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
  2. ConcreteMethod A ... shensy
  3. After :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
  4. Before :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)
  5. ConcreteMethod B ... 0
  6. After :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)

可以看到,拦截器在调用被代理类方法前后都执行了print操作。

实战CGLib系列之proxy:方法拦截MethodInterceptor相关推荐

  1. 死磕cglib系列之一 cglib简介与callback解析

    简介 cglib是一套java动态代理实现框架,cglib被应用到spring app,hibernate等高级业务框架,spring事务在业务实现类未实现接口的情况下也会使用该技术. 实际上,cgl ...

  2. 【WEB API项目实战干货系列】- API登录与身份验证(三)

    上一篇: [WEB API项目实战干货系列]- 接口文档与在线测试(二) 这篇我们主要来介绍我们如何在API项目中完成API的登录及身份认证. 所以这篇会分为两部分, 登录API, API身份验证. ...

  3. 菜鸟级三层框架(EF+MVC)项目实战之 系列一 EF零基础创建领域模型

    系列概述:全系列会详细介绍抽象工厂三层的搭建,以及EF高级应用和 ASP.NET MVC3.0简单应用,应用到的技术有Ef.Lambda.Linq.Interface.T4等. 由于网上对涉及到的技术 ...

  4. .Net中的AOP系列之《方法执行前后——边界切面》

    返回<.Net中的AOP>系列学习总目录 本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用 ...

  5. 【WEB API项目实战干货系列】- API访问客户端(WebApiClient适用于MVC/WebForms/WinForm)(四)

    目前最新的代码已经通过Sqlite + NHibernate + Autofac满足了我们基本的Demo需求. 按照既定的要求,我们的API会提供给众多的客户端使用, 这些客户端可以是各种Web站点, ...

  6. freemarker 数组转字符串_TypeScript 实战算法系列(一):实现数组栈与对象栈

    本文由图雀社区认证作者 神奇的程序员 写作而成,图雀社区将连载其TypeScript 实战算法系列,点击阅读原文查看作者的掘金链接,感谢作者的优质输出,让我们的技术世界变得更加美好? 前言 栈作为一种 ...

  7. Net中的AOP系列之《方法执行前后——边界切面》

    本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用户 真实案例--缓存 小结 本系列的源码本人已托管于C ...

  8. AOP到底有啥魅力?《Spring实战》系列 05

    终于来到了 <Spring实战>第一部分的最后一章,"面向切面的Spring",也是Spring第二把宝刀的精髓所在:AOP大法. 还记得AOP是什么吗?-----(A ...

  9. 【H3C V7路由器实战课程系列-2】WAN接入配置与管理-王达-专题视频课程

    [H3C V7路由器实战课程系列-2]WAN接入配置与管理-643人已学习 课程介绍         全面.系统地介绍了H3C路由器主要的WAN接入技术及应用配置与管理方法,包括PPP.MP.DDR和 ...

最新文章

  1. Firefox 3.6最新功能:网页可根据设备方位调整角度
  2. Introduction to Machine Learning
  3. 算法--腾讯面试:单词游戏,谁会赢?
  4. MapReduce进阶:多MapReduce的链式模式
  5. 笔记-组织级项目管理与大型项目管理-大型及复杂项目
  6. Activiti6.0教程 Eclipse安装Activiti Diagram插件(一)
  7. 信息学奥赛一本通(1061:求整数的和与均值)
  8. PHP js 点击按钮 切换模版,javascript点击按钮实现隐藏显示切换效果_javascript技巧...
  9. Python字符串的格式化,看这一篇就够了
  10. Docker 容器资源管理,你真的学会了吗?
  11. filemode对git diff的影响
  12. 测试用ASP.NET建立一个在线RSS新闻聚合器
  13. Linux下制作动图的软件,GIF制作教程 | 如何制作高清动图_什么值得买
  14. matlab中beta是什么软件,软件版本中的beta是什么意思?
  15. 移动端车牌识别,交警助力
  16. 计算机flash拉开效果,使用Flash制作卷轴展开效果
  17. Vue+Echarts实现饼图统计通过率
  18. 采购订单审批与采购申请审批
  19. 数组转集合问题Arrays.asList()
  20. 理解maven命令package、install、deploy的联系与区别

热门文章

  1. 前端学习(310):清除浮动的方法
  2. spring mvc学习(19):cookievalue注解(显示cookie的值,默认必须有值)
  3. 35修改tomcat端口
  4. 玩转oracle 11g(2):创建数据库
  5. Linux cJSON库的使用、编译为cJSON动态库
  6. 如何对linux文件进行编译,linux编译和执行命令都有哪些?该如何实现?
  7. C++中如何读取一个数的位数_求1000以内的水仙花数
  8. python程序代码解析_Python源码分析3 – 词法分析器PyTokenizer
  9. 51 Python - 装饰器 参数化装饰器——装饰器更通用
  10. 省选专练[POI2005]SAM-Toy Cars