Java动态代理-创建动态类的实例对象及调用其方法

为什么动态类的实力对象的getClass()方法返回了正确的结果? $Proxy0;

调用代理对象的从Object类继承的hashCode,equals,或toString这个3个方法时,代理对象将调用请求转发给InvorcationHandler对象,对于其他方法,则不转发请求。所以geyClass(),返回的是代理对象本身的getClass(),值为: $Proxy0;


InvocationHandller接口中定义的invoke方法接受的三个参数的说明:

client程序调用objProxy.add(“abv”)方法时,涉及三要素:

objProxy 对象, add 方法, “abc” 参数, 分别对应invoke()的三个参数


生成Collectoin接口中的方法的运行原理:

// 在构造的时候接受传递过来的InvocationHandler
$Proxy0 implements Collection{
    InvocationHandler handler;
    public $Proxy0(InvocationHandler handler){
        this.handler = handler;
    }
}

// 生成的 Collection接口中的方法的运行原理
int size(){
    return handler.invoke(this, this.getClass().getMethod("size",null));
}

void clear(){
    handler.invode(this,this.getClass().getMethod("clear"),null);
}

测试代码:

package com.mari.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest1 {

  public static void main(String[] args) throws Exception{

    Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

    System.out.println("-------begin create instance object-------");

    Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);

    Collection proxy = (Collection) constructor.newInstance(new MyInvocationHandler());

    //创建实例对象
    Collection proxy1 = (Collection) Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() {

      ArrayList target = new ArrayList();

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        long beginTime = System.currentTimeMillis();
        Object rctVal = method.invoke(target, args);
        long endTime = System.currentTimeMillis();
        System.out.println(method.getName()+", running time of " + (endTime - beginTime));
        return rctVal;
      }
    });

    //调用add方法
    proxy1.add("abv");
    proxy1.add("abv");
    proxy1.add("abv");
    System.out.println(proxy1.size());
  }

  static class MyInvocationHandler implements InvocationHandler{

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

      return null;
    }

  }


}

控制台输出信息

-------begin create instance object-------
add, running time of 0
add, running time of 0
add, running time of 0
size, running time of 0
3


下面我们封装一下,将main函数中代码修改成为:
可生成代理和插入通告的通用方法:

package com.mari.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest1 {

  public static void main(String[] args) throws Exception{

    final ArrayList target = new ArrayList();

    Collection proxy1 = (Collection) getProxy(target, new MyAdvice());
    proxy1.add("a");
    proxy1.add("b");
    proxy1.add("c");
    System.out.println(proxy1.size());
  }

  //将mian函数中的获取代理的代码封装成方法,接收2个参数
  //一个是代理的目标,一个是执行代理的方法的接口
  public static Object getProxy(final Object target, final Advice advice) {
    Object proxy1 = Proxy.newProxyInstance(target.getClass().getClassLoader(),
                                                            target.getClass().getInterfaces(), 
                                                            new InvocationHandler() {

      //解释一下3个参数分别是: objProxy, add方法, "a","b","c" 等参数
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        advice.beforeMethod(method);
        Object rctVal = method.invoke(target, args);
        advice.afterMethod(method);

        return rctVal;

      }
    });
    return proxy1;
  }



}


接口类:

package com.mari.proxy;

import java.lang.reflect.Method;

public interface Advice {

  void beforeMethod(Method method);

  void afterMethod(Method method);

}

接口的实现类:

package com.mari.proxy;

import java.lang.reflect.Method;

public class MyAdvice implements Advice {

  long beginTime;

  @Override
  public void beforeMethod(Method method) {
    beginTime = System.currentTimeMillis();
  }

  @Override
  public void afterMethod(Method method) {
    long endTime = System.currentTimeMillis();
    System.out.println(method.getName()+ ", running time of " + (endTime - beginTime));
  }

}

控制台的输出:
add, running time of 0
add, running time of 0
add, running time of 0
size, running time of 0
3


这个就是一个简单的AOP框架的原理了

你可能感兴趣的:(Java)