java动态代理机制

  Java动态代理中有两个重要的接口跟类,即 InvoctionHandler(Interface)、DynamicProxy(class),这个接口跟类使我们应用动态代理时必须要用的。每一个动态代理类都必须去实现 InvoctionHandler 这个接口,而且每个代理类的实例都必须关联一个 Hanlder 通过代理对象调用被代理对象中的方法时,其实是代理对象委托 InvoctionHandler 中的 invoke() 方法去调用被代理对象中的方法。invoke()方法的语法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable
其中三个参数的具体说明如下:
proxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数

Proxy 这个类提供了许多方法,其中我们最常用到的是  newProxyInstance  这个方法,这个方法作用就是得到一个动态代理的实例:


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

loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

我们来看一个例子,手机按我们定义了一个 Subject 接口,这个接口声明了真实对象和代理对象的共同接口,作用是在任何可以使用真实对象的时候都可以使用代理对象:

package proxy1;


public interface Subject {
      void rent();
      void Hello(String str);
  }


接下来要定义一个真实类来实现这个接口:


package proxy1;


public class RealSubject implements Subject {


@Override
public void rent() {
             System.out.println("I want to rent a house!");
} 


@Override
public void Hello(String str) {
             System.out.println("Hello " + str);
   }


}


这个真实类中具体实现了抽象接口中定义的方法。


接下来就要定义动态代理类了,这个动态代理类必须实现 InvocationHandler 接口:


package proxy1;


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

public class DynamicProxy implements InvocationHandler {

private Object subject;

public DynamicProxy(Object subject) {

this.subject = subject;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before rent a house,you need to know the proxyObject name.");
System.out.println("The proxyObject name is: " + method.getName());
          method.invoke(subject, args);
          System.out.println("Now you can live in your new house.");
return null;
  }
} 


代理类中含有对真实类的引用,从而可以在任何时刻操作真实对象。代理类提供一个与真实类相同的接口,以便在任何时候都可以代理真实类,控制对真是类引用,负责在需要的时候创建真实类对象或者删除真实类对象。代理类通常在将客户端调用传递给真实类之前或者之后,都要执行特定操作,比如日志记录等等,而不是单纯地将调用传递给真实类。

最后我们还要定义一个客户端:


package proxy1;

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

public class Client {
public static void main(String[] args) {
Subject subject=new RealSubject();  //创建一个真实对象的引用
InvocationHandler handler=new DynamicProxy(subject); //将真实对象的引用传递给代理对象
Subject str=(Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),
subject.getClass().getInterfaces(), handler); //代理对象调用真实对象的方法,通过 Proxy.newProxyInstance 创建的
          //代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,
          //也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,
         //以$开头,proxy为中,最后一个数字表示对象的标号。
str.rent();
str.Hello("Tom");
  }
}


控制台输出:


Before rent a house,you need to know the proxyObject name.
The proxyObject name is: rent
I want to rent a house!
Now you can live in your new house.
Before rent a house,you need to know the proxyObject name.
The proxyObject name is: Hello
Hello Tom
Now you can live in your new house.

str.rent();
str.Hello("Tom");


这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而我们的这个 handler 对象又接受了一个 RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的invoke方法去执行:

public Object invoke(Object object, Method method, Object[] args)
            throws Throwable
    {
        //  在代理真实对象前我们可以添加一些自己的操作
      System.out.println("Before rent a house,you need to know the proxyObject name.");
        
        System.out.println("The proxyObject name is: " + method.getName());
        
        //    当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        method.invoke(subject, args);
        
        //  在代理真实对象后我们也可以添加一些自己的操作
         System.out.println("Now you can live in your new house.");
        
        return null;
    }


调用的就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值