`

Java 动态代理

阅读更多

Java 动态代理

 

1. 动态代理需要Proxy类

   

   动态代理一般使用java.lang.reflect.Proxy类的

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

   方法创建一个代理类实例.

   

   传递的参数中:

     Class<?>[] interfaces 表示可以把创建的代理类强制转换成相应的接口,然后调用接口方法.

     

     InvocationHandler 是一个接口.

     接口方法为invoke(Object proxy, Method method, Object[] args),

     

     Proxy.newProxyInstance方法创建接口类,需要一个这个接口的实现类.

     实现这个InvocationHandler接口的类时,需要在构造函数中,把被代理的 对象实例(target) 传递过去,

     然后在invoke方法中,调用Method method的method.invoke(target, args);方法(真正调用被代理实例的方法).

 

   总结:

   使用 Proxy.newProxyInstance 方法动态创建代理类实例.

      参数ClassLoader loader 类加载器,使用被代理类 实例的类加载器即可.

      

      参数 Class<?>[] interfaces  决定 动态生成的代理实例可调用的方法(通过强制转化创建的代理类实例为该接口类型即可)

      

      代理类实例对Class<?>[] interfaces中任何方法的调用,

      都转化成对InvocationHandler h参数(InvocationHandler接口的实现类)

      的invoke(Object proxy, Method method, Object[] args),方法的调用

      其中Object proxy 表示动态生成的代理类实例(即Proxy.newProxyInstance生成的实例);

      Method method 代理类实例调用的方法实例,

      

      在invoke方法中,调用Method method的method.invoke(target, args);方法,

      表示调用 被代理类实例(target)的 接口方法

      因为代理类实例调用接口方法时,其实是调用InvocationHandler的invoke方法,而在这个方法里面

      在调用Method method的method.invoke(target, args);方法(表示调用 被代理类的 接口方法) 的前后

      可以做一些额外操作,这样就实现了代理.

      

2. 相关代码

/**
 * 
 * 被代理类实现的接口
 *
 */
public interface TrainStack
{
  public void SaleTicket();
}

 

/**
 * 
 * 被代理类
 *
 */
public class TrainStackImpl implements TrainStack
{
  @Override
  public void SaleTicket()
  {
    System.out.println("到达火车站售票处;");
    System.out.println("给钱,买票");
    System.out.println("");
  }
}

 

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

/**
 * 
 * Proxy.newProxyInstance方法需要的参数:
 * InvocationHandler接口实现类,
 * 在这个类的构造函数中,传递被代理类的实例.
 * Proxy.newProxyInstance创建的实例中调用的任何方法
 * 都相当于调用InvocationHandler接口实现类的
 * invoke方法,在invoke方法中调用
 * method.invoke(target, args);表示被代理类实例的接口方法嗲用,
 * 且在method.invoke(target, args)调用前后,可以做一些额外操作
 * 这样就形成了动态代理
 *
 */
public class TrainInvocationHandler implements InvocationHandler
{
  private Object target;
  
  public TrainInvocationHandler(Object obj) 
  {
   this.target = obj;
  }

  // 调用火车站买票的具体执行售票动作
  
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
  {
   Object sales;
   //代理先做一些初始工作
   System.out.println("代理开始...");
   System.out.println("买票人到达火车票代售点;");
   System.out.println("先交代售票服务费;");
   System.out.println("再交火车票票价钱;");
   System.out.println("火车票代售点派人去火车站;");
   System.out.println("");
   
   //调用火车站售票的动作SaleTicket()方法
   System.out.println("调用实际业务方法...");
   sales = method.invoke(target, args);
   
   //票买过后,代售点人买票回来
   System.out.println("继续代理...");
   System.out.println("火车票代售点人将代买来的火车票交给买票人.");
   
   return sales;
  }

  // 火车票代售点,创建具体代理对象
  // obj 接受具体买票的人
  /**
     * 这里要解释下面长长的代码的意思,以及具体做了哪些工作? 第一
     * 根据obj.getClass().getClassLoader()这个要代理类的类加载器
     * 和obj.getClass().getInterfaces()要代理类所实现的所有的接口
     * 作为参数调用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
     * 的方法返回代理类的java.lang.Class对象,也就是得到了java动态生成的代理类$Proxy0的Class对象。
     * 同时,java还让这个动态生成的$Proxy0类实现了要代理类的实现的所有接口,并继承了Proxy接口。 第二
     * 实例化这个动态生成的$Proxy0类的一个实例,实例化代理类的构造函数为Proxy(InvocationHandler h),
     * 也就是说要实例化这个动态生成的$Proxy0类,必须给它一个InvocationHandler参数,也就是我们自己实现的用来在代理类
     * 方法执行前后做额外工作的类TrainInvocationHandler。
     * 这段代码Proxy.newProxyInstance(obj.getClass().getClassLoader(),
     * obj.getClass().getInterfaces(), new TrainInvocationHandler(obj))
     * 得到的其实是一个类名叫$Proxy0 extends Proxy implements TrainStackImpl的类。
     */
  public static Object getInstance(Object obj)
  {
   
   return Proxy.newProxyInstance(
     obj.getClass().getClassLoader(),
     obj.getClass().getInterfaces(),
     new TrainInvocationHandler(obj));
  }
  /**
     * 大家如果还是不理解,可以看一下这段代码
     * 
     * 创建某一接口 Foo 的代理: InvocationHandler handler = new MyInvocationHandler(...);
     * 
     * Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new
     * Class[] { Foo.class });
     * 
     * Foo f = (Foo) proxyClass.getConstructor( new Class[] {
     * InvocationHandler.class }).newInstance(new Object[] { handler });
     * 
     * 或使用以下更简单的方法: Foo f = (Foo)
     * Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] {
     * Foo.class }, handler);
     */
}
 

 

/**
 * 
 * 动态代理客户端调用测试
 *
 */
public class TestDynamicProxy
{
  public static void main(String[] args)
  {
    TrainStack wantToBuy = new TrainStackImpl(); // 定义一个卖票的人
    TrainStack buyTicket = (TrainStack) TrainInvocationHandler.getInstance(wantToBuy); // 类型要转换
    buyTicket.SaleTicket(); // 调用卖票的方法,其实就是在调用invoke()这个方法
  }
}

  

附,概念解释:

  什么叫代理呢,网络中有各种各样的代理,比如我们上网有时候用代理服务器。

    你通过这样上网就是使用了代理上网。

     再举个通俗的例子,你想找某局长帮你做一件事情,但局长官位显赫,你又不能轻易见着,你就想到了找他的秘书,通过她传话给局长,这样你就等于请他的秘书帮你办成了那件事。秘书为什么就可以找到局长呢,因为秘书和局长之间有一定的关系。这里产生了四个对象:你、秘书、局长、秘书-局长(关系)。 

 

      JAVA中同样有代理关系,我们叫做代理模式。

代理模式的作用是:为其他对象(局长)提供一种代理(秘书)以控制对这个对象(局长)的访问。代理对象可以在客户端(你)和目标对象(局长)之间起到中介的作用。

代理模式一般涉及到的角色有: 

1.抽象角色(秘书-局长):声明真实对象和代理对象的共同接口(秘书-局长)

2. 代理角色(秘书):代理对象角色(秘书)内部含有对真实对象(局长)的引用,从而可以操作真实对象(局长),同时代理对象(秘书)提供与真实对象(局长)相同的接口(秘书-局长)以便在任何时刻都能代替真实对象(局长)。同时,代理对象(秘书)可以在执行真实对象(局长)操作时,附加其他的操作,相当于对真实对象(局长)进行封装

3. 真实角色(局长):代理角色(秘书)所代表的真实对象(局长),是我们最终要引用的对象(局长)

附件为工程文件:

 

分享到:
评论

相关推荐

    java动态代理demo

    Java动态代理是Java编程中一个重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理在很多场景下都非常有用,比如日志记录、性能监控、事务管理等。本示例将带你深入理解...

    java动态代理实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用真实目标对象的方法时添加额外的功能或行为。在这个实例中,我们将深入探讨Java动态代理的核心概念,...

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

    Java动态代理是Java编程中一个重要的特性,它允许在运行时创建代理对象,这些代理对象可以代表并增强原对象的功能。动态代理主要应用于面向切面编程(AOP)和事件监听等场景,使得代码更加模块化,易于维护。以下是...

    Java动态代理两种实现方式

    Java动态代理技术是Java编程中一个非常重要的特性,它允许我们在运行时动态创建具有特定行为的对象。这种技术常用于AOP(面向切面编程)和框架中,如Spring AOP,用于实现方法拦截、事务管理等功能。Java提供了两种...

    Java动态代理helloworld

    本篇文章将深入探讨Java动态代理的概念、原理以及如何通过一个简单的"Hello, World!"示例来理解它。 动态代理,顾名思义,是在程序运行时动态地生成代理对象。与静态代理(编译时已知)相比,动态代理更加灵活,...

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

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

    java 动态代理 简单实例

    Java动态代理是Java语言提供的一种在运行时创建代理对象的技术,它允许我们为已存在的接口创建代理类,以便在调用方法时添加额外的功能或控制。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等。...

    java动态代理机制

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现特定接口,从而可以灵活地扩展或增强已有代码的功能。在Java中,动态代理主要通过两个类来实现:`java.lang.reflect.Proxy` 和 `...

    java 动态代理实现AOP

    ### Java动态代理实现AOP详解 #### 一、引言 随着软件开发复杂度的提升,传统的面向对象编程(OOP)已经难以满足现代软件工程的需求。为了更好地管理跨切面的关注点,如日志记录、性能监控、安全控制等,面向切面...

    java动态代理和反射

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

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

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

    java动态代理(2)

    Java动态代理机制是Java语言提供的一种强大的功能,它允许在运行时创建代理对象来实现指定的接口。这一机制使得我们可以在不修改已有代码的情况下,为已有接口增加额外的功能或者增强已有功能的行为。在Java中,动态...

    java动态代理机制分析及拓展

    Java动态代理机制的优点在于灵活性和便捷性,它允许在运行时动态创建符合特定接口的代理对象,无需对原有代码做任何修改,使得我们可以方便地实现诸如日志、事务控制等跨切面的逻辑。不过,动态代理仅限于代理接口,...

    用Java动态代理实现AOP

    Java动态代理实现AOP Java动态代理是实现Aspect Oriented Programming(AOP)的重要手段。在Java中,动态代理可以通过java.lang.reflect InvocationHandler接口和java.lang.reflect.Proxy类来实现。AOP的主要思想...

    java动态代理

    ### Java动态代理知识点详解 #### 一、Java动态代理简介 在Java中,动态代理是一种非常重要的机制,它允许我们在运行时动态地创建一个接口的实现类实例。这种技术广泛应用于AOP(面向切面编程)、RPC(远程过程...

    java动态代理(3)

    Java动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建代理对象来代替目标对象,以便在不修改原有代码的情况下对目标对象的行为进行增强或扩展。在Java.lang.reflect包下,动态代理主要涉及两个核心...

    对代理模式与Java动态代理类的理解

    对代理模式与Java动态代理类的理解说明

    基于Java动态代理和反射机制实现ORM

    总之,基于Java动态代理和反射机制实现ORM,可以有效地解耦业务逻辑和数据库操作,提高代码的可读性和可维护性。虽然现有的ORM框架如Hibernate、MyBatis已经相当成熟,但对于学习和理解Java的高级特性,这样的实践...

    Java动态代理实现数据源连接池

    Java动态代理是Java语言提供的一种机制,它允许在运行时创建一个对象的代理,这个代理对象可以在调用实际方法之前和之后添加额外的功能。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang....

Global site tag (gtag.js) - Google Analytics