Java 代理模式(二) Java中的动态代理

动态代理类

  Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

  1.Interface InvocationHandler

  该接口中仅定义了一个方法:

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

  在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组(无参时设置为null)。

  这个抽象方法在代理类中动态实现。

  2.Proxy

  该类即为动态代理类,作用类似于上文例子中的ProxySubject,其中主要包含如下内容:

  protected  Proxy(InvocationHandler h): 构造函数,用于给内部的invocation handler赋值。

  static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) : loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

  static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  :返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类在Subject接口中声明过的方法)。

动态代理类说明

  所谓Dynamic Proxy是这样一种class:

  它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。

  你当然可以把该class的实例当作这些interface中的任何一个来用。

  当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

  在使用动态代理类时,我们必须实现InvocationHandler接口。每一个动态代理类都会有一个与之关联的invocation handler。

  真正的调用是在invocation handler的invoke()方法里完成的。

实例说明:

  首先定义抽象角色和真实角色类:

public interface Subject
{
    public void request();
}

public class RealSubject implements Subject
{
    @Override
    public void request()
    {
        System.out.println("From real subject!");
    }
}

  之后定义一个DynamicSubject类:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 该代理类的内部属性是Object类型,实际使用的时候通过该类的构造方法传递进来一个对象。
 * 该类实现了invoke()方法,该方法中的method.invoke()其实就是调用被代理对象的将要执行的方法,
 * 方法参数sub表示该方法从属于sub。
 * 通过动态代理类,我们可以在执行真实对象的方法前后加入自己的一些额外方法
 *
 */
public class DynamicSubject implements InvocationHandler
{

    //对真实对象的引用
    private Object sub;

    public DynamicSubject(Object obj)
    {
        this.sub = obj;

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        System.out.println("Before calling: " + method);

        //通过反射来调用方法
        method.invoke(sub, args);

        System.out.println("After calling: " + method);
        return null;
    }

}

  使用的时候:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client
{
    public static void main(String[] args)
    {
        RealSubject realSubject = new RealSubject();

        InvocationHandler handler = new DynamicSubject(realSubject);

        Class<?> classType = handler.getClass();

        // 生成代理
        // 动态生成一个类(实现了指定的接口),生成类的对象,转换成接口类型
        Subject subject = (Subject) Proxy.newProxyInstance(classType
                .getClassLoader(), realSubject.getClass().getInterfaces(),
                handler);

        subject.request();
        // 调用方法时,转移给handler接管,由其中的invoke()方法实际完成方法执行

        System.out.println(subject.getClass());// 打印出:class $Proxy0
        // $Proxy0是在运行期间动态生成的一个类

    }

}

  通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。

动态代理

  动态代理是指客户通过代理类来调用其他对象的方法。

  动态代理使用场合:

    调试。

    远程方法调用(RMI)。

动态代理步骤

  1.创建一个实现接口InvocationHandler的类,它必须实现invoke()方法。

  2.创建被代理的类以及接口。

  3.通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)创建一个代理。

  4.通过代理调用方法。

动态代理实现例子2:  

动态代理模式实例2

动态代理实现例子3:

  这个例子中定义了一个接口: 

public interface Foo
{
    public void doAction();
}

  这个接口有两个实现类:

public class FooImpl1 implements Foo
{
    @Override
    public void doAction()
    {
        System.out.println("From Implement 1 !");
    }
}

public class FooImpl2 implements Foo
{
    @Override
    public void doAction()
    {
        System.out.println("From Implement 2 !");
    }
}

  定义invocation handler,其中的set方法使得实际对象是可更换的:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CommonInvocationHandler implements InvocationHandler
{
    private Object target;

    public CommonInvocationHandler()
    {

    }

    public CommonInvocationHandler(Object obj)
    {
        this.target = obj;
    }

    public void setTarget(Object target)
    {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
    {
        return method.invoke(target, args);
    }

}

  使用:

import java.lang.reflect.Proxy;

public class Demo
{
    public static void main(String[] args)
    {
        CommonInvocationHandler handler = new CommonInvocationHandler();

        Foo f = null;

        handler.setTarget(new FooImpl1());

        f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                new Class[] { Foo.class }, handler);

        f.doAction();
        System.out.println("----------------------------");
        handler.setTarget(new FooImpl2());
        f.doAction();

    }

}

  程序运行后输出:

