实战CGLib系列之proxy:方法拦截MethodInterceptor
一、首先说一下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。
最后,在代理类上调用方法:
- ccni.getConcreteMethodA("shensy");
- ccni.getConcreteMethodB(0);
查看控制台输出:
- Before :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
- ConcreteMethod A ... shensy
- After :public java.lang.String generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodA(java.lang.String)
- Before :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)
- ConcreteMethod B ... 0
- After :public int generic.cglib.proxy.ConcreteClassNoInterface.getConcreteMethodB(int)
可以看到,拦截器在调用被代理类方法前后都执行了print操作。
实战CGLib系列之proxy:方法拦截MethodInterceptor相关推荐
- 死磕cglib系列之一 cglib简介与callback解析
简介 cglib是一套java动态代理实现框架,cglib被应用到spring app,hibernate等高级业务框架,spring事务在业务实现类未实现接口的情况下也会使用该技术. 实际上,cgl ...
- 【WEB API项目实战干货系列】- API登录与身份验证(三)
上一篇: [WEB API项目实战干货系列]- 接口文档与在线测试(二) 这篇我们主要来介绍我们如何在API项目中完成API的登录及身份认证. 所以这篇会分为两部分, 登录API, API身份验证. ...
- 菜鸟级三层框架(EF+MVC)项目实战之 系列一 EF零基础创建领域模型
系列概述:全系列会详细介绍抽象工厂三层的搭建,以及EF高级应用和 ASP.NET MVC3.0简单应用,应用到的技术有Ef.Lambda.Linq.Interface.T4等. 由于网上对涉及到的技术 ...
- .Net中的AOP系列之《方法执行前后——边界切面》
返回<.Net中的AOP>系列学习总目录 本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用 ...
- 【WEB API项目实战干货系列】- API访问客户端(WebApiClient适用于MVC/WebForms/WinForm)(四)
目前最新的代码已经通过Sqlite + NHibernate + Autofac满足了我们基本的Demo需求. 按照既定的要求,我们的API会提供给众多的客户端使用, 这些客户端可以是各种Web站点, ...
- freemarker 数组转字符串_TypeScript 实战算法系列(一):实现数组栈与对象栈
本文由图雀社区认证作者 神奇的程序员 写作而成,图雀社区将连载其TypeScript 实战算法系列,点击阅读原文查看作者的掘金链接,感谢作者的优质输出,让我们的技术世界变得更加美好? 前言 栈作为一种 ...
- Net中的AOP系列之《方法执行前后——边界切面》
本篇目录 边界切面 PostSharp方法边界 方法边界 VS 方法拦截 ASP.NET HttpModule边界 真实案例--检查是否为移动端用户 真实案例--缓存 小结 本系列的源码本人已托管于C ...
- AOP到底有啥魅力?《Spring实战》系列 05
终于来到了 <Spring实战>第一部分的最后一章,"面向切面的Spring",也是Spring第二把宝刀的精髓所在:AOP大法. 还记得AOP是什么吗?-----(A ...
- 【H3C V7路由器实战课程系列-2】WAN接入配置与管理-王达-专题视频课程
[H3C V7路由器实战课程系列-2]WAN接入配置与管理-643人已学习 课程介绍 全面.系统地介绍了H3C路由器主要的WAN接入技术及应用配置与管理方法,包括PPP.MP.DDR和 ...
最新文章
- Firefox 3.6最新功能:网页可根据设备方位调整角度
- Introduction to Machine Learning
- 算法--腾讯面试:单词游戏,谁会赢?
- MapReduce进阶:多MapReduce的链式模式
- 笔记-组织级项目管理与大型项目管理-大型及复杂项目
- Activiti6.0教程 Eclipse安装Activiti Diagram插件(一)
- 信息学奥赛一本通(1061:求整数的和与均值)
- PHP js 点击按钮 切换模版,javascript点击按钮实现隐藏显示切换效果_javascript技巧...
- Python字符串的格式化,看这一篇就够了
- Docker 容器资源管理,你真的学会了吗?
- filemode对git diff的影响
- 测试用ASP.NET建立一个在线RSS新闻聚合器
- Linux下制作动图的软件,GIF制作教程 | 如何制作高清动图_什么值得买
- matlab中beta是什么软件,软件版本中的beta是什么意思?
- 移动端车牌识别,交警助力
- 计算机flash拉开效果,使用Flash制作卷轴展开效果
- Vue+Echarts实现饼图统计通过率
- 采购订单审批与采购申请审批
- 数组转集合问题Arrays.asList()
- 理解maven命令package、install、deploy的联系与区别
热门文章
- 前端学习(310):清除浮动的方法
- spring mvc学习(19):cookievalue注解(显示cookie的值,默认必须有值)
- 35修改tomcat端口
- 玩转oracle 11g(2):创建数据库
- Linux cJSON库的使用、编译为cJSON动态库
- 如何对linux文件进行编译,linux编译和执行命令都有哪些?该如何实现?
- C++中如何读取一个数的位数_求1000以内的水仙花数
- python程序代码解析_Python源码分析3 – 词法分析器PyTokenizer
- 51 Python - 装饰器 参数化装饰器——装饰器更通用
- 省选专练[POI2005]SAM-Toy Cars