实战CGLib系列之proxy:方法拦截MethodInterceptor

一、首先说一下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操作。





本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/419337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊聊并发(四)——深入分析ConcurrentHashMap

转载自:http://www.infoq.com/cn/articles/ConcurrentHashMap 术语定义 术语 英文 解释哈希算法hash algorithm是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值。哈希表hash table根据设定的哈希函数H(key)和处理冲突方法将一组…

布点算法的原理和实现

在数据可视化的过程中,绘制网络拓扑图是很重要的,它能清晰呈现一个复杂网络的结构,节点的重要性和关系。比如下面几张图: 下面这张图是我的软件绘制的: 这些都有一个共同的问题,就是如何让图绘制的更加美观…

Nginx是什么?

一、介绍 Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。 Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件代理服务器,并在一个BSD-like协议下发行。由俄罗斯的程序设计师lgor Sysoev所开发,供俄国大…

Spring中拦截/和拦截/*的区别 - 不能访问到返回的JSP - 访问静态资源(jpg,js等)

最近碰到了一个spring的web.xml无法跳转到index.html页面的小问题,查了之后从下面这篇文章中受益,特此转发,谢谢!!! 一、我们都知道在基于Spring的Application中,需要在web.xml中增加下面类似的…

webService上传图片

1 webService 2 3 /// <summary>4 /// 上传图片webServer 的摘要说明5 /// </summary>6 [WebService(Namespace "http://tempuri.org/")]7 [WebServiceBinding(ConformsTo WsiProfiles.BasicProfile1_1)]8 [ToolboxItem(fal…

天赋是牛人的基因?

最近听了吴瀚清&#xff08;俗称道哥&#xff09;分享安全&#xff0c;他是西安交大少年班毕业&#xff0c;专注于安全技术领域&#xff0c;23 岁加入阿里巴巴成为集团最年轻的高级技术专家&#xff0c;目前在阿里任 P10 职级。对于这类少年天才&#xff0c;一般会冠与神童的美…

最长回文Manacher

预处理: 判断一个串是不是回文串&#xff0c;往往要分开编写&#xff0c;造成代码的拖沓 int LongestPalindrome(const char * s, int n){ int i, j, max; if (s 0 || n < 1) return 0; max 0; for (i 0; i < n; i){//i is the middle point of palindrome for (j 0;…