动态代理双剑客--JDK Proxy与CGLIB
背景:
研究过设计模式的同胞们都知道代理模式可以有两种实现方案:
1.接口实现(或继承抽象类)
核心代码片段
ProxySubject-->>doOperation()
//dosomething before
realSubject.doOperation()
//dosomething after
2.继承父类
核心代码片段
ProxySubject-->>doOperation()
//dosomething before
super.doOperation()
//dosomething after
总结:
相同点
都可以通过Proxy控制对Target的访问
不同点
1.灵活性
“接口实现”的方式更加灵活,代理类可以代理所有实现了ISubject接口的类;
“继承父类”的方式代理类只能代理它的父类,因为java中只支持单继承
2.可行性
如果Target有直接接口,那么这两种方式都可以;
如果没有实现任何接口,那只能采取“继承父类”的方式了
正文
Java中动态代理对应着也有两种实现方式
1.“接口实现"---JDK Proxy
用到JDK提供的InvocationHandler接口和Proxy类
类之间的关系如下
InvocationHandler接口
用于处理方法请求
Proxy类
用于生成代理对象
代码演示
ISubject接口
public interface ISubject {
public void showName(String name);
}
RealSubject类
public class RealSubject implements ISubject {
@Override
public void showName(String name) {
System.out.println(name+"闪亮登场");
}
}
LogHandler类
为了更明确的说明动态代理的工作原理,将代理的创建过程放到了LogHandler的外部,即main方法中
public class LogHandler implements InvocationHandler {
Object target=null;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
//调用目标对象方法前的逻辑
System.out.println("下面有一个大人物要出现");
//调用目标对象的方法,这句代码将代理与目标类联系了起来
method.invoke(target, args);
//调用目标对象方法后的逻辑
System.out.println("大家鼓掌欢迎");
return result;
}
}
客户端
类Client
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
LogHandler logHandler=new LogHandler();
logHandler.setTarget(new RealSubject());
//创建代理对象
ISubject proxySubject=(ISubject)Proxy.newProxyInstance(RealSubject.class.getClassLoader(), RealSubject.class.getInterfaces(), logHandler);
System.out.println("-------JDK Proxy-------------");
proxySubject.showName("委座");
}
}
执行结果
调用过程时序图
2.“继承父类”---CGLIB
用到了CBLIB提供的Enhancer类和MethodInterceptor接口
类之间的关系如下
需要引入第三方jar包
- cglib-2.2.jar
- asm-3.1.jar
Enhancer类
用于创建代理对象
MethodInterceptor接口
用于处理方法请求
代码演示
ISubject接口,RealSubject类同上
LogIntercept类
public class LogIntercept implements MethodInterceptor {
Object target=null;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
Object result=null;
//调用目标对象方法前的逻辑
System.out.println("下面有一个大人物要出现");
//调用目标对象的方法,这句代码将代理与目标类联系了起来
arg3.invoke(target, arg2);
//调用目标对象方法后的逻辑
System.out.println("大家鼓掌欢迎");
return result;
}
}
客户端类Client
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
LogIntercept logIntercept=new LogIntercept();
logIntercept.setTarget(new RealSubject());
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(logIntercept);
ISubject proxySubject=(ISubject)enhancer.create();
System.out.println("-------CBLIB-------------");
proxySubject.showName("委座");
}
}
调用过程时序图
总结
大家可以看到JDK Proxy和CGLIB这两种动态代理的实现过程是非常相似的,但也有区别
相同点:
- 都用到了一个接口一个类;
- 接口用于处理方法调用,类用于创建代理对象
JDK Proxy
InvocationHandler接口
Proxy类
CGLIB
MethodIntercept接口
Enhancer类
不同点:
JDK Proxy
使用目标类的接口创建动态代理
CBLIB
使用目标类的子类创建动态代理
最后
JDK Proxy和CGLIB两种动态代理各有千秋,具体用哪个方案要看具体情况。如果目标类实现了对应接口,两种方案都可以;如果没有实现任何接口则要使用CBLIB。比如Hibernate中的实体类是POJO类,没有实现任何接口,那么要通过代理实现延迟加载就只能采用CGLIB方案了。
动态代理双剑客--JDK Proxy与CGLIB的更多相关文章
- Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...
- JDK的动态代理深入解析(Proxy,InvocationHandler)(转)
JDK的动态代理深入解析(Proxy,InvocationHandler)(转) 一.什么是动态代理 动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实.代理一般会实现它所表示的实际对象的 ...
- jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)
代理模式是一种很常见的模式,本文主要分析cglib动态代理的过程 1. 举例 使用cglib代理需要引入两个包,maven的话包引入如下 <!-- https://mvnrepository.c ...
- JDK Proxy和CGLIB Proxy
动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...
- java 动态代理范例 InvocationHandler与Proxy
java 动态代理范例 InvocationHandler与Proxy,拦截与代理 java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxy ...
- java 动态代理模式(jdk和cglib)
package proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Met ...
- 【Java】代理模式,静态代理和动态代理(基于JDK或CGLib)
当我们需要在一个方法之前或之后添加一段逻辑时,自然会想到使用代理类.代理类帮我们代理了实际类的调用,然后可以在实际调用之前和之后添加一些逻辑,从而不浸入实际类. 拓展:由于代理类能在实际类调用之前和之 ...
- java设计模式(一)动态代理模式,JDK与CGLIB分析
-本想着这个知识点放到Spring Aop说说可能更合适一点,但因为上一篇有所提到就简单分析下,不足之处请多多评论留言,相互学习,有所提高才是关键! 什么是代理模式: 记得有本24种设计模式的书讲到代 ...
- 动态代理入门(jdk)
动态代理就是aop的核心,动态代理简单的就是通过创建一个代理对象,然后把原来的方法增强.很抽象,例子是王道.jdk中提供了动态代理的实现,但是它是针对接口,如果要实现动态代理,需要被代理对象的接口.这 ...
随机推荐
- gcc和arm-linux-gcc区别
安装arm-linux-gcc的时候,查了不少资料,总算环境搭好了.于是,想写个程序员的经典程序---hello world. 语法都没错,生成test.c. 命令行运行:arm-linux-gcc ...
- C++ 实现Trim
一.字符串去空格(没有处理字符串中间的空格) lTrim:除去字符串开头的空格 eg." abc123 " --> "abc123 " ...
- 五、MP3文件认识上的几个误区
1.每帧播放时长都为26ms? 很多博客和文章都提到,Mp3文件每个帧的播放时长(Frame_PlayingTime)是26ms,这个结论是错误的.公式应该是这样的: 一个帧的播放时长=一个帧的采样个 ...
- transform的2D部分,嗯…就这个标题了。
上一次写了transition的内容,这次就写拼写很类似的另外一个属性transform好了……我英语差这件事就不要吐槽了,下面是正文,真的: transition是过渡,transform是变换. ...
- React-Native个人信息界面
最近在做一个小练习项目,用户登陆后需要跳转到用户登录信息界面,加班半个小时终于将界面的布局搞定.接触Rect-Native也有一段时间了,以前没有做过ios,只做过android,就布局和开发效率上来 ...
- 链接<a href="javascript:void(0)" />
1.<a href="#"></a>——点击链接后,页面会向上滚到页首,# 默认锚点为 #TOP 2.<a href="javascript ...
- 如何测试sql语句性能,提高执行效率
有时候我们经常为我们的sql语句执行效率低下发愁,反复优化后,可还是得不到提高 那么你就用这条语句找出你sql到底是在哪里慢了 示例: SET STATISTICS io ON SET ...
- 使用xib方式创建UITableViewCell,设置Label自动换行注意事项
自定义的UITableViewCell,使用xib方式创建,想要其中的UILabel换行显示:计算Label的高度,让其自动换行,总是没有效果. 我猜测原因可能在于使用了autolayout布局.只要 ...
- 天坑 之 Eclipse J2EE Preview 运行正确项目一直显示http 404
昨天下载了几个新Demo学习,结果不知道改了哪里,导致运行原先自己写的项目(JSP+Servlet+JDBC)(这理论上不会出什么大的问题吧?这么底层),结果莫名其妙的出现Http 404. 搞的我一 ...
- HTML5动画图片播放器 高端大气
我们见过很多图片播放插件(焦点图),很多都基于jQuery.今天介绍的HTML5图片播放器很特别,它不仅在图片间切换有过渡动画效果,而且在切换时图片中的元素也将出现动画效果,比如图中的文字移动.打散. ...