一、动态代理概念

动态代理分为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)详细解析
# 第一个
# 给大家
# 来实现
# 回调
# 过程中
# 是一个
# 子类
# 老生常谈
# 是由
# 则是
# 两种
# 有一定
# 它是
# 可以通过
# 希望能
# 更有
# 如果没有
# 为其
# 更快
# 因为它
相关文章:
建站主机选购指南与交易推荐:核心配置解析
如何在阿里云ECS服务器部署织梦CMS网站?
网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
智能起名网站制作软件有哪些,制作logo的软件?
南平网站制作公司,2025年南平市事业单位报名时间?
制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?
如何在IIS7中新建站点?详细步骤解析
三星网站视频制作教程下载,三星w23网页如何全屏?
建站之星如何助力企业快速打造五合一网站?
c# 在ASP.NET Core中管理和取消后台任务
建站之星如何防范黑客攻击与数据泄露?
小程序网站制作需要准备什么资料,如何制作小程序?
如何选择高性价比服务器搭建个人网站?
php条件判断怎么写_ifelse和switchcase的使用区别【对比】
香港服务器网站推广:SEO优化与外贸独立站搭建策略
建站之星如何实现网站加密操作?
宝塔建站无法访问?如何排查配置与端口问题?
在线教育网站制作平台,山西立德教育官网?
枣阳网站制作,阳新火车站打的到仙岛湖多少钱?
潮流网站制作头像软件下载,适合母子的网名有哪些?
Swift中switch语句区间和元组模式匹配
北京网站制作公司哪家好一点,北京租房网站有哪些?
小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化
建站之星后台密码遗忘或太弱?如何重置与强化?
建站之星后台密码遗忘?如何快速找回?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
已有域名和空间如何搭建网站?
临沂网站制作企业,临沂第三中学官方网站?
在线制作视频的网站有哪些,电脑如何制作视频短片?
如何通过可视化优化提升建站效果?
如何做网站制作流程,*游戏网站怎么搭建?
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
青浦网站制作公司有哪些,苹果官网发货地是哪里?
深圳 网站制作,深圳招聘网站哪个比较好一点啊?
如何在腾讯云服务器上快速搭建个人网站?
建站主机是什么?如何选择适合的建站主机?
建站VPS能否同时实现高效与安全翻墙?
电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?
简易网站制作视频教程,使用记事本编写一个简单的网页html文件?
如何用PHP工具快速搭建高效网站?
c# await 一个已经完成的Task会发生什么
重庆网站制作公司哪家好,重庆中考招生办官方网站?
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
教学论文网站制作软件有哪些,写论文用什么软件
?
建站之星安全性能如何?防护体系能否抵御黑客入侵?
香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南
微网站制作教程,不会写代码,不会编程,怎么样建自己的网站?
如何在建站主机中优化服务器配置?
*请认真填写需求信息,我们会在24小时内与您取得联系。