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学习笔记--动态代理的更多相关文章

  1. Java学习笔记——动态代理

    所谓动态,也就是说这个东西是可变的,或者说不是一生下来就有的.提到动态就不得不说静态,静态代理,个人觉得是指一个代理在程序中是事先写好的,不能变的,就像上一篇"Java学习笔记——RMI&q ...

  2. Java学习之动态代理篇

    Java学习之动态代理篇 0x00 前言 在后面的漏洞研究的学习中,必须要会的几个知识点.反射机制和动态代理机制.至于反射的前面已经讲到过了,这里就不做更多的赘述了. 0x01 动态代理 这里先来讲一 ...

  3. java学习之动态代理模式

    package com.gh.dynaproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Metho ...

  4. JAVA学习之动态代理

    JDK1.6中的动态代理 在Java中Java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成一个动态代理对象.JDK提供 ...

  5. Mybatis进阶学习笔记——动态代理方式开发Dao接口、Dao层(推荐第二种)

    1.原始方法开发Dao Dao接口 package cn.sm1234.dao; import java.util.List; import cn.sm1234.domain.Customer; pu ...

  6. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  7. Java学习笔记--JDK动态代理

    1.JDK动态代理     JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和 ...

  8. java学习笔记(中级篇)—JDK动态代理

    一.什么是代理模式 相信大家都知道代理商这个概念,在商业中,代理商无处不在.假设你要去买东西,你不可能去找真正的厂家去买,也不可能直接跟厂家提出需求,代理商就是这中间的一桥梁,连接买家和厂商.你要买或 ...

  9. Java笔记--动态代理

    Java动态代理 1.概念 代理: 有时我们并不想直接访问对象A,或者不能直接访问对象A.而是通过访问一个中间对象B,让中间对象B去访问A.这种方式就称为代理. 这里的对象A所属的类就为委托类,或者被 ...

随机推荐

  1. 史上最全的njRAT通信协议分析

    Njrat,又称Bladabindi,该木马家族使用.NET框架编写,是一个典型的RAT类程序,通过控制端可以操作受控端的文件.进程.服务.注册表内容,也可以盗取受控端的浏览器的保存的密码信息等内容. ...

  2. linux下MongoDB客户端shell基本操作

    MongoDB 是一款NoSql数据库,没有固定的模式,即同一个集合中的不同文档结构可以不同,如:第一条记录{name:”xiaoming”},第二条记录:{name:”xiaoli”,age:15} ...

  3. springmvc缓存和mybatis缓存

    首先要有一个搭建好的ssm框架,笔者使用的是基于maven搭建的ssm框架. 加入springmvc缓存: 导入相关依赖包: <dependency> <groupId>org ...

  4. Python标准库--Scope

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 1 模块简介 你一定在很多计算机科学课程上听说过作用域.它很重要, ...

  5. Linux 下按时间顺序批量删除文件

    ls -lrt| awk '{print $9}'| head -n 10 | xargs rm -rf 1.文件按时间排序: 2.获取文件名字: 3.取前10个文件 4.删除文件

  6. 微信小程序开发之获取openid及用户信息

    1. 获取openid 1.1 获取code 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的会话密钥(session_key).用户数据的加解 ...

  7. 《高性能javascript》 --- in case of odd number of items(奇怪的条目的数量)

    不知道是做着故意放的还是什么原因.总之运行后就会出现问题(奇怪的条目的数量) function merge(left, right){ var result = []; while (left.len ...

  8. linux通配符与正则表达式

    通配符   *  任意字符,可重复多次     ? 任意字符,重复一次     [] 代表一个字符 举例: [a,b,c] 表示abc中任意一个 通配符的作用是用来匹配文件名的 正则表达式 正则表达式 ...

  9. 常用统计分析 SQL 在 AWK 中的实现(转)

    转自:http://my.oschina.net/leejun2005/blog/100710 最近有需求需要本地处理一些临时的数据,用做统计分析.如果单纯的 MYSQL 也能实现, 不过一堆临时数据 ...

  10. GPU编程--kernels(2)

    "如何区分不同的数据单位单位呢?" "如何确定程序是在CPU端执行,还是GPU端执行呢?" "如何确定要调用的GPU线程数呢?" 下面举一个 ...