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

JDK反射之JDK动态proxy

    博客分类:
  • java
 
阅读更多

JDK动态代理

 

JDK 动态代理是 java 反射的一个重要特性。它在某种方面为 java 提供了动态性的特性,给应用带来了无限的空间。大名鼎鼎的 Hessian 、 Spring AOP 基于动态代理实现。本文将简单的介绍 JDK 动态代理使用。

 

1.关于代理模式

 

代理模式是非常常用的一种设计模式,在我们的应用中经常被使用。一般场景是,我们有一个现成的类,它的功能比较的完善了,但是还是存在某些欠缺,这个时候我们需要去扩展一些新的功能,但又不想去重造轮子,这个时候可以使用代理类来替代原来的目标类,通过组合的模式,增加一种为目标类增加一些额外的功能。

代理模式的类结构图一般如下:

 

 

 

 

图1:代理模式类结构图

 

 

 

 

 

图2:代理模式序列图

 

2.JDK 动态代理


所谓 JDK 动态代理就是在运行时动态生成红色的代理类的过程。和静态代理不一样的地方是静态代理在编译期就要完成代理类 的实现。那么动态代理是如何实现的呢?

根据下面的例子,一步一步来看。

假设有这样一个接口 Speak:

 

Java代码 复制代码 收藏代码
  1. package proxy;   
  2. public interface Speak {   
  3.     public void sayHello();   
  4. }  
package proxy;
public interface Speak {
    public void sayHello();
}

 
 

 

实现类 PeopleSpeak.

 

Java代码 复制代码 收藏代码
  1. package proxy;   
  2. public class PersonSpeak implements Speak {   
  3.     public void sayHello() {   
  4.         System.out.println("hello");   
  5.     }   
  6. }  
package proxy;
public class PersonSpeak implements Speak {
    public void sayHello() {
        System.out.println("hello");
    }
}

 
 

 

当我们去调用 PersonSpeak 的 sayHello 的时候,很显然是输出 hello 。现在我们需要通过动态代理在运行时动态的生成 Speak 的代理类,并在调用 sayHello 方法的前后做一些输出。完成类似 aop 的功能。

根据以上的思路,我们需要有一个 PersonSpeak 的代理类,它持了 PersonSpeak 的对象,这样就能很方便的完成这个任务。如果用静态代理实现显然是很简单,那么用动态代理如何实现呢?

这个时候我们可以使用 java 反射里的 Proxy 类。此类是 JDK 动态代理的核心类。 Proxy 类拥有一个在运行期动态创建类的功能。动态的去创建一个 Speak 的子类,同时该子类持有 PersonSpeak 类的一个实例,该子类的功能就是实现上述第一部分代理类的功能。

关于 java 反射的 Method 、 Field 、 Class 、 Construtor 等这里不做介绍,重点介绍 Proxy和 InvocationHandler 类。

Proxy和InvocationHandler 类简介

Proxy 类提供了非常重要的方法,该方法能够动态的生成几个接口的实现类。具体的实现过程由 ProxyGenerator 类来实现,这是比较低层的一个类,这里不做过多描述。同时该动态类需要持有一个实现了 InvocationHandler 接口的子类对象。 InvocationHandler 接口的子类对象是我们目标类的又一层代理。对于接口里面的每个方法实现,都是通过调用 InvocationHandler 接口的子类对象的反射调用。也就是说动态代理类实际上是 InvocationHandler 子类对象的一个代理。那么 InvocationHandler 子类对象有时我们目标类的代理。通过这样层层代理我们就能实现上述的功能了。这句话可能不是很好理解,但是确实就是这么实现的,也许通过下面的图就能更好的理解:

 

 

 

 

 

 

 

图3:JDK动态代理调用过程

 

可以从上图看出来, JDK 动态反射并不是那么简单的一层代理,而是通过层层代理,最终通过 Method 的反射来调用目标对象的方法,而 aop 的实现可以放在 InvocationHandler 的是实现类里。

那么根据上述关于动态代理的简介,要实现 PersonSpeak 的 aop ,需要做两件事情

1.       实现一个持有 Speak 对象的 InvocationHandler 子类,改子类通过 Mechod 反射调用 PersonSpeak 的方法,并在调用方法前后实现 aop 功能。

2.       实现一个能动态创建 Speak 子类的代理类工厂,改工厂能动态的创建 Speak 子类。

 

具体实现如下:

1.        SpeakInvocationHandler ( 实现 InvocationHandler 接口 )

可以看出该类的 invoke 方法实现 aop 的关键,所有方法都是通过 invoke 来调用, invoke 内部通过反射来调用目标对象 target ,同时在调用前后实现了 aop 。

