在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个是AOP,对于IoC,依赖注入不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理是java的动态代理机制,所以本篇随笔是对java的动态机制进行一个回顾。
  在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:
  InvocationHandler:
  InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
  每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的一个方法 invoke 方法:
  Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?
  Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  proxy:  指代我们所代理的那个真实对象
  method:  指代的是我们所要调用真实对象的某个方法的Method对象
  args:  指代的是调用真实对象某个方法时接受的参数
  如果不是很明白,等下通过一个实例会对这几个参数进行更深的讲解。
  接下来我们来看看Proxy这个类:
  Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
  Proxy这个类的作用是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的多的是 newProxyInstance 这个方法:
  public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
  Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.
  这个方法的作用是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义:
  public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
  loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
  interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象宣称实现了该接口(多态),这样我能调用这组接口中的方法了
  h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
  好了,在介绍完这两个接口(类)以后,我们来通过一个实例来看看我们的动态代理模式是什么样的:
  首先我们定义了一个Subject类型的接口,为其声明了两个方法:
  public interface Subject
  {
  public void rent();
  public void hello(String str);
  }
  接着,定义了一个类来实现这个接口,这个类是我们的真实对象,RealSubject类:
  public class RealSubject implements Subject
  {
  @Override
  public void rent()
  {
  System.out.println("I want to rent my house");
  }
  @Override
  public void hello(String str)
  {
  System.out.println("hello: " + str);
  }
  }
  下一步,我们要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:
public class DynamicProxy implements InvocationHandler
{
// 这个是我们要代理的真实对象
private Object subject;
//    构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject)
{
this.subject = subject;
}
@Override
public Object invoke(Object object, Method method, Object[] args)
throws Throwable
{
//  在代理真实对象前我们可以添加一些自己的操作
System.out.println("before rent house");
System.out.println("Method:" + method);
//    当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
method.invoke(subject, args);
//  在代理真实对象后我们也可以添加一些自己的操作
System.out.println("after rent house");
return null;
}
}