java-动态代理-从源码分析

来源:互联网 发布:fft c语言代码 编辑:程序博客网 时间:2024/06/05 05:24

现在有一个接口UserService

public interface UserService {  /**  * 目标方法   */  public abstract void add();  }  

有一个实现类

public class UserServiceImpl implements UserService {  /* (non-Javadoc)  * @see dynamic.proxy.UserService#add()  */  public void add() {      System.out.println("--------------------add---------------");  }  }  

有一个InvocationHandler类

public class MyInvocationHandler implements InvocationHandler {  // 目标对象   private Object target;  /**  * 构造方法  * @param target 目标对象   */  public MyInvocationHandler(Object target) {      super();      this.target = target;  }  /**  * 执行目标对象的方法  */  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {      // 在目标对象的方法执行之前简单的打印一下      System.out.println("------------------before------------------");      // 执行目标对象的方法      Object result = method.invoke(target, args);      // 在目标对象的方法执行之后简单的打印一下      System.out.println("-------------------after------------------");      return result;  }  }  

现在就可以实现动态代理啦

public class ProxyTest {  @Test  public void testProxy() throws Throwable {      // 实例化目标对象      UserService userService = new UserServiceImpl();      // 实例化InvocationHandler      MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);      // 根据目标对象生成代理对象,参数为:一个classloader,一个接口数组,一个invocationHandler     UserService proxy = (UserService)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),userService.getClass().getInterfaces(), invocationHandler );    // 调用代理对象的方法      proxy.add();  }  }  

解析

当你刚看到动态代理时,会感到非常疑惑与混乱。但最终的结果告诉我们,最后执行的代码是invocationHandler.invoke方法:

System.out.println("------------------before------------------");      // 执行目标对象的方法      Object result = method.invoke(target, args);      // 在目标对象的方法执行之后简单的打印一下      System.out.println("-------------------after------------------");  

通过查看Proxy.newProxyInstance方法的源码,我发现,有用的就两句话,大概意思是:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
Class proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
return (Object) cons.newInstance(new Object[] { invocationHandler });

java用Proxy.newInstance的第二个参数:接口数组,构造了一个新的class,并且返回了一个用该class构造的一个新的对象,通过反编译工具,来将该class文件反编译为一个java文件,来看看究竟:

public final class $Proxy11 extends Proxy  implements UserService  {   public $Proxy11(InvocationHandler invocationhandler)  {      super(invocationhandler);  }  public final boolean equals(Object obj)  {      try      {          return ((Boolean)super.h.invoke(this, m1, new Object[] {              obj          })).booleanValue();      }      catch(Error _ex) { }      catch(Throwable throwable)      {          throw new UndeclaredThrowableException(throwable);      }  }  @这个方法是关键部分@ public final void add()  {      try      {            super.h.invoke(this, m3, null);          return;      }      catch(Error _ex) { }      catch(Throwable throwable)      {          throw new UndeclaredThrowableException(throwable);      }  }  public final int hashCode()  {      try      {          return ((Integer)super.h.invoke(this, m0, null)).intValue();      }      catch(Error _ex) { }      catch(Throwable throwable)      {          throw new UndeclaredThrowableException(throwable);      }  }  public final String toString()  {      try      {          return (String)super.h.invoke(this, m2, null);      }      catch(Error _ex) { }      catch(Throwable throwable)      {          throw new UndeclaredThrowableException(throwable);      }  }  private static Method m1;  private static Method m3;  private static Method m0;  private static Method m2;  static   {      try      {          m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {              Class.forName("java.lang.Object")          });          m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);          m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);          m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);      }      catch(NoSuchMethodException nosuchmethodexception)      {          throw new NoSuchMethodError(nosuchmethodexception.getMessage());      }      catch(ClassNotFoundException classnotfoundexception)      {          throw new NoClassDefFoundError(classnotfoundexception.getMessage());      }  }  }  

也就是说当我们调用proxy.add()方法时,add方法的代码为:
super.h.invoke(this, m3, null);
super.h:
h也就是我们我们构造这个类时传入的参数,上面提到过,具体代码如下:
return (Object) cons.newInstance(new Object[] { invocationHandler });
一个我们定义过的类的实例。
m3:
m3 = Class.forName(“dynamic.proxy.UserService”).getMethod(“add”, new Class[0]);
现在一切就很清晰明了了吧,知其然知其所以然,现在就可以灵活运用java动态代理了。

参考文章:http://rejoy.iteye.com/blog/1627405

0 0
原创粉丝点击