Java反射

java反射中的Proxy类的方法getProxyClass中的一个参数,我们可以看到源码如下

package java.lang.reflect;

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

该方法中的参数proxy是生成的代理类对象,method是被代理类的某个方法,args是在该method中的参数。业务增强就是在这里

一个次动态代理的组成,一个接口,一个实现类,一个动态代理类。这个动态代理类是生成的,并且该类继承了Proxy并实现了接口。因为已经继承了Proxy所以被代理类一定需要一个接口,而不能是个抽象类。这个接口存在是为了提供给动态生成的代理类,需要实现哪些方法,方法的修饰符和参数类型都是什么。

一个完整的例子如下。

package com.easyjdbc.proxyobtain;

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

interface Dao {
    void save(String name);
    void put();
}

class DaoImpl implements Dao {
    @Override
    public void save(String name) {
        System.out.println("save..."+name);
    }

    @Override
    public void put() {
        System.out.println("put");
    }
}

public class DynamicProxyTest {

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

        Object target = new DaoImpl();
        
        Class<?> proxyClass = Proxy.getProxyClass(DaoImpl.class.getClassLoader(), DaoImpl.class.getInterfaces());
        InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                System.out.println("before...");
                result = method.invoke(target, args);
                System.out.println("after...");
                return result;
            }
        };
        Dao userDao = (Dao) proxyClass.getConstructor(InvocationHandler.class).newInstance(handler);
        userDao.save("123");
    }
}

其中最为重要的方法就是public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException。可以进去看到于源码有安全检查和数据

 接着点进入,注意这里都是点方法,不是点类

 看到,apply就是生成代理类得函数。接着点进去,在实现类中找到

 然后到

其中proxyName就是代理类得类名,porxyPkg是$Proxy所以代理类就是$Proxy0,$Proxy1这样得类名,往下翻是生成字节码得方法,其中生成字节码得方法不让看,安全问题而放在了一个安全得包中。但是我们将生成得字节码从内容中读出并放在文件中。反编译后如下。

import com.easyjdbc.proxyobtain.Dao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
  extends Proxy
  implements Dao
{
  private static Method m1;
  private static Method m3;
  private static Method m4;
  private static Method m2;
  private static Method m0;
  
  public $Proxy0(InvocationHandler paramInvocationHandler)
  {
    super(paramInvocationHandler);
  }
  
  public final boolean equals(Object paramObject)
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void put()
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void save(String paramString)
  {
    try
    {
      this.h.invoke(this, m4, new Object[] { paramString });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final String toString()
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final int hashCode()
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.easyjdbc.proxyobtain.Dao").getMethod("put", new Class[0]);
      m4 = Class.forName("com.easyjdbc.proxyobtain.Dao").getMethod("save", new Class[] { Class.forName("java.lang.String") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

生成得代理类可以看出,构造方法传入一个InvocationHandler得实例,被代理得类中得方法与代理类得方法一一对应,而每个方法的方法体都是在调用传入参数InvocationHandler实例的invoke方法。三个参数一次对应为代理类this,被代理类的方法method,该方法的参数args。这样被代理类的每个方法都得到了增强。

在获取生成代理类的时ProxyGenerator不让用,右键项目、Properties、javaBuildPath、Library中、JRE systemLibrary、Edit、改为workspace default JRE或者改为Alternative JRE

上面创建代理类的过程还可以直接一步完成

Dao proxyClass = (Dao) Proxy.newProxyInstance(DaoImpl.class.getClassLoader(), DaoImpl.class.getInterfaces(), new InvocationHandler() {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("before...");
        result = method.invoke(target, args);
        System.out.println("after...");
        return result;
    }
});

内部也是和前面方法的调用时一样的

posted @ 2019-10-22 17:14  缓步徐行静不哗  阅读(241)  评论(0编辑  收藏  举报