`
esperanza
  • 浏览: 181450 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 动态代理 proxy InvocationHandler

阅读更多

一篇杂文,写到哪就说到哪。在一些框架中有所谓的截面(aop),这些应用主要就是使用了JAVA的动态代理机制。截面或者说是拦截器所做的事情就是把一些共同的功能代码进行了抽取,简化开发以及维护。比如说,某些业务需要记录日志,需要进行功能验证。

先把用到的代码做一些简单的说明:

Ø  ImasterBusiness:主业务接口

Ø  MasterBusiness:主业务接口的一个实现类

Ø  MasterBusinessIntercepter:你叫拦截器也好,叫截面也好的一个类

Ø  MasterBusinessHander:处理器

Ø  MasterBusinessProxy:静态代理类

1.    静态代理

代理模式主要就是为了隐藏真实的业务主体,来达到一种封装的效果。静态代理模式是最简单的一种,说白了就是为每一个真实的业务主体都手动创建一个代理类。先看下面的代码

l   业务接口:

public interface IMasterBusiness {

    public void moreMoney();

}

l   真实业务主体

public class MasterBusiness implements IMasterBusiness {

    /* (non-Javadoc)

     * @see test.IMasterBusiness#moreMoney()

     */

    @Override

    public void moreMoney() {

        System.out.println("股票飘红!");

    }

}

l  代理类

public class MasterBusinessProxy implements IMasterBusiness{

    private IMasterBusiness imb;

   

    public MasterBusinessProxy(IMasterBusiness imb){

        this.imb = imb;

    }

   

    @Override

    public void moreMoney() {

        buy();

        imb.moreMoney();

        sale();

    }

    //buy,sale就是一些共同的功能代码,例如记录日志,功能验证等

    private void buy(){

        System.out.println("抄底");

    }

   

    private void sale(){

        System.out.println("高抛");

    }  

}

l  使用代理:

    public static void main(String[] args) {

        IMasterBusiness imb = new MasterBusiness();

        IMasterBusiness imbp = new MasterBusinessProxy(imb);

        imbp.moreMoney();

    }

l  运行结果:

抄底

股票飘红!

高抛

静态代理有一个问题就是需要我们手动创建代理类,如果业务方法不止一个,那么就要在每个业务方法中都加入buy()以及sale()方法。如果业务类不止一个,我们就要分别创建代理类。代码量增大,也为之后的维护增加了难度。解决的办法就是动态代理模式

动态代理模式

动态代理需要引用java中的Proxy类以及InvocationHandler接口。先把实现代码贴上

l  处理器

public class MasterBusinessHander implements InvocationHandler {

    //被代理的对象

    private Object masterBusinee;

    //拦截器

    private MasterBusinessIntercepter intercepter = new MasterBusinessIntercepter();

   

    public MasterBusinessHander(Object masterBusinee){

        this.masterBusinee = masterBusinee;

    }

 

    /* (non-Javadoc)

     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])

     * proxy:代理类

     * method:要调用的业务方法

     * args:也无方法的参数

     */

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object result;

        if(method.getName().equals("moreMoney")){

            intercepter.buy();

            result = method.invoke(masterBusinee, args);

            intercepter.sale();

        }else{

            result = method.invoke(masterBusinee, args);

        }

        return result;

    }

}

l  调用:

public static void main(String[] args) throws Exception {

        //创建一个调用器

        MasterBusinessHander hander = new MasterBusinessHander(new MasterBusiness());

        //拆分生成代理的步骤,方便后面的介绍

        Class<?> mbClass = Proxy.getProxyClass(MasterBusiness.class.getClassLoader(), MasterBusiness.class.getInterfaces());

        Constructor<?> constructor =  mbClass.getConstructor(new Class[]{InvocationHandler.class});

        Object obj =  constructor.newInstance(hander);

        if(obj instanceof IMasterBusiness){

            IMasterBusiness mb = (IMasterBusiness)obj;

            mb.moreMoney();

        }else{

            System.out.println("代理失败");

        }

    }

Proxy

Java 动态代理机制的主类,提供了2个静态方法来生成指定接口的代理类或者对象

//获取指定接口的动态代理类的类对象

static Class getProxyClass(ClassLoader loader, Class[] interfaces)

//生成动态代理类实例

static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

InvocationHandler

调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行

Object invoke(Object proxy, Method method, Object[] args)

拆分动态代理对象创建过程

1.          首先是new 一个InvocationHandler的实现类对象

new MasterBusinessHander(new MasterBusiness())

需要为调用处理器指定一个真实的业务对象,我们调用代理类的方法最终还是要调用到真实业务对象的方法,就是我们在这里提供的业务对象。

2.          根据指定的接口生成一个代理类对象

Proxy.getProxyClass(MasterBusiness.class.getClassLoader(), MasterBusiness.class.getInterfaces());

getProxyClass这个方法里会对接口数组进行一些验证,而且会把创建的代理对象类缓存到一个map(暂称为proxymap)中,类加载器作为proxymapkeyproxymapvalue又是一个map(暂称为valuemap)valuemapkey是接口数组生产的一个对象,value就是我们创建的代理类对象。这些可以看看Proxy的代码。

3.          获取代理类的构造器

mbClass.getConstructor(new Class[]{InvocationHandler.class})

 我之前一直没有弄明白这个mbClass到底是一个什么样的类,看到下面这张图就可以看得很明白了。$ProxyN就是我们生产的代理类($以及NProxy定义的一个明白规则),这个类实现业务接口A,B,X,同时继承了Proxy类。在Proxy类中定义了一个protect访问权限的构造器

protected Proxy(InvocationHandler h) {

    this.h = h;

}

4.          通过构造函数对象创建动态代理类实例

constructor.newInstance(hander);

在创建代理对象的过程中用到了很多反射方面的知识。

待解决的问题

查看Proxy的源码,生成代理类的代码如下:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces);

try {

    // 动态地定义新生成的代理类

    proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);

} catch (ClassFormatError e) {

    throw new IllegalArgumentException(e.toString());

}

sun.misc.ProxyGenerator没有公开代码,proxy到底如何调用处理器InvocationHandler我们就无法得知了,一个牛人给出了一个推演

// 假设代理类为 SimulatorProxy, 其类声明将如下

final public class SimulatorProxy implements businessInterface {    

    // 调用处理器对象的引用

    protected InvocationHandler handler;    

    // 以调用处理器为参数的构造函数

    public SimulatorProxy(InvocationHandler handler){

        this.handler = handler;

    }

    // 实现接口方法

    public void businessMethod(int arg1, long arg2, String arg3) throws ExceptionA, ExceptionB {

        // 第一步是获取方法的 Method 对象

        java.lang.reflect.Method method = null;

        try{

            method = businessInterface.class.getMethod(

                " businessMethod ", new Class[] {int.class, long.class, String.class} );

        } catch(Exception e) {

        }        

        // 第二步是调用 handler invoke 方法分派转发方法调用

        Object r = null;

        try {

// 对于原始类型参数需要进行装箱操作,高级别版本的JDK可以自动装箱

            r = handler.invoke(this, method,          

                new Object[] { arg1, arg2, arg3});

        }catch(Throwable e) {

        }

    }

}

这个推演的思路个人认为是正确的,也解释了我的疑惑

分享到:
评论

相关推荐

    Java动态代理实现 Proxy InvocationHandler

    JAVA动态代理,采用Proxy与InvocationHandler实现。

    java动态代理和反射

    java动态代理 public class HireProxy implements InvocationHandler { //被代理的真实角色 private Object obj; public HireProxy(Object obj) { super(); this.obj = obj; } //第二个参数method,被...

    java动态代理(3)

    Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: (1) Interface InvocationHandler (2) Proxy:该类即为动态代理类,

    java动态代理(2)

    Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: (1) Interface InvocationHandler (2) Proxy:该类即为动态代理类,

    java实现Proxy例子

    我自己用eclipse写的java代码,可以直接用eclipse导入,也可以直接用java -jar proxy_sample.jar执行 代码量很小,尽量通过注释进行说明 本例实现了InvocationHandler接口,代码具有典型性 在研究代理模式(Proxy...

    java静态代理和动态代理详解

    Java中提供了一个java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。代理类在运行时会根据被代理接口自动生成,并且可以通过InvocationHandler接口对方法进行增强。

    java动态代理(1)

    Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类 (1)Interface InvocationHandler(2)Proxy

    Java动态代理1

    动态代理的实现:一:简单的动态代理实现:(1) 实现InvocationHandler接口(2) Proxy.newInstance()创建代理例:二:实际案

    使用Java动态代理实现一个简单的网络请求拦截器.txt

    这个代码实现了一个简单的网络请求拦截器,使用了Java的动态代理机制。在这个例子中,我们创建了一个`HttpRequestInterceptor`类来实现`InvocationHandler`接口,并在`invoke()`方法中实现了对目标方法的拦截操作。...

    Java面向对象系列[v1.0.0][使用反射生成动态代理]

    在Java的java.lang.reflect包里有个Proxy类和一个InvocationHandler接口,通过使用他们可以生成JDK动态代理类或动态代理对象 使用Proxy和InvocationHandler创建动态代理 Proxy提供了用于创建动态代理类和代理对象的...

    JDK动态代理+JDK动态代理完整代码+JDK动态代理代码实现逻辑

    动态代理::在程序运行时,运用反射机制动态创建而成。 动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员...java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。

    Java的动态代理机制详解

     在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对...

    JDK的动态代理(powernode 文档)(源代码)

    JDK的动态代理(powernode 文档)(源代码) JDK的动态代理(powernode 文档) 一、动态代理 1.1JDK动态代理 1.1.1 proxy 1.1.2 InvocationHandler 1.1.3 创建一个Maven项目 1.1.4 导入Spring的相关依赖 1.1.5 修改...

    JDK动态代理(powernode CD2207 video)(教学视频+源代码)

    JDK动态代理(powernode CD2207 video)(教学视频+源代码) JDK动态代理(powernode CD2207 video) 一、动态代理 1.1JDK动态代理 1.1.1 proxy 1.1.2 InvocationHandler 1.1.3 创建一个Maven项目 1.1.4 导入Spring...

    AOP的实现机制

    Java在JDK1.3后引入的动态代理机制,使我们可以在运行期动态的创建代理类。使用动态代理实现AOP需要有四个角色:被代理的类,被代理类的接口,织入器,和InvocationHandler,而织入器使用接口反射机制生成一个代理类...

    demo:java生产项目常用的demo

    实现动态代理的InvocationHandler类重写invoke方法实现. 二.spring 1.spring ioc 1.1.spring容器 1.1.1.BeanFactory 常用实现类:DefaultListableBeanFactory 1.1.2.ApplicationContext 常用实现类:...

    java 实现AOP

     JDK1.2以后提供了动态代理的支持,程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行商业方法,在商业方法被...

    Java 高级特性.doc

    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Collection; import java.util.Vector; public class ProxyTest { public ...

    ProxyTest.zip

    Java动静态代理机制简介,尤其是动态代理,结合反射机制,为后续的java hook技术打下基础。动态代理需实现java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持。

    疯狂JAVA讲义

    第1章 Java概述 1 1.1 Java语言的发展简史 2 1.2 Java的竞争对手及各自优势 4 1.2.1 C#简介和优势 4 1.2.2 Ruby简介和优势 4 1.2.3 Python的简介和优势 5 1.3 Java程序运行机制 5 1.3.1 高级语言的运行机制 6...

Global site tag (gtag.js) - Google Analytics