动态代理

一、静态代理

代理的背后一般至少有一个实际对象,代理的外部功能和实际对象一般是一样的,

用户与代理打交道,不直接接触实际对象。代理存在的价值:

1)节省成本比较高的实际对象创建开销,按需延迟加载,创建代理时

并不正真创建实际对象,而只是保存实际对象的地址,在需要时再加载或者创建。

2)执行权限检查,代理检查权限后再调用实际对象。

3)屏蔽网络的差异性和复杂性,代理在本地,而实际对象在其他服务器上,调用

本地代理时,本地代理请求其他服务器。

静态代理示例:

public class SimpleStaticProxy {//服务接口static interface IService {void sayHello();}//服务类static class RealService implements IService {@Overridepublic void sayHello() {System.out.println("hi");}}//代理类static class TraceProxy implements IService {private IService realService;public TraceProxy(IService realService) {this.realService = realService;}@Overridepublic void sayHello() {System.out.println("Start say hi");realService.sayHello();System.out.println("End say hi");}}public static void main(String[] args) {RealService service = new RealService();TraceProxy traceProxy = new TraceProxy(service);traceProxy.sayHello();}
}

静态代理缺陷:如果每个类都需要代理,我们需要为每个类都创建代理类,

实现所有接口,这个工作量相当大。

二、Java SDK代理

所谓动态代理,代理类是动态生成的。

1.用法

public class SimpleJDKDynamicProxy {interface IService {void sayHello();void sayGoodBye();}static class RealService implements IService {@Overridepublic void sayHello() {System.out.println("hi");}@Overridepublic void sayGoodBye() {System.out.println("GoodBye world!");}}static class SimpleInvocateHandler implements InvocationHandler {private Object realObj;public SimpleInvocateHandler(Object realObj) {this.realObj = realObj;}/*** @param proxy 表示代理对象本身,注意它不是被代理的对象,这个参数用处不大* @param method 表示正在被调用的方法* @param args 表示方法的参数* */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Start " + method.getName());Object result = method.invoke(realObj, args);System.out.println("End " + method.getName());return result;}}public static void main(String[] args) {IService realService = new RealService();IService proxyService = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(),new Class<?>[]{IService.class}, new SimpleInvocateHandler(realService));proxyService.sayHello();proxyService.sayGoodBye();}
}

/*** @param loader 类加载器* @param interfaces 代理类要实现的接口列表* @param h 该接口定义了invoke方法,对代理接口所有的方法调用都会转给该方法* @return 可以转换为interfaces数组中的某个接口类型,注意只能转换为接口不能转换为具体的类* */public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h);

2.基本原理

创建proxyService的代码可以用如下的代码代替:

//创建代理类定义,类定义会被缓存
Class<?> proxyCls = Proxy.getProxyClass(IService.class.getClassLoader(), new Class<?>[] { IService.class });
//获取代理类的构造方法
Constructor<?> ctor = proxyCls.getConstructor(new Class<?>[] { InvocationHandler.class });
InvocationHandler handler = new SimpleInvocationHandler(realService);
//创建代理类对象
IService proxyService = (IService) ctor.newInstance(handler);

    final class $Proxy0 extends Proxy implements SimpleJDKDynamicProxyDemo.IService {private static Method m1;private static Method m3;private static Method m2;private static Method m0;public $Proxy0(InvocationHandler paramInvocationHandler) {super(paramInvocationHandler);}public final boolean equals(Object paramObject) {return((Boolean) this.h.invoke(this, m1,new Object[] { paramObject })).booleanValue();}public final void sayHello() {this.h.invoke(this, m3, null);}public final String toString() {return (String) this.h.invoke(this, m2, null);}public final int hashCode() {return ((Integer) this.h.invoke(this, m0, null)).intValue();}static {m1 = Class.forName("java.lang.Object").getMethod("equals",new Class[] { Class.forName("java.lang.Object") });m3 = Class.forName("laoma.demo.proxy.SimpleJDKDynamicProxyDemo$IService").getMethod("sayHello",new Class[0]);m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);}}

三、cglib动态代理

Java SDK动态代理的局限,它只能为接口创建代理,返回的代理对象也只能转换到某个接口类型。

public class SimpleCGLibDemo {static class RealService {public void sayHello() {System.out.println("hello");}}static class SimpleInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object object, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {System.out.println("start " + method.getName());Object result = methodProxy.invokeSuper(object, args);System.out.println("end " + method.getName());return result;}}private static <T> T getProxy(Class<T> cls) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(cls);enhancer.setCallback(new SimpleInterceptor());return (T) enhancer.create();}public static void main(String[] args) {RealService proxy = getProxy(RealService.class);proxy.sayHello();}
}

cglib是通过继承实现的,具体原理略。

转载于:https://www.cnblogs.com/Shadowplay/p/10005222.html

Java笔记(二十一) 动态代理相关推荐

  1. 深入理解Java Proxy和CGLIB动态代理原理

    点击上方关注,每天进步一点点 动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译 ...

  2. Java Proxy和CGLIB动态代理原理

    动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...

  3. Java核心技术点之动态代理

    本篇博文会从代理的概念出发,介绍Java中动态代理技术的使用,并进一步探索它的实现原理.由于个人水平有限,叙述中难免出现不清晰或是不准确的地方,希望大家可以指正,谢谢大家:) 一.概述 1. 什么是代 ...

  4. Java 反射机制和动态代理是基于什么原理,了解过吗?

    工作多年以及在面试中,我经常能体会到,有些面试者确实是认真努力工作,但坦白说表现出的能力水平却不足以通过面试,通常是两方面原因: 1."知其然不知其所以然". 做了多年技术,开发了 ...

  5. python3.4学习笔记(二十一) python实现指定字符串补全空格、前面填充0的方法

    python3.4学习笔记(二十一) python实现指定字符串补全空格.前面填充0的方法 Python zfill()方法返回指定长度的字符串,原字符串右对齐,前面填充0. zfill()方法语法: ...

  6. java底层 —反射、动态代理

    java底层 -反射.动态代理和注解 1. 反射介绍 1.1 反射 反射是指程序可以访问,检测,修改它本身状态或行为的一种能力. 1.2 java的反射机制 java的反射机制是指在程序运行状态中,给 ...

  7. [Spring手撸专栏学习笔记]——把AOP动态代理,融入到Bean的生命周期

    本文是学习<Spring 手撸专栏>第 10 章笔记,主要记录我的一些debug调试过程,方便后期复习.具体学习,大家可以去看一下这个专栏,强烈推荐. 方案 其实在有了AOP的核心功能实现 ...

  8. Java高级编程细节-动态代理-进阶高级开发必学技能

    关于代理模式的话题有很多, 在开发中经常用到的应该是静态代理模式,能很好的去耦合. 动态代理是代理模式的另外一种实现. 动态代理的区别在哪里? 动态代理有什么好处? 今天我们来分析下这些问题. 回顾静 ...

  9. Java反射机制和动态代理实例

    反射机制是Java语言的一个重要特性,允许用户动态获取类的信息和动态调用对象的方法. 通过给定类的名字,通过反射机制就可以获取类的所有信息. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道 ...

  10. 【Visual C++】游戏开发笔记二十一 游戏基础物理建模(三) 摩擦力系统模拟

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7555785 作者:毛星云    邮箱: h ...

最新文章

  1. 正则表达式re模块使用介绍
  2. 微信开发系列之一 - 微信公众号开发的开发环境搭建
  3. 深入探究Kubernetes - 初识容器
  4. 智能电视直播软件_速度快,节目多,高清网络电视直播
  5. 60-30-012-使用-Kafka不停机删除topic数据(自动建立topic)md
  6. java连接池hkai,MySQL连接配置文件密码加密及其在多种连接池上的应用
  7. 计算机多媒体技术的内容有哪些方面,多媒体技术是什么_多媒体技术知识点总结...
  8. 构建简单的智能客服系统(三)——基于 UniMRCP 实现讯飞 TTS MRCP Server
  9. welearn综合教程网课答案
  10. 影响力 读后感 书评
  11. php 腾讯短信接口api,ThinkPHP5——接入腾讯云短信API
  12. gitter 卸载_最佳Gitter渠道:材料设计
  13. 联想电脑G40无法使用 非要睡眠后才能启用wifi
  14. Linux - UAC USB声卡
  15. 我的四核Cortex-A53学习之路
  16. 模块 , 用户管理系统 , 购物车程序 , 分页显示.
  17. 如何在个人微信中免费接入ChatGPT
  18. 使用Fiddler抓包工具后导致无法正常上网
  19. “理想”上市,80后李想,做出2家上市公司:这是我给年轻人的100条成长建议...
  20. ext.net 后台方法调用

热门文章

  1. 图书管理系统的5W1H
  2. python 多线程 paramiko实现批量命令输入输出
  3. 创建模态对话框和非模态对话框
  4. 浅谈一下js中的this
  5. vscode调试Flutter
  6. while (n-- > 0) 的用法
  7. office套件_【office】Android版微软办公套件Office独立版一体化
  8. 进程调度的时机,切换与过程,方式
  9. 力扣 买卖股票的最佳时机II
  10. 2021年POS机费率上调了吗?