实战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,一经查实,立即删除!

相关文章

“睡服”面试官系列第六篇之set数据结构(建议收藏学习)

目录 set 1基本用法 2Set 实例的属性和方法 3遍历操作 3.1 keys() , values() , entries() 3.2 forEach() 3.3遍历的应用 weakset 含义 语法 总结 set 1基本用法 ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一…

“睡服”面试官系列第七篇之map数据结构(建议收藏学习)

目录 1map 1.1含义和基本用法 1.2实例的属性和操作方法 1.2.1size属性 1.2.2set(key, value) 1.2.3get(key) 1.2.4has(key) 1.2.5delete(key) 1.2.6clear() 1.3遍历方法 1.4与其他数据结构的互相转换 1.4.1Map 转为数组 1.4.2数组 转为 Map…

java 入门 第二季3

1.继承 1.java是单继承的,一个子类只有一个父类 父类,基类 子类,派生类 2.继承的好处:子类拥有父类的所有属性和方法,属性的修饰符不能是private 3.语法规则: class 子类 extends 父类 如果父类的属性是用p…

聊聊并发(四)——深入分析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所开发,供俄国大…

实战SQL Server 2005镜像配置全过程

SQL Server 2005镜像配置基本概念 我理解的SQL Server 2005镜像配置实际上就是由三个服务器(也可以是同一服务器的三个 SQL 实例)组成的一个保证数据的环境,分别是:主服务器、从服务器、见证服务器。 主服务器:数据存放…

Java反转单链表(code)

转载自:http://poly.iteye.com/blog/1748272 主要是面试中可能会经常碰上该类似操作,尤其是稍大点公司,面试官可能并不在乎你能不能搞定该题,但是这类型题目最是能体现程序员的思维状态 ---一个迷糊头脑的程序员 怎能立志改变这个…

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

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

net重载

先了解重载 重写 和多态性吧 ,这三个基本不同概念。但是基本面试都会同一时间问,让你以为他们有联系呢。真坑。对新手来说 先说重载吧:用同样的名称。用不同的等数列表来创建多个方法和属性,在调用的时候可以适应不同参数的要求&a…

JavaScript 回调函数中的 return false 问题

今天一个同事问了我一个问题,就是在 Ajax 方法中,请求成功后(success)的回调函数中根据响应的值来判断程序是否继续执行,他不解的是在回调函数中已经 return false 了,但是 Ajax 方法外部的后续语句却仍然继…

AngularJs ngIf、ngSwitch、ngHide/ngShow

在组合这些ng指令写到一篇文章里的时候,基本是有规则的,本兽会将功能相似相近的一类整合到一篇文章,方便理解和记忆。 这篇的三个指令也都是对DOM元素的操作,页面上显示/隐藏的判断,添加/移除的判断。 ngIf ngIf指令会…

MySQL与MongoDB的区别

什么是MongoDB ?MongoDB 是由C语言编写的,是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为一个文档&…