`
esperanza
  • 浏览: 183336 次
  • 性别: 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 动态代理Proxy应用和底层源码分析.pdf

    ### Java 动态代理Proxy应用和底层源码分析 #### 一、Java动态代理简介 Java动态代理是一种在运行时动态生成代理类的技术,通过该技术可以为一个或多个接口生成一个实现类,该实现类可以拦截接口方法的调用,并...

    Java动态代理Proxy和cglib

    Java的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。这个主题将深入探讨这两个关键组件以及与之相关的CGLIB库。 ### 1. Java动态代理 #### 1.1 Proxy类 `Proxy`...

    java Proxy 动态代理

    在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类是用于创建一个代理对象,而InvocationHandler接口则定义了代理对象调用方法时的行为。 1. **...

    java动态代理实例

    在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。`Proxy`类用于创建代理对象,而`InvocationHandler`接口定义了处理代理对象方法调用的逻辑。 1. **...

    java动态代理demo

    `java.lang.reflect.Proxy` 类是用于创建动态代理对象的工厂类。我们需要使用`Proxy.newProxyInstance()`方法,传入类加载器、接口数组以及自定义的`InvocationHandler`实例,来生成代理对象。 5. **动态代理示例*...

    Java动态代理[动态类Proxy的使用]

    本文将深入探讨Java中的动态代理,特别是基于`java.lang.reflect.Proxy`类的使用。 首先,`java.lang.reflect.Proxy`是Java标准库中用于生成动态代理类的关键类。它允许我们创建一个新的接口实现类,而无需手动编写...

    java动态代理 经典文章(word 2007格式的)

    - `Java动态代理模式.docx`可能详细讲解了动态代理模式的原理和实现,包括如何创建代理对象和实现`InvocationHandler`。 - `动态代理详解.docx`则可能深入讨论了Java动态代理的细节,包括实际应用场景和常见问题。...

    Java动态代理两种实现方式

    JDK动态代理是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。Proxy类用于创建一个代理对象,而InvocationHandler接口定义了处理代理对象方法调用的逻辑。 #### 1. 创建...

    一个简单的java动态代理的实例

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,主要由`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口组成。在这个简单的Java动态代理实例中,我们将探讨如何利用这两个核心...

    java 动态代理 简单实例

    在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于生成代理对象,而`InvocationHandler`接口定义了代理对象的方法调用应该如何处理。 ...

    java动态代理机制

    在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。 1. **Proxy类**: `Proxy` 类是Java提供的一个内部类,它主要用于创建一个实现了指定一组接口的...

    Java动态代理helloworld

    Java中的动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。 1. **Proxy类**:Proxy是Java动态代理的核心类,它提供了创建动态代理对象的方法。代理对象是目标对象的...

    Java代理模式Java动态代理

    ### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...

    java InvocationHandler

    Java中的`InvocationHandler`接口是Java动态代理机制的核心组成部分,主要用在`java.lang.reflect`包下。这个接口提供了一种方法,使得我们可以在运行时创建具有特定行为的代理对象。这种行为通常体现在调用代理对象...

    Java 动态代理详解(学习资料)

    JDK 动态代理JDK 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。Proxy 类用于创建一个代理对象,而 InvocationHandler 接口则定义了代理对象的方法调用处理逻辑。...

    java proxy demo 代理类的运用demo

    Java代理分为静态代理和动态代理两种。静态代理是在编译时就已经确定代理类的实现,而动态代理则是在运行时根据接口生成代理类。我们这里主要讨论的是动态代理,它基于Java的`java.lang.reflect.Proxy`类和`java....

    Java动态代理ReflectProxyDemo

    首先,Java中的动态代理是通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现的。`Proxy`类用于创建一个代理对象,而`InvocationHandler`接口则定义了处理代理对象的方法调用的逻辑...

    Java动态代理案例演示代码

    Java动态代理基于JDK的`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。`Proxy`类用于创建代理类实例,而`InvocationHandler`接口定义了处理代理对象的方法调用的逻辑。 ### 2. 创建代理...

Global site tag (gtag.js) - Google Analytics