java-代理模式及动态代理
代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在考虑到性能或安全等因素的情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

Proxy代理类:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
Target目标类:代理角色所代表的真实对象,是我们最终要引用的对象。
动态代理
假如要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色对应一个代理角色,假如大量使用会导致类的急剧膨胀;此外,假如事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
java动态类的实现主要通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。
Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现。
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
static InvocationHandler |
getInvocationHandler(Object proxy) 返回指定代理实例的调用处理程序。 |
static Class<?> |
getProxyClass(ClassLoader loader, Class<?>... interfaces)返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。 |
static boolean |
isProxyClass(Class<?> cl)当且仅当指定的类通过 getProxyClass 方法或newProxyInstance 方法动态生成为代理类时,返回 true。 |
static Object |
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。 |
- 参数:
loader- 定义代理类的类加载器interfaces- 代理类要实现的接口列表h- 指派方法调用的调用处理程序
InvocationHandler 是代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。
Object |
invoke(Object proxy, Method method, Object[] args) 在代理实例上处理方法调用并返回结果。 |
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数

根据自己理解画的动态代理原理图

示例代码
写一个动态代理,其内部可以实现 ArrayList 和HashMap中完全相同的功能,并可以计算每个方法运行的时间。
定义代理工具类,可以根据目标和建议的不同生成不同的代理类对象。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ProxyUtil {
//抽取方法,接收不同的目标和建议,返回一个代理
public static Object getProxy(final Object target,final Advice advice) {
/*参数:
定义代理类的类加载器
代理类要实现的接口列表
指派方法调用的调用处理程序*/
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){ public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
}
);
return proxy;
}
}
定义建议接口
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method);
void afterMethod(Method method);
}
自定义建议类实现建议接口
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
long beginTime = 0;
public void afterMethod(Method method) {
long endTime = System.currentTimeMillis();
System.out.println("["+method.getName() + "]耗时" + (endTime - beginTime)+"毫秒");
}
public void beforeMethod(Method method) {
beginTime = System.currentTimeMillis();
}
}
客户端测试
import java.util.*;
class TargetDemo
{
public static void main(String[] args)
{
//定义target
List<String> target = new ArrayList<String>();
//获取target的代理类对象
List proxy = (List)ProxyUtil.getProxy(target,new MyAdvice());
//代理类对象实现添加等方法
proxy.add("hello");
proxy.add("hehe");
proxy.add("hello");
System.out.println("size="+proxy.size());
for(Object tar : proxy){
System.out.println(tar);
} System.out.println("================"); Map<String,Integer> target1 = new HashMap<String,Integer>();
Map proxy1 = (Map)ProxyUtil.getProxy(target1,new MyAdvice());
proxy1.put("zhangsan1",21);
proxy1.put("zhangsan2",22);
proxy1.put("zhangsan2",22);
System.out.println("size="+proxy1.size());
Set<Map.Entry<String,Integer>> entrySet = proxy1.entrySet(); Iterator<Map.Entry<String,Integer>> it = entrySet.iterator(); while(it.hasNext())
{
Map.Entry<String,Integer> me = it.next();
String key = me.getKey();
Integer value = me.getValue(); System.out.println(key+"="+value);
}
}
}
运行结果:
---------- 运行 ----------
[add]耗时1毫秒
[add]耗时0毫秒
[add]耗时0毫秒
[size]耗时0毫秒
size=3
[iterator]耗时1毫秒
hello
hehe
hello
================
[put]耗时0毫秒
[put]耗时0毫秒
[put]耗时0毫秒
[size]耗时0毫秒
size=2
[entrySet]耗时0毫秒
zhangsan1=21
zhangsan2=22
输出完成 (耗时 0 秒) - 正常终止
java-代理模式及动态代理的更多相关文章
- (转)轻松学,Java 中的代理模式及动态代理
背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...
- Java设计模式-代理模式之动态代理(附源代码分析)
Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...
- Java代理模式之动态代理
动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件.代理角色和真实角色的联系在程序运行时确定! Java中有两种动态代理,一种是JDK自带的,另一种的CGL ...
- JAVA代理模式与动态代理模式
1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...
- Java的三种代理模式(Spring动态代理对象)
Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...
- java代理模式及动态代理类
1. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用 ...
- 代理模式-jdk动态代理
IDB package com.bjpowernode.proxy; /** * 代理类和目标类都必须使用同一个接口. */ public interface IDB { int insert(); ...
- 动态代理模式——JDK动态代理
今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理 ...
- 代理模式与动态代理之JDK实现和CGlib实现
静态代理 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 由业务实现类.业务代理类 两部分组成.业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截.过滤.预处理, ...
- Java 中的代理模式及动态代理
原文:https://blog.csdn.net/briblue/article/details/73928350
随机推荐
- 原生js arguments 用法
http://note.youdao.com/noteshare?id=fcd201e872e1ede16ce0057a1909f613
- jQuery Mobile 网格布局
jQuery Mobile 布局网格 jQuery Mobile 提供了一套基于 CSS 的列布局方案.不过,一般不推荐在移动设备上使用列布局,这是由于移动设备的屏幕宽度所限. 但是有时你需要定位更小 ...
- configparser配置文件操作
configparser 模块用于对配置操作 官方文档地址https://docs.python.org/3/library/configparser.html 导入configparser模块 i ...
- 【openresty】向lua代码中传递参数
前面介绍FormInputNginxModule模块时,明白了openresty如何获取post提交的数据. 然后,如果需要通过lua处理这些数据,需要把数据作为参数传递到lua中,lua获取了这些数 ...
- Shell基础-ech0,cat,history,alias,unalias,bash快捷键,wc,执行结果写入文件
1 系统所支持的shell存放于 /etc/shells 文件中,shell脚本的开头 #!/bing/bash 是指定使用的脚本类型 不能省略,省略之后有些文件可以执行,但容易出错 这行不是注释 2 ...
- 持续集成工具Jenkins学习总结
概述 持续集成(Continuous Integration,简称CI)是一种软件开发实践,团队开发人员每次都通过自动化的构建(编译.发布.自动化测试)来验证,从而尽早的发现集成错误.持续集成最大的优 ...
- pll及其modesim仿真
100mhz输入时钟,pll层40mhz和200zhm 进入quartus,建立工程,新建图形文件,导入pll模块,设定pll相关参数. 完成pll模块的建立,并生成pll.v文件 建立modes ...
- kendo chart label position 图表的值标签位置及显示模板
1.不显示0 seriesDefaults: { type: "column", labels: { visible: true, position:'' background: ...
- sql update多表联合更新
update tabA set PrintTag=c.dp_state from tabA a inner join tabB b on a.Code=b.design inner join tabC ...
- freeCodeCamp:Caesars Cipher
让上帝的归上帝,凯撒的归凯撒. 下面我们来介绍风靡全球的凯撒密码Caesar cipher,又叫移位密码. 移位密码也就是密码中的字母会按照指定的数量来做移位. 一个常见的案例就是ROT13密码,字母 ...