Java代码 复制代码 收藏代码
  1.  package proxy;   
  2. import java.lang.reflect.InvocationHandler;   
  3. import java.lang.reflect.Method;   
  4. public class SpeakInvocationHandler implements InvocationHandler {   
  5.     public Object target;   
  6.     SpeakInvocationHandler(Object target) {   
  7.         this.target = target;   
  8.     }   
  9.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  10.         System.out.println(method.getName() + " invoked!");   
  11.         Object result = method.invoke(target, args);   
  12.         System.out.println(method.getName() + " return!");   
  13.         return result;   
  14.     }   
  15. }  
 package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class SpeakInvocationHandler implements InvocationHandler {
    public Object target;
    SpeakInvocationHandler(Object target) {
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + " invoked!");
        Object result = method.invoke(target, args);
        System.out.println(method.getName() + " return!");
        return result;
    }
}

 
 

2.        ProxyFactory

 

Java代码 复制代码 收藏代码
  1. package proxy;   
  2. import java.lang.reflect.InvocationHandler;   
  3. import java.lang.reflect.Proxy;   
  4. public class ProxyFactory {   
  5.     Class             cls;   
  6.     InvocationHandler h;   
  7.     public ProxyFactory(String className, InvocationHandler h) {   
  8.         try {   
  9.             cls = Class.forName(className);   
  10.             this.h = h;   
  11.         } catch (ClassNotFoundException e) {   
  12.             e.printStackTrace();   
  13.         }   
  14.     }   
  15.     public Object createProxyObject() {   
  16.         return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);   
  17.     }   
  18. }  
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyFactory {
    Class             cls;
    InvocationHandler h;
    public ProxyFactory(String className, InvocationHandler h) {
        try {
            cls = Class.forName(className);
            this.h = h;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public Object createProxyObject() {
        return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
    }
}

  

ProxyFactory 主要是通过反射的 Proxy 类动态的去创建接口的子类,同时该子类是 InvocationHandler 的一个代理,所有的方法实现,都是通过 InvocationHandler 代理来调用。

 

最后来看下 Main 函数:

 

Java代码 复制代码 收藏代码
  1. package proxy;   
  2. import java.lang.reflect.InvocationHandler;   
  3. public class ProxyTest {   
  4.     public static void main(String args[]) {   
  5.         Speak s = new PersonSpeak();   
  6.         InvocationHandler h = new SpeakInvocationHandler(s);   
  7.         ProxyFactory proxyFactory = new ProxyFactory(PersonSpeak.class.getName(), h);   
  8.         Speak speakProxy = (Speak) proxyFactory.createProxyObject();   
  9.         speakProxy.sayHello();   
  10.     }   
  11. }  
package proxy;
import java.lang.reflect.InvocationHandler;
public class ProxyTest {
    public static void main(String args[]) {
        Speak s = new PersonSpeak();
        InvocationHandler h = new SpeakInvocationHandler(s);
        ProxyFactory proxyFactory = new ProxyFactory(PersonSpeak.class.getName(), h);
        Speak speakProxy = (Speak) proxyFactory.createProxyObject();
        speakProxy.sayHello();
    }
}

  

 

得到的输出结果如下:

 sayHello invoked!

hello

sayHello return!

 

 

从输出结果可以看出红色的输出部分正是我们通过动态代理来实现的。通过如上的过程完成了正果动态代理的过程。

 

3.Hessian远程代理

 

除了实现 AOP ,动态代理还可以用于实现远程服务代理。比如说 Hessian 就是通过动态创建远程服务代理类来调用远程服务,从而使应用对远程服务透明化。 Hessian 调用过程如下: 

 

 

 

 

图4:Hessian远程服务调用过程

总结
JDK 动态代理是 java 反射的一个非常重要的特性, JDK 动态代理类还可以用来作为 SOAP 的远程服务代理类,总之它在某种程度上提供了 java 的动态性的特点,为应用提供了很大的灵活性。

分享到:
评论
1 楼 WhyNever 2012-07-20  
学习了。谢谢分享~

相关推荐

    jdk反射机制资料大合集

    6. **动态代理**:Java的反射机制可以结合java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现动态代理,创建代理对象,用于在调用实际目标对象的方法前或后添加额外的行为。 7. **安全性与...

    JdkProxy.java

    JdkProxy.java

    JDK动态代理_JDK动态代理

    JDK动态代理的核心API包括`java.lang.reflect.Proxy`和`java.lang.reflect.InvocationHandler`。 - **`java.lang.reflect.Proxy`**:提供了创建动态代理类和实例的方法。通过`newProxyInstance`方法,传入...

    JDK动态代理proxy

    JDK动态代理,全称为Java Dynamic Proxy,是Java标准库提供的一种强大且灵活的机制,允许我们在运行时创建代理类来实现指定的接口。这种机制主要用于实现AOP(面向切面编程)或为已有接口提供额外的功能,如日志、...

    Aop jdk proxy实现小例子

    JDK Proxy是Java提供的一种动态代理机制,它是实现AOP的一种方式。通过JDK Proxy,我们可以在运行时创建一个接口的实现类,并在调用接口方法时插入自定义的处理逻辑,这就是AOP的核心思想——“织入”(Weaving)。...

    Spring_0300_JDKProxy

    标题"Spring_0300_JDKProxy"暗示我们将讨论Spring如何使用JDK的Proxy类来实现动态代理。在Spring中,`org.springframework.aop.framework.ProxyFactoryBean`或`org.springframework.aop.framework.ProxyFactory`可以...

    jdk动态代理和CGlib动态代理

    1. **Proxy类**:这是JDK动态代理的核心类,它提供了`newProxyInstance()`静态方法,用于创建代理对象。 2. **InvocationHandler接口**:每个代理对象都关联一个`InvocationHandler`实例。当代理对象的方法被调用时...

    浅谈JDK动态代理与CGLIB代理去区别

    首先,JDK动态代理主要依赖于java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。Proxy类用于创建一个代理对象,而InvocationHandler接口则定义了处理代理对象调用方法的逻辑。当调用代理对象的...

    关于jdk动态代理的源码剖析

    `Proxy`类是JDK中专门用于生成动态代理类的工具类。它提供了一系列静态方法来帮助我们生成代理对象。 1. **`ProxyGenerator`的作用**:`ProxyGenerator`是一个辅助工具类,用于生成代理类的字节码文件。我们可以...

    Jdk动态代理和cglib动态代理原理

    JDK动态代理是Java内置的一种机制,依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。以下是JDK动态代理的基本工作原理: 1. **InvocationHandler接口**:这是处理代理对象方法调用...

    jdk动态代理技术详解

    InvocationHandler 接口是 JDK 中和动态代理直接相关的主要接口之一。该接口相当于 Proxy 类的 CallBack Interface,定义了一个方法 Object:invoke(Object obj, Method method, Object[] args)。第一个参数 proxy ...

    Jdk动态代理,cglib动态代理,反射和拦截器(链)示例

    Java标准库中的`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口是实现JDK动态代理的基础。动态代理主要用于创建一个代理对象,这个代理对象可以代替原始目标对象执行方法,并在调用前后...

    mybatis_jdk_proxy.zip

    总的来说,"mybatis_jdk_proxy.zip"可能包含的是关于如何在MyBatis中利用JDK Proxy实现Mapper接口动态代理的教程或示例代码。通过学习这部分内容,你可以掌握如何在MyBatis中优雅地处理数据库操作,并理解Java内存...

    JDK动态代理简单示例

    JDK动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建具有特定接口的代理类实例。这种技术在很多场景下都非常有用,比如在AOP(面向切面编程)中实现方法拦截、日志记录、事务管理等。下面我们将深入...

    静态代理 动态代理 jdk Proxy

    自己写的小例子,供学习参考。 public class StaticProxy implements Hello{ private HelloSpecker helloSpecker; public StaticProxy() { } public StaticProxy(HelloSpecker helloSpecker) { ...

    代理模式-静态动态代理-jdk动态代理-cglib动态代理

    JDK动态代理则是通过反射机制在运行时动态创建代理类。我们只需要提供一个InvocationHandler接口的实现,处理实际的调用逻辑。JDK动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`...

    CGLIB 和 JDK生成动态代理类的区别

    首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。JDK动态代理只能为实现了至少一个接口的类生成代理。它的基本原理是利用反射机制生成一个实现了目标接口的...

    JDK动态代理源码

    1. **Java.lang.reflect.Proxy**:这是JDK动态代理的关键类,它提供了创建动态代理对象的工厂方法`newProxyInstance()`。这个方法接收三个参数:`ClassLoader`用于加载代理类,`Interface[]`表示代理对象需要实现的...

    JDK动态代理 spring aop 的原理

    首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,而InvocationHandler接口定义了一个方法`invoke()`,该...

    JDK动态代理在EJB3(包括WebService)中的应用

    标题 "JDK动态代理在EJB3(包括WebService)中的应用" 暗示了本文将探讨Java开发中的一种重要技术——JDK动态代理,以及它如何在企业级JavaBean (EJB) 3.x版本及其相关的Web服务实现中发挥作用。EJB3是Java EE平台的...

Global site tag (gtag.js) - Google Analytics