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. 跟着刚哥学习Spring框架--创建HelloWorld项目(一)

    1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spri ...

  2. OC中的copy

    copy的概念 Copy的字面意思是"复制"."拷贝",是一个产生副本的过程 对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容,常 ...

  3. linux-redhat-iso 下载

    http://archive.download.redhat.com/pub/redhat/linux/9/en/iso/i386/ http://www.jb51.net/do/plus/downl ...

  4. 工具类总结---(三)---MD5加密

    用于给文件名等进行MD5加密: import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; / ...

  5. Android ec环境配置

    ec环境配置 1.0概述 鉴于很多同事,或者新从事android开发,虽然会做android的开发,但是会遇见一些最基本的环境搭建问题,本文仅作为(win7 64位系统)eclipse中集成andro ...

  6. 【PHP】文件写入和读取详解

    文章提纲: 一.实现文件读取和写入的基本思路 二.使用fopen方法打开文件 三.文件读取和文件写入操作 四.使用fclose方法关闭文件 五.文件指针的移动 六.Windows和UNIX下的回车和换 ...

  7. MHA在线切换的步骤及原理

    在日常工作中,会碰到如下的场景,如mysql数据库升级,主服务器硬件升级等,这个时候就需要将写操作切换到另外一台服务器上,那么如何进行在线切换呢?同时,要求切换过程短,对业务的影响比较小. MHA就提 ...

  8. AngularJs之初

    很久以前就听人说起angularjs,但一直都没有深入了解过.直到最近才在自己心里有了一个准确的定义.和相濡以沫多年的函数库JQuery相比,angular更像一个框架.对,就是一个框架,相比之下的话 ...

  9. elasticsearch系列(四)部署

    本文采用tar包的方式部署es 准备jdk8的环境 5.4.0的es依赖jdk8及以上版本 下载linux版的jdk jdk-8u121-linux-x64.tar.gz tar -zvxf jdk- ...

  10. 一个html页面传入参数到另一个html页面用js获取方法

    没错使用以下函数就能够完整的获取到路径里的你想要的参数:function getURLParameter(name) { return decodeURIComponent((new RegExp(' ...