代理模式

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

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-代理模式及动态代理的更多相关文章

  1. (转)轻松学,Java 中的代理模式及动态代理

    背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...

  2. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. Java代理模式之动态代理

    动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件.代理角色和真实角色的联系在程序运行时确定! Java中有两种动态代理,一种是JDK自带的,另一种的CGL ...

  4. JAVA代理模式与动态代理模式

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...

  5. Java的三种代理模式(Spring动态代理对象)

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  6. java代理模式及动态代理类

     1.      代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用 ...

  7. 代理模式-jdk动态代理

    IDB package com.bjpowernode.proxy; /** * 代理类和目标类都必须使用同一个接口. */ public interface IDB { int insert(); ...

  8. 动态代理模式——JDK动态代理

    今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理 ...

  9. 代理模式与动态代理之JDK实现和CGlib实现

    静态代理 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 由业务实现类.业务代理类 两部分组成.业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截.过滤.预处理, ...

  10. Java 中的代理模式及动态代理

    原文:https://blog.csdn.net/briblue/article/details/73928350

随机推荐

  1. Chrome & Linux font

    1 $ sudo apt-get install texlive-full # 较大 2 $ mkdir -p ~/.fonts 3 下载这个win7字体包解压后放到~/.fonts下 4 $ sud ...

  2. LTS

    LTS(light-task-scheduler)主要用于解决分布式任务调度问题,支持实时任务,定时任务和Cron任务.有较好的伸缩性,扩展性,健壮稳定性而被多家公司使用. 1. 支持分布式,解决多点 ...

  3. Servlet过滤器(详询请加qq:2085920154)

    1.1  过滤器简介 过滤器是向Web应用程序的请求和响应处理添加功能的Web服务组件.在Servlet处理用户输入的请求之前,过滤器可以访问该请求.在将Web响应发送给用户之前,过滤器还可以访问该响 ...

  4. 总结下用Vue.js和webpack遇到的问题

    这段时间用vue.js+webpack做一个单页应用的demo,第一次尝试模块化,技术水平有限,学习不够深入,总是遇到各种问题,所谓前事不忘后事之师,so记录下. 1.ES6匿名函数里面this值 结 ...

  5. vim段替换

    文件中有很多字段: dd ssdf df aaa="100" dd ssdf df aaa="200" asdf sdf sdf aaa="700&q ...

  6. XE3随笔16:将字符串转换成 UTF8 编码的函数

    这种转换一般用于网页地址; 我不知道 Delphi 是不是有现成的函数, 用到了就写了一个. //函数: function ToUTF8Encode(str: string): string; var ...

  7. 操作系统win2003 x64的,安装OFFICE2003后,DCOM服务找不到 WORD应用程序服务

    打开注册表,找到以下健值 HKEY_CLASSES_ROOT\AppID\{00020906-0000-0000-C000-000000000046} HKEY_CLASSES_ROOT\CLSID\ ...

  8. 一个login

    login 1.获取提交表单,保存到变量中.2.判断用户密码是否正确,利用Model类.3.验证用户是否激活.3.判断用户是否记住登录状态,是的话,将其用cookie和session分别保存.没有的话 ...

  9. CSS里常见的块级元素和行内元素

    根据CSS规范的规定,每一个网页元素都有一个display属性,用于确定该元素的类型,每一个元素都有默认的display属性值,比如div元素,它的默认display属性值为“block”,成为“块级 ...

  10. 流媒体协议介绍(rtp/rtcp/rtsp/rtmp/mms/hls)

    RTP           参考文档 RFC3550/RFC3551 Real-time Transport Protocol)是用于Internet上针对多媒体数据流的一种传输层协议.RTP协议详细 ...