From Implement 1 !
----------------------------
From Implement 2 !

时间: 2024-10-12 20:45:07

Java 代理模式(二) Java中的动态代理的相关文章

java动态代理【二】:JDK动态代理的内部原理

上一章我们简单的讲解了什么是动态代理和如何使用动态代理. 这章讲解一下jdk的动态代理的内部实现: 首先查看测试代码: //创建一个静态方法,生成代理类, public static Object newProxyInstance(Object speak){ System.out.println(JDKDynamicProxy.class.getClassLoader().toString()); return Proxy.newProxyInstance(JDKDynamicProxy.cl

模式的秘密-代理模式(2)-JDK动态代理

代理模式-动态代理 (1) (2) 代码实践动态代理: 第一步:被代理类的接口: package com.JdkProxy; public interface Moveable { void move(); } 第二步:被代理类: package com.JdkProxy; import java.util.Random; public class Car implements Moveable { @Override public void move() { //实现开车 try { Thre

java反射机制中的动态代理

java反射机制中的动态代理 动态代理模式及其使用 步骤1:定义一个接口 //接口 interface Subject{ void action(); } 步骤2:定义一个接口的实现类,也就是被代理类 //被代理类 class RealSubject implements Subject { @Override public void action() { System.out.println("我是被代理类,请执行我"); } } 步骤3:定义一个实现InvocationHandle

Java语言中反射动态代理接口的解释与演示

Java语言中反射动态代理接口的解释与演示 Java在JDK1.3的时候引入了动态代理机制.可以运用在框架编程与平台编程时候捕获事件.审核数据.日志等功能实现,首先看一下设计模式的UML图解: 当你调用一个接口API时候,实际实现类继承该接口,调用时候经过proxy实现. 在Java中动态代理实现的两个关键接口类与class类分别如下: java.lang.reflect.Proxy java.lang.reflect.InvocationHandler 我们下面就通过InvocationHan

十分钟理解Java中的动态代理

十分钟帮助大家理解Java中的动态代理,什么是动态代理?感兴趣的小伙伴们可以参考一下 若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. 一.概述1. 什么是代理我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家"委托"代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,"委托

java中的动态代理机制

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的.下面通过代码来学习java中的动态代理技术. 首先定义一个接口: package com.aop.spring; /** * Created by xinfengyao on 16-2-29. */ public interface Perform { public void play(); } 实

Java中的动态代理以及Proxy类的偷瞄

动态代理机制 所谓动态代理,即通过代理类Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. Java动态代理类位于Java.lang.reflect包下,主要涉及到两个类. (1)接口InvocationHandler:该接口中仅定义了一个方法. Object invoke(Object obj, Method method, Object[] args); 在实际使用时,第一个参数obj一般指代理类,method是被代理的方法,args为该方法

使用Java中的动态代理实现数据库连接池

2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈.我们可以在 互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度.很多的连接池 都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前

Java类型信息与应用--动态代理

Java类型信息与应用--动态代理 本文结构 一.前言 二.为什么需要RTTI 三.RTTI在java中的工作原理 四.类型转化前先做检测 五.动态代理 六.动态代理的不足 一.前言 运行时信息使你可以在程序运行时发现和使用类型信息 Java在运行时识别对象和类的信息的方式: 1.一种是RTTI,它假定我们在编译时已经知道了所有的类型. 2.另一种是"反射"机制,它允许我们在运行时发现和使用类的信息. 这带来的好处是,你可以在程序运行时发现和使用类型信息 二.为什么需要RTTI 以多态

Spring AOP中的动态代理

0  前言 1  动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2  Spring AOP中的动态代理机制 2.1 JdkDynamicAopProxy 2.2 CglibAopProxy 3 总结 0  前言 前一个季度旅游TDC的Thames服务有几次宕机,根据组内原因认真查找发现是数据库事务造成的,后来把服务中的事务配置全部去掉,服务恢复正常.根据这次教训,虽然现在还是很难确定是哪一个方面的真正原因,但是激