java动态代理_Java核心 -- 动态代理
- 动态类型和静态类型:语言类型是 运行时 检查,还是 编译期 检查
- 强类型和弱类型:为 不同类型 的变量赋值时,是否需要进行 显式的类型转换
- Java是 静态的强类型语言 ,但提供了类似 反射 等机制,因此也具备了 部分 动态类型语言的能力
反射
- 反射机制是Java语言提供的一种基础功能,赋予程序 在运行时自省 的能力
- 通过反射可以 直接操作类或者对象
- 获取某个对象的类定义
- 获取类声明的属性和方法
- 调用方法或者构造函数
- 运行时修改类定义
setAccessible
- AccessibleObject.setAccessible(boolean flag):可以在 运行时 修改成员的 访问限制
- setAccessible的应用遍布在日常开发、测试、依赖注入等框架中
- 在O/R Mapping框架中,为一个Java实体对象,运行时自动生成getter/setter方法
- 绕过API的访问控制,来调用内部API
动态代理
- 动态代理是一种方便 运行时动态构建代理、动态处理代理方法调用 的机制
- 很多场景都是利用类似的机制来实现的,例如用来 包装RPC调用 和 AOP
- 实现动态代理的方式
- JDK自身提供的动态代理,主要利用 反射 机制
- 字节码操作机制 ,类似ASM、cglib(基于ASM)和Javassist
解决的问题
- 动态代理是一种 代理 机制,代理可以看作对调用目标的 包装 ,对目标代码的调用是通过代理完成的
- 通过代理可以让 调用者和实现者解耦 ,例如RPC调用,框架内部的寻址、序列化、反序列化等,对调用者没什么意义
发展历程
- 静态代理 -> 动态代理
- 静态代理:需要引入 额外的工作 ,而这些工作与实际的业务逻辑没有关系
- 古董技术RMI,需要rmic之类的工具生成静态stub等文件,增加了很多繁琐的准备工作
- 动态代理:相应的stub等类,可以在运行时生成,对应的调用操作也是动态生成的,极大地提高生产力
JDK Proxy + cglib
public class MyDynamicProxy {public static void main(String[] args) {Hello hello = new HelloImpl();MyInvocationHandler handler = new MyInvocationHandler(hello);// 构造代理实例Hello proxyHello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), hello.getClass().getInterfaces(), handler);// 调用代理方法proxyHello.sayHello();// 输出// MyInvocationHandler Invoking HelloImpl#sayHello// HelloImpl : Hello World}
}interface Hello {void sayHello();
}class HelloImpl implements Hello {@Overridepublic void sayHello() {System.out.println(getClass().getSimpleName() + " : Hello World");}
}@AllArgsConstructor
class MyInvocationHandler implements InvocationHandler {private Object target;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(getClass().getSimpleName() + " Invoking " + target.getClass().getSimpleName() + "#" + method.getName());Object result = method.invoke(target, args);return result;}
}
- 实现InvocationHandler,添加 额外 逻辑
- 以Hello接口为纽带,为被调用目标构建 代理对象 ,可以使用代理对象 间接 运行调用目标的逻辑
- 以 接口 为中心,相当于添加了一种 对被调用者没有太大意义的限制
- 另外实例化的是 Proxy对象 ,而不是真正的被调用类型,可能会带来各种不变和能力退化
- 如果 被调用者没有实现接口 ,可以通过 cglib 来实现动态代理(克服了对接口的依赖)
- cglib动态代理的方式:创建目标类的 子类 ,可以达到 近似使用被调用者本身 的效果
优势对比
JDK Proxy
- 最小化依赖关系 ,简化开发和维护,JDK本身的支持
- JDK平滑升级 ,而字节码类库通常需要进行 更新 以保证在新版Java上能够使用
- 代码实现简单
cglib
- 侵入性更小,JDK Proxy是基于 接口 的,而 限定被调用者实现特定接口 是有侵入性的实践
- 只需操作关心的类 ,而不必为其它相关类增加工作量
- 高性能
性能对比
- 在 主流 的JDK版本中,JDK Proxy在 典型场景 可以提供 对等的性能水平 ,在数量级的差距并不是广泛存在的
- 反射机制的性能在 现代 JDK中,已经得到了 极大的改进和优化 ,同时JDK的很多功能同样使用了 ASM 进行字节码操作
- 在选型时,性能并不是唯一考量,而 可靠性、可维护性和编程工作量 才是更主要的考虑因素
java动态代理_Java核心 -- 动态代理相关推荐
- java如何实现动态时钟_Java实现动态数字时钟
本文实例为大家分享了Java实现动态数字时钟的具体代码,供大家参考,具体内容如下 构建: Clock继承 JFrame 为运行页面 ClockText 测试类 创建 Clock 对象 运行效果: 具体 ...
- java数字时钟_Java实现动态数字时钟
本文实例为大家分享了Java实现动态数字时钟的具体代码,供大家参考,具体内容如下 构建: Clock继承 JFrame 为运行页面 ClockText 测试类 创建 Clock 对象 运行效果: 具体 ...
- java动态打包_java 调用动态库打包sdk
java连接c++动态库并生成jar包提供给别人调用 1.需要将java通过jni生成头文件,并导入到c++项目并对c++进行jni方法继承 在项目的src目录执行,否则会提示 错误:找不到符号 ja ...
- java常量配置_java项目动态配置常量和peiconfig.properties配置使用详解
java项目动态配置常量和peiconfig.properties配置使用详解 点击:2 Java工程中配置信息一般都写在 properties文件中,下面这篇文章是对java基础配置的一点学习心得整 ...
- java动态录音_java实现动态录音,声卡有声音进来就自动录音
TargetDataLine是声音的输入(麦克风),而SourceDataLine是输出(音响,耳机). 整个过程,请参见下面的程序.(运行后,实时地从麦克风录音,实时输出). import java ...
- java 卷轴式_java核心卷轴之泛型程序设计
本文根据<Java核心卷轴>第十二章总结而来,更加详细的内容请查看<Java核心卷轴> 1. 泛型类型只能是引用类型,不可以使用基本数据类型. 2. 类型变量含义 E :集合K ...
- java 流式_Java核心教程5: 流式编程
本次课程的标题不像之前那样易懂,是一个陌生的概念,"流式编程"是个什么东西? 在了解流式编程之前先思考一下"流",水流.电流.人流,这些都是流.而流式编程则是让 ...
- springboot 注解动态赋值_java springboot动态给注解属性参数赋值
场景: 最近做了一个系统,使用Elasticsearch做了全文搜索,系统分为开发环境和正式环境,正式环境供公司内部使用,因为服务器资源不太充裕,决定开发环境和正式环境共用一个Elasticsearc ...
- java 分布式事务_Java核心知识 Spring原理十五 JPA 原理
1. 事务 事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity ).一致性 ( Consistency ).隔离性 ( Isolation ) 和持久性 ( Dur ...
- java 复制对象_Java核心知识 基础七 JAVA 复制
将一个对象的引用复制给另外一个对象,一共有三种方式.第一种方式是直接赋值,第二种方式 是浅拷贝,第三种是深拷贝.所以大家知道了哈,这三种概念实际上都是为了拷贝对象. 1. 直接赋值复制 直接赋值.在 ...
最新文章
- Nature Genetics:微生物如何适应植物的?(articles)
- 阅读笔记一——java高并发的性能优化
- 栅格数据的像素值保存问题
- Py之matplotlib.pyplot:matplotlib.pyplot的plt.legend函数的简介、使用方法之详细攻略
- VUE2.x的浏览器兼容情况汇总
- 微型计算机文献,微型计算机控制系统期刊文章参考文献 哪里有微型计算机控制系统参考文献...
- mysql中什么是选择引擎_Mysql 应该选择什么引擎
- css行内元素和块级元素
- 初学C语言 输出图形
- js统计页面刷新次数
- 网站被封了要换服务器吗,网站被惩罚或被封该怎么办?
- 二元非洲秃鹫优化算法附Matlab代码
- android10管理权限,Android 权限管理
- 机器学习算法(二十五):KD树详解及KD树最近邻算法
- 安装Robo 3T(Robomongo)MongoDB可视化工具
- 《CLR via C#》读书笔记---06 类型和成员基础
- 使用webflow的感觉
- Python 3.10 尝鲜
- HSQLDB基本认识
- Jenkins中Changelog插件使用
热门文章
- centos6.5 yum安装php5.5,mysql5.5.46 ,aphche 2.2.15
- 软中断和tasklet
- Unable to resolve dependency for ':app@debug/compileClasspath'
- 【开源资讯】开源文档管理系统 Wizard 1.2.5 发布
- mysql视图的更新 条件_MySQL进阶16 - 视图的创建/修改/删除/更新--可更新性的不适用条件...
- 最大弹窗_你不在意的小弹窗,为什么总是出现问题?
- grdraw用法 lisp_AutoCAD 2000 Visual LISP开发
- python 条件查询_Python SQLAlchemy 不确定条件查询
- 导航猫连接Oracle
- concurrenthashmap获取不到_面试必问的ConcurrentHashMap