关于java动态代理模式
1. 动态代理
- 动态代理就是通过代理类是代理类与相关接口不直接发生联系,而在运行期(Runtime)实现动态关联。
- 动态代理主要用到java.lang.reflect包中的两个类,InvocationHandler接口和Proxy类。
- 动态代理相较于静态代理最大的不同就是:动态代理的代理类不需要手动生成,该代理类是在运行期间动态生成的,这个动态生成的代理类已经实现代理对象的相关接口(Interface)。在生成代理类的同时,必须提供一个handler,这个handler有InvocationHandler提供,同时用来接管实际的工作。
2. InvocationHandler接口
(1)接口声明:
public interface InvocationHandler
- 每一个动态代理类都必须实现InvocationHandler接口,InvocationHandler是代理实例(代理的真实对象),的调用处理程序实现的接口,当通过代理实例调用一个方法的时候,该方法的调用就会指派到它调用处理程序(InvocationHandler接口)的 invoke 方法。
(2)invoke方法声明:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
参数意义:Object proxy: 指代所代理的真实对象,也就是真实对象的代理
Method method: 指代所调用的真实对象的某个方法的Method对象
Object[] args: 指代所代理的真实对象某个方法的参数
3. Proxy类
(1)类声明:
public class Proxy extends Object implements Serializable
- Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类(JDK).
- Proxy类根据已经提供的相关接口和被代理的类就可以利用反射机制得到实现的方法,根据Proxy类的newProxyInstance(...)方法生成代理类。
(2)newProxyInstance方法声明:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
参数意义:
ClassLoader loader: 类加载器,就是把动态生成的代理类的字节码文件加载到JVM虚拟机中,一般使用被代理类的类加载器
Class<?>[] interfaces:为代理对象提供的接口,就是被代理类实现的接口
InvocationHandler h: 当代理对象调用方法的时候关联到InvocationHandler对象上,也就是前面说的*调用处理程序*(有待更深理解)
4.动态代理模式实现
package com.manu;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TestTrendsProxy {
public static void main(String[] args) {
Subject man = new Man();
Proxy p = new Proxy(man);
//通过java.lang.reflect.newProxyInstance(...)方法获得真实对象的代理对象
Subject subject = (Subject)java.lang.reflect.Proxy.newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(), p);
//通过代理对象调用真实对象相关接口中实现的方法,这个时候就会跳转到这个代理对象所关联的handler的invoke()方法去执行
subject.shopping();
//获得真实对象的代理对象所对应的Class对象的名称,用字符串表示
System.out.println(subject.getClass().getName());
//调用处理程序的表示
InvocationHandler handler = java.lang.reflect.Proxy.getInvocationHandler(subject);
System.out.println(handler);
}
}
//被代理人和代理人要执行的动作
interface Subject{
void shopping();
}
//被代理类
class Man implements Subject{
private String name="Tom";
public void shopping() {
System.out.println(name+"要去买东西...");
}
}
//代理类
class Proxy implements InvocationHandler{
private Object target;//要代理的真实对象
public Proxy(Subject target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy:"+proxy.getClass().getName());
System.out.println("购买之前的评估工作...");
method.invoke(target, args);
System.out.println("购买之后的满意度调查...");
return null;
}
}
下面是运行结果:
运行结果:
proxy:com.manu.$Proxy0
购买之前的评估工作...
Tom要去买东西...
购买之后的满意度调查...
com.manu.$Proxy0
com.manu.Proxy@6bc7c054
运行结果中出现的$Proxy0是subject.getClass().getName())得到的,返回的是类的名称,这是在运行时动态创建的,命名方式貌似是$Proxy+编号构成。整个代理过程主要体现在一个handler上。
如果选择关注微信公众号:jzman-blog,一起交流学习!
关于java动态代理模式的更多相关文章
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- java动态代理模式
java动态代理机制详解 Spring的核心AOP的原理就是java的动态代理机制. 在java的动态代理机制中,有两个重要的类或接口: 1.InvocationHandler(Interface): ...
- Java动态代理模式浅析
Java代理设计模式 - 静态代理 Java中的动态代理 - 调用处理器 代理设计模式的UML图: 我将首先介绍Java中的各种代理实现方法 Java代理设计模式 - 静态代理 这个例子非常简单,只有 ...
- java 动态代理模式(jdk和cglib)
package proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Met ...
- Java 动态代理模式浅析
目录 Java代理设计模式 - 静态代理 静态代理的优点 静态代理的缺点 Java中的动态代理 - 调用处理器 主要笔记: 动态代理类的限制 代理设计模式的UML图: 我将首先介绍Java中的各种代理 ...
- JAVA代理模式与动态代理模式
1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...
- Java设计模式系列之动态代理模式(转载)
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...
- Java静态代理与动态代理模式的实现
前言: 在现实生活中,考虑以下的场景:小王打算要去租房,他相中了一个房子,准备去找房东洽谈相关事宜.但是房东他很忙,平时上班没时间,总找不到时间去找他,他也没办法.后来,房东想了一个办法,他找到 ...
- java jdk动态代理模式举例浅析
代理模式概述 代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色. java中常用的动态代理模式为jdk动态代理和c ...
随机推荐
- web前端 关于浏览器兼容的一些知识和问题解决
浏览器兼容 为什么产生浏览器兼容,浏览器兼容问题什么是浏览器兼容: 所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况. 浏览器兼容产生的原因: 因为不 ...
- Python-Requests库的安装和调用
#使用pip或者pip3安装requests库pip3 install requests #requests库:python #输入python进入命令行模式在cmd命令行中依次运行以下代码,或者直接 ...
- JavaScript的数组(一)
在JavaScript中,对象,数组,函数是最最常用的东东了,写完了对象和函数,最后来说说数组吧,提到数组,就只能想到,map,forEach啊,pop,push啊,当真是没有一点点的积累了?这么多年 ...
- Linux apache开启虚拟主机伪静态.htaccess
打开apache配置文件 /etc/httpd/conf/httpd.conf 查找“#LoadModule rewrite_module modules/mod_rewrite.so” 去掉前面的# ...
- django 从零开始 6 数据库模型增删改查
这些都是凭记忆写下的,有些会漏掉,在之后的笔记中会写 和flask query不同,django是使用objects进行一个查询 查询 单条记录 django 模型.bojects.get(查询的字段 ...
- 【猫狗数据集】使用预训练的resnet18模型
数据集下载地址: 链接:https://pan.baidu.com/s/1l1AnBgkAAEhh0vI5_loWKw提取码:2xq4 创建数据集:https://www.cnblogs.com/xi ...
- mongo复制数据库和表
1.使用工具Studio 3T for MongoDB 选择一个数据库中的Collections集合,然后按住 Ctrl+C 复制快捷键会弹出如下帮助框. 点击 Ctrl+V 粘贴快捷键,重命名一下复 ...
- 对时间进行操作 加减 XXX天
date:要操作的时间目标 days: 要加减的天数时间 addDate: function(date, days) { if (date == '') { return '' }; if (days ...
- 我在使用DriverManager时发现的问题
小白今天在连接数据库的时候,心里面突然想起之前有大佬说没有必要添加一条"com.mysql.jdbc.Driver",当时也实验了确实可行,但是这个可是驱动地址,难道是不用添加是根 ...
- 我用STM32MP1做了个疫情监控平台4—功能完善界面重新设计
目录 前言 界面展示 新增功能 API 接口说明 多个接口数据的获取和解析 FontAwesome字体图标库的使用 代码下载 系列教程 @ 前言 之前我用STM32MP1和Qt实现了疫情监控平台,系列 ...