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. 从点击到呈现 — 详解一次HTTP请求

    一般来说,很多的参考资料上面都会说,http 是一个基于请求/响应的工作模式,然后画出一张浏览器和服务器的 b/s 结构图,再画上两个箭头,表示请求和响应,应该说这么解释是易懂的,一般也是够清楚的,但 ...

  2. poj2185 Milking Grid

    题目链接:http://poj.org/problem?id=2185 这道题我看了好久,最后是通过参考kuangbin的博客才写出来的 感觉next数组的应用自己还是掌握的不够深入 这道题其实就是先 ...

  3. 谈谈我的session跨域处理方法

    情景:公司的一个网站有一个模块(测试模块)需要单独用另外的一个域名(www.btest.com)去访问,即网站需要用两个不同的域名去访问,如首页(www.abc.com)和测试模块(www.xyz.c ...

  4. Java 7 Fork/Join 框架

    在 Java7引入的诸多新特性中,Fork/Join 框架无疑是重要的一项.JSR166旨在标准化一个实质上可扩展的框架,以将并行计算的通用工具类组织成一个类似java.util中Collection ...

  5. ZooKeeper实践:(1)配置管理

    一. 前言     配置是每个程序不可或缺的一部分,配置有多重方式:xml.ini.property.database等等,从最初的单机环境到现在的分布式环境. 1. 以文件的格式存储配置,修改任何都 ...

  6. struts2.1.6教程三、在Action获取Scope对象

    引言:在前面的Action操作中,关键就是Action中的exectue方法,但是此方法并没有request.session.application等对象作为参数,自然就不能利用这些对象来操作.下面我 ...

  7. Android框架式编程之BufferKnife

    配置 compile 'com.jakewharton:butterknife:(insert latest version)' annotationProcessor 'com.jakewharto ...

  8. Java计算1-100的和(要求尽量考虑代码优化)

    1.递归算法 public static void main(String[] args) { System.out.println(add(1)); } private static int add ...

  9. 移动端页面 iPhone + Safari 页面调试 之 正确查看网络请求的姿势

    如题 本文主要将 Safari + iPhone 前端开发调试  之 正确查看网络请求的 姿势 惯例 说下问题场景: 早知道safari(Mac) + iPhone 调试的方便 能解决很多日常调试问题 ...

  10. ftp服务器可以连接但不能传输数据(proftpd)

    问题:在客户端连接FTP服务器(proftpd)时可以正常连接,但是无法正常传输数据 ftp> ls530 Please login with USER and PASSPassive mode ...