一、动态代理概念

动态代理分为JDK动态代理和cglib动态代理两种方式。
jdk动态代理是由Java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。
还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。
由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
二、JDK动态代理
以下代码使用代理模式实现一个大小写字符转换的功能。
定义接口和实现类:
ISomeService接口:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
/**
* 接口类
*
* @author Root
*/
public interface ISomeService {
String doFirst();
void doSecond();
}
SomeServiceImpl实现类:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
/**
* 实现类
*
* @author Root
*/
public class SomeServiceImpl implements ISomeService {
@Override
public String doFirst() {
System.out.println("执行doFirst()...");
String result = "abcde";
return result;
}
@Override
public void doSecond() {
System.out.println("执行doSecond()...");
}
}
JDK动态代理类:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
final ISomeService target = new SomeServiceImpl();
// 使用JDK的Proxy动态代理,要求目标类和代理类必须实现相同的接口,因为其底层的执行原理与静态代理的相同
ISomeService service = (ISomeService) Proxy.newProxyInstance(
// 目标类的类加载器
target.getClass().getClassLoader(),
// 目标类所实现的所有接口
target.getClass().getInterfaces(),
new InvocationHandler() {
// proxy:代理对象
// method:目标方法
// args:目标方法的参数列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用目标方法
Object result = method.invoke(target, args);
if (result != null) {
result = ((String) result).toUpperCase();
}
return result;
}
});
String result = service.doFirst();
System.out.println(result);
service.doSecond();
}
}
三、cglib动态代理
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:
CGLIB的核心类:
net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;
第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。
以下程序实现了大小写转换的功能:
实现类SomeService:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
/**
* 实现类
*
* @author Root
*/
public class SomeService {
public String doFirst() {
System.out.println("执行doFirst()...");
String result = "abcde";
return result;
}
public void doSecond() {
System.out.println("执行doSecond()...");
}
}
代理类MyCglibFactory:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyCglibFactory implements MethodInterceptor {
private SomeService target;
public MyCglibFactory() {
super();
target = new SomeService();
}
public SomeService myCglibCreator() {
// 创建增强器对象
Enhancer enhancer = new Enhancer();
// 指定目标类,即父类
enhancer.setSuperclass(SomeService.class);
// 设置回调接口对象
enhancer.setCallback(this);
return (SomeService) enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 调用目标方法
Object result = method.invoke(target, args);
if (result != null) {
result = ((String) result).toUpperCase();
}
return result;
}
}
测试:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;
public class Main {
public static void main(String[] args) {
SomeService service = new MyCglibFactory().myCglibCreator();
String result = service.doFirst();
System.out.println("result = " + result);
service.doSecond();
}
}
运行结果:
执行doFirst()... result = ABCDE 执行doSecond()...
以上这篇老生常谈设计模式之动态代理就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
# 设计模式之动态代理
# 详解java动态代理模式
# Java动态代理分析及简单实例
# java 代理模式及动态代理机制深入分析
# java 反射和动态代理详解及实例代码
# Java动态代理分析及理解
# java动态代理(jdk与cglib)详细解析
# 第一个
# 给大家
# 来实现
# 回调
# 过程中
# 是一个
# 子类
# 老生常谈
# 是由
# 则是
# 两种
# 有一定
# 它是
# 可以通过
# 希望能
# 更有
# 如果没有
# 为其
# 更快
# 因为它
相关文章:
在线流程图制作网站手机版,谁能推荐几个好的CG原画资源网站么?
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
,南京靠谱的征婚网站?
如何快速上传建站程序避免常见错误?
一键制作网站软件下载安装,一键自动采集网页文档制作步骤?
手机网站制作与建设方案,手机网站如何建设?
青岛网站建设如何选择本地服务器?
网站制作公司排行榜,抖音怎样做个人官方网站
广东专业制作网站有哪些,广东省能源集团有限公司官网?
如何自定义建站之星网站的导航菜单样式?
如何用好域名打造高点击率的自主建站?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
如何获取PHP WAP自助建站系统源码?
seo网站制作优化,网站SEO优化步骤有哪些?
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
济南专业网站制作公司,济南信息工程学校怎么样?
已有域名如何免费搭建网站?
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
javascript基本数据类型及类型检测常用方法小结
定制建站价位费用解析与套餐推荐全攻略
如何在云服务器上快速搭建个人网站?
免费制作小说封面的网站有哪些,怎么接网站批量的封面单?
大连网站制作公司哪家好一点,大连买房网站哪个好?
建站168自助建站系统:快速模板定制与SEO优化指南
怀化网站制作公司,怀化新生儿上户网上办理流程?
如何在宝塔面板创建新站点?
网站制作软件免费下载安装,有哪些免费下载的软件网站?
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
建站之星在线版空间:自助建站+智能模板一键生成方案
c# 服务器GC和工作站GC的区别和设置
公司网站设计制作厂家,怎么创建自己的一个网站?
零服务器AI建站解决方案:快速部署与云端平台低成本实践
如何制作算命网站,怎么注册算命网站?
已有域名能否直接搭建网站?
如何快速生成ASP一键建站模板并优化安全性?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
建站主机类型有哪些?如何正确选型
百度网页制作网站有哪些,谁能告诉我百度网站是怎么联系?
如何通过服务器快速搭建网站?完整步骤解析
建站主机系统SEO优化与智能配置核心关键词操作指南
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
如何快速重置建站主机并恢复默认配置?
建站之星展会模版如何一键下载生成?
建站之星与建站宝盒如何选择最佳方案?
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
定制建站方案优化指南:企业官网开发与建站费用解析
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
代刷网站制作软件,别人代刷火车票靠谱吗?
网站制作知乎推荐,想做自己的网站用什么工具比较好?
*请认真填写需求信息,我们会在24小时内与您取得联系。