java 动态代理模式(jdk和cglib)
package proxy.dynamicproxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* 需要实现InvocationHandler接口,内部维护一个实际类实例
*
*/
public class JdkProxyHandler implements InvocationHandler { private Object realObject; public Object proxy(Object realObject){
this.realObject = realObject;
return Proxy.newProxyInstance(this.realObject.getClass().getClassLoader(),
this.realObject.getClass().getInterfaces(), this);
} /**
*
* @param proxy 动态生成的代理类实例
* @param method 方法实例
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是代理人:大明星唱歌开始前,我先宣传一下:巴拉巴拉。。。"); // 调用实际类的方法,并传入参数,内部是反射机制
Object ret = method.invoke(this.realObject, args); System.out.println("我是代理人:大明星唱歌完毕了,我来总结一下:巴拉巴拉。。。"); return ret;
}
}
package proxy.dynamicproxy; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* 需要实现MethodInterceptor接口
* cglib相关依赖:
* ant-1.6.2.jar
* asm-3.1.jar
* asm-util-3.1.jar
* cglib-2.2.2.jar
*/
public class CglibProxyHandler implements MethodInterceptor { public Object proxy(Object realObject){ // 使用字节码增强器 四个固定步骤:
// 1、new字节码增强器
// 2、设置当前类实例为回调
// 3、将实际类实例设置为父类
// 4、创建一个代理类
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(realObject.getClass());
// 这里会生成代理类、代理类的FastClass辅助类、实际类的FastClass辅助类
// 辅助类为代理类和实际类的每个方法生成一个唯一的id
// 用于在调用intercept方法时,通过唯一id就可以调用对应的方法
// 不再走反射机制,提高性能
return enhancer.create();
} /**
*
* @param o 代理类的实例
* @param method 方法实例
* @param objects 方法参数
* @param methodProxy 方法代理
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("我是代理人:大明星唱歌开始前,我先宣传一下:巴拉巴拉。。。"); // 这里如果使用 method.invoke方法,就等同于走了反射机制去调用方法,性能不高
// 而且还需要另外维护实际类实例
// Object ret = method.invoke(this.realObject, objects); Object ret = methodProxy.invokeSuper(o, objects); System.out.println("我是代理人:大明星唱歌完毕了,我来总结一下:巴拉巴拉。。。"); return ret;
}
}
package proxy.dynamicproxy; import net.sf.cglib.core.DebuggingClassWriter;
import proxy.staticproxy.IStar;
import proxy.staticproxy.RealStar; public class Test {
public static void main(String[] args) { /**
* 还是以“代理人”和“大明星”为例
* jdk动态代理:适用于大明星实现某接口的情况,且只能用于实现接口的情况
* 不能用于未实现任何接口的类,因为生成的动态代理类要继承自Proxy、同时实现大明星接口。
* cglib动态代理:适用于任何类。它是采用动态代理类直接继承大明星类的方式,将大明星当作父类
* 覆写大明星类的所有方法(除final修饰的方法,wait方法,notify方法)
*
* 优缺点:
* jdk方式,只能针对接口,底层直接写字节码的方式生成代理类,所以生成代理类速度快
* 但是代理类执行方法时,通过反射的方式去执行,速度不如cglib方式
* cglib方式,可以适用于任何类,底层使用ASM框架生成字节码,因为采用FastClass机制
* 在生成代理类的同时还要生成代理类和大明星类的对应FastClass类(辅助类)
* 这两个辅助类的作用是:对应FastClass辅助类会为代理类和大明星类的每一个方法
* (除final修饰的方法,wait方法,notify方法)生成唯一id,这样在后面的调用方法时
* 不再通过反射去执行逻辑,而是直接根据id找到对应的方法去执行,提高性能,但相对的,生成字节码速度较慢
*/
boolean isUseJdkProxy = false; if (isUseJdkProxy) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); IStar star = (IStar) new JdkProxyHandler().proxy(new RealStar());
star.sing();
}
else { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,
"C:\\Users\\Administrator\\IdeaProjects\\untitled\\cglibClass"); IStar star = (IStar) new CglibProxyHandler().proxy(new RealStar()); // 这一步里面的具体流程:
// 动态代理类的sing方法 --> CglibProxyHandler的intercept方法
// --> 实际类执行前的行为代理 --> MethodProxy.invokeSuper方法
// --> 根据唯一id在FastClass里找到对应的实际方法
// --> 代理类的FastClass内部:让代理类调用实际方法
// --> 代理类的实际方法内部一般就是直接调用父类(被代理类)的方法
// --> 返回父类方法的返回值
star.sing(); }
}
}
java 动态代理模式(jdk和cglib)的更多相关文章
- [转]java动态代理(JDK和cglib)
转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...
- java动态代理(JDK和cglib)
转:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代 ...
- 《转》JAVA动态代理(JDK和CGLIB)
该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...
- 《转》java动态代理(JDK和cglib)
该文章转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的 ...
- java动态代理(JDK和cglib实现对比)
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt214 JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特 ...
- Spring学习(四)—— java动态代理(JDK和cglib)
JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他 的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托 ...
- java动态代理(JDK和cglib)(转载)
原文地址:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html 高亮部分是我的理解. JAVA的动态代理 代理模式 代理模式是常用的j ...
- java动态代理(JDK和CGLIB)笔记
动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等. JDK的 ...
- Java 的静态代理 动态代理(JDK和cglib)
转载:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是 ...
- Java中的动态代理(jdk和cglib)
JAVA的动态代理 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类 ...
随机推荐
- 【LOJ#3096】[SNOI2019]数论
[LOJ#3096][SNOI2019]数论 题面 LOJ 题解 考虑枚举一个\(A\),然后考虑有多少个合法的\(B\). 首先这个数可以写成\(a_i+kP\)的形式,那么它模\(Q\)的值成环. ...
- vmware创建虚拟机不识别网卡
今天在给虚拟机添加网卡的时候,出现了虚拟机不识别新加的网卡,很纳闷,连的一样的端口组,为什么新加的网卡识别不了呢 然后查看pci设备,发现网卡的驱动为 AMD 79C970 PCnet32- LANC ...
- swagger.core的使用方法
Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务,那么如何在abp中使用呢,已经有大牛为我们实现了一个swagger.core的组件而作为菜鸟 ...
- SQL SERVER 查询所有数据表名称和数据行数
SELECT a.name, b.rows FROM sysobjects AS a INNER JOIN sysindexes AS b ON a.id = b.id WHERE ( a.type ...
- 详解最大似然估计(MLE)、最大后验概率估计(MAP),以及贝叶斯公式的理解
转载声明:本文为转载文章,发表于nebulaf91的csdn博客.欢迎转载,但请务必保留本信息,注明文章出处. 原文作者: nebulaf91 原文原始地址:http://blog.csdn.net/ ...
- easyui Datagrid 表格高度计算及自适应页面的实现
因为页面上既要计算表格的高度,又要自适应浏览器大小,之前都都采用固定表格高度,这样就会导致不同的分辨率电脑上看起来表格高矮不一, 所以采用了计算网页高度和其他div 的高度之差作为表格的初始高度: H ...
- com.fasterxml.jackson工具类
老版本的Jackson使用的包名为org.codehaus.jackson,而新版本使用的是com.fasterxml.jackson. Jackson主要包含了3个模块: jackson-core ...
- java 源码编译
Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(叫“编译器的前段”更准确)——把*.java文件转变成*.class文件的过程:也可能是虚拟机的后端运行期编译器( ...
- Phoenix(SQL On HBase)
1.简介 Phoenix是一个HBase框架,可以通过SQL的方式来操作HBase. Phoenix是构建在HBase上的一个SQL层,是内嵌在HBase中的JDBC驱动,能够让用户使用标准的JDBC ...
- go [第一篇]初识
[第一篇] 简介 Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发 ...