Java学习笔记--JDK动态代理
1.JDK动态代理
JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例。JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标的代码,动态将横切逻辑和业务逻辑编织在一起。而Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
通过使用动态代理,可以在运行时动态创建出同时实现多个Java接口的相关代理类及其对象实例。当客户代码通过这些被代理的接口来访问其中的方法时,相关的调用信息就会被传递给代理中的一个特殊对象进行处理,处理的结果作为方法调用的结果返回。客户代码看到的只是接口,具体的逻辑被封装在代理的实现中。
动态代理机制的强大之处在于可以在运行时动态实现多个接口,而不需要在源代码中通过inplements关键词来声明。同时,动态代理把对接口中的方法调用的处理逻辑交给开发人员,让开发人员可以灵活处理。通过动态代理可以实现面向对象编程(AOP)中的常见的方法拦截功能。
2.基本使用方式
使用动态代理时只需要理解两个要素即可:第一个是要代理的接口,另外一个是处理接口方法调用的java.lang.reflect.InvocationHandler。动态代理只支持对接口提供代理,一般的Java类是不行的。如果要代理的接口不是公开的,那么被代理的接口和创建动态代理的代码必须在同一个包中。在创建动态处理的时候,需要提供InvocationHandler接口的实现,以处理实际的调用。在进行处理的时候可以得到表示实际调用方法的Method对象和调用的实际参数列表。
InvocationHandler接口的实现类的示例
public class LoggingInvocationHandler implements InvocationHandler{
private static final Logger logger = Logger.getLogger(LoggingInvocationHandler.class);
private Object target;
public LoggingInvocationHandler(Object obj){
this.target = obj;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
logger.log(Level.Info + "调用方法" + method.getName() + ":参数为" + Arrays.deepToString(args));
return method.invoke(target,args);
}
}
创建和使用动态代理的示例
public static void useProxy(){
String str = "Hello World";
LoggingInvocationHandler handler = new LoggerInvocationHandler(str);
ClassLoaser cl = SimpleProxy.class.getClassLoader();
Comparable obj = (Comparable)Proxy.newProxyInstance(cl,new Class[]{Comparable},handler);
obj.comparedTo("Good");
}
代码说明:
创建动态代理时需要一个InvocationHandler接口的实现,这是使用的的是上面的LoggingInvocationHandler类的实例。动态代理的创建是由java.lang.reflect.Proxy类的静态方法newProxyInstance来完成的。创建时需要提供类加载器实例、被代理的接口列表以及InvocationHandler接口的实现。在创建完成之后,需要通过类型转换把代理对象转换成被代理的某个接口来使用。
虽然LoggingInvocationHandler类只是简单地记录了日志,并没有改变方法的实际执行,但是实际上,在InvocationHandler接口的invoke方法中可以实现各种各样复杂的逻辑。比如对实际调用参数进行转换,或者是改变实际调用的方法,还可以对调用的返回结果进行修改。开发人员可以自己的需要,添加感兴趣的业务逻辑。这实际上就是AOP中常用的方法拦截,即拦截一个方法调用,以在其上附加所需的业务逻辑。InvocationHandler很适合于封装一些横切(cross-cutting)的代码逻辑,包括日志、参数检查与校验、异常处理和返回值归一化等。
一般来说,在创建一个动态代理的InvocationHandler实例的时候,需要把原始的方法调用的接受者对象也传进去,以方便执行原始的方法调用。这可以在创建InvocationHandler的时候,通过构造方法来传递。在大多数情况下,代理对象只会实现一个Java接口。对于这种情况,可以结合泛型来开发一个通用的工厂方法,以创建代理对象。
为任何接口及其实现类创建代理的工厂方法
public static <T>T makeProxy(Class<T> clazz,final T target,InovcationHandler handler){
ClassLoader classLoader = target.getClass().getClassLoader();
return (T) Proxy.newProxyInstance(classLoader,new Class<?>[]{clazz},handler)
}
Java学习笔记--JDK动态代理的更多相关文章
- Java学习笔记--Cglib动态代理
CGLib动态代理 使用JDK创建代理有一个限制,即它只能为接口创建代理实例,这一点可以从Proxy的接口方法newProxyInstance(ClassLoader loader,Class[] i ...
- AOP学习心得&jdk动态代理与cglib比较
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...
- Java中的JDK动态代理
所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户. 在日常生活中,就拿买火 ...
- Java设计模式之JDK动态代理原理
动态代理核心源码实现public Object getProxy() { //jdk 动态代理的使用方式 return Proxy.newProxyInstance( this.getClass(). ...
- Java学习笔记14--动态代理
InvocationHandler接口 public interface InvocationHandler{ public Object invoke(Object proxy,Method met ...
- Java 反射之JDK动态代理
Proxy提供用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类.如果我们在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类:如果需要为一个或多个接口动态的 ...
- 8.3(java学习笔记)动态编译(DynamicCompiler)与动态运行(DynamicRun)
一.动态编译 简单的说就是在运行一个java程序的过程中,可以通过一些API来编译其他的Java文件. 下面主要说动态编译的实现: 1.获取java编译编译器 2.运行编译器(须指定编译文件) 获取编 ...
- 【JVM学习笔记】动态代理
基于JDK的动态代理例子如下 接口 Subject public interface Subject { public abstract void request(); } 实现类RealSubjec ...
- [java学习笔记]JDK的安装和环境变量的配置
1.JDK的下载和安装 jdk(java development kit)是java提供给我们的一套java开发工具,它必运行在JVM(java虚拟机)上,java语言的跨平台性就是利用java运行在 ...
随机推荐
- ABP默认生成数据库结构
数据库设计文档 -- MyFirstABP 数据库设计文档 数据库名:MyFirstABP 序号 表名 说明 1 AbpFeatures 2 AbpEditions 3 AbpLanguage ...
- Python NumPy学习总结
一.NumPy简介 其官网是:http://www.numpy.org/ NumPy是Python语言的一个扩充程序库.支持高级大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库.Num ...
- C语言指针基本操作
C语言指针基本操作 指针 指针介绍 如果说C语言最有魅力的地方在哪,那么毋庸置疑,非指针莫属了. 众所周知,C语言中每个变量都有一个内存地址,可以通过&进行访问.指针是一个变量,它的值是一个 ...
- macOS 系统 .DS_Store 文件详解
.DS_Store 文件 .DS_Store 是 Finder 用来存储这个文件夹的显示属性的:比如文件图标的摆放位置. 显示/隐藏 Mac 隐藏文件 显示:defaults write com.ap ...
- IdentityServer4关于多客户端和API的最佳实践【含多类型客户端和API资源,以及客户端分组实践】【下】
经过前两篇文章你已经知道了关于服务器搭建和客户端接入相关的基本资料,本文主要讲述整个授权系统所服务的对象,以ProtectApi资源为演示 目标: 1)实现多资源服务器针对请求的token校验,接入I ...
- [Linux] Linux Shell查找文件
#!/bin/bash # 查找当前目录中所有大于1mb的文件,把文件名写到文本文件中,统计个数 # # find命令,参数:路径地址,命令参数,-size n (查找长度为n的文件) -type f ...
- 怎样删除C/C++代码中的所有注释?浅谈状态机的编程思想
K&R习题1-23中,要求“编写一个程序,删除C语言程序中所有的注释语句.要正确处理带引号的字符串与字符常量.在C语言中,注释不允许嵌套”. 如果不考虑字符常量和字符串常量,问题确实很简单.只 ...
- Python十讲 - 第一讲:从零开始学Python
之后慢慢添加... Python语言的背景知识
- linux学习笔记-目录相关知识
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! linux的目录结构及作用是根据fhs标准定制的,以下列出一些常用的目录的作用,以及fhs官方网站的连接 FHS官方网站的连接: ...
- postgresql-10.1-3-windows-x64 安装之后,起动pgAdmin 4问题(win10)
运行pgAdmin出现”pgAdmin 4 the application server could not be contant“ 窗口. 参考:https://stackoverflow.com ...