JDK动态代理之InvocationHandler接口源码分析

JDK动态代理之InvocationHandler接口源码分析

InvacationHandler类是JDK动态代理中需要实现的接口,接口中只有一个方法:invoke

代码

package java.lang.reflect;

/**
 * {@code InvocationHandler} is the interface implemented by
 * the <i>invocation handler</i> of a proxy instance.
 *
 * 译文:
 *  InvocationHandler是代理类实现的接口
 *
 * <p>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 {@code invoke}
 * method of its invocation handler.
 *
 * 译文:
 *  每个代理对象都有一个与之关联的handler,代理对象上方法调用会被编码,并发送到
 *  与之对应的handler上
 */
public interface InvocationHandler {

    /**
     * Processes a method invocation on a proxy instance and returns
     * the result.  This method will be invoked on an invocation handler
     * when a method is invoked on a proxy instance that it is
     * associated with.
     *
     * 译文:
     * 处理代理类上的方法调用并返回结果。代理类的方法调用将同步调用与之相关联的handler
     *
     * @param   proxy the proxy instance that the method was invoked on
     *
     * 入参:proxy:承载被调用的方法的代理类实例
     *
     * @param   method the {@code Method} instance corresponding to
     * the interface method invoked on the proxy instance.  The declaring
     * class of the {@code Method} object will be the interface that
     * the method was declared in, which may be a superinterface of the
     * proxy interface that the proxy class inherits the method through.
     *
     *  入参:method:代理类实例上实现的接口的方法
     *
     *
     * @param   args an array of objects containing the values of the
     * arguments passed in the method invocation on the proxy instance,
     * or {@code null} if interface method takes no arguments.
     * Arguments of primitive types are wrapped in instances of the
     * appropriate primitive wrapper class, such as
     * {@code java.lang.Integer} or {@code java.lang.Boolean}.
     *
     *   入参:args: 代理类实例上的被调用方法的参数,为一个object数组,
     *               当被调用的方法无入参时,args为null,基本类型的参数将会
     *               被其相应的包装类型的参数转换,比如int会被转换成Integer,
     *               boolean会被转换成Boolean
     *
     * @return  the value to return from the method invocation on the
     * proxy instance.  If the declared return type of the interface
     * method is a primitive type, then the value returned by
     * this method must be an instance of the corresponding primitive
     * wrapper class; otherwise, it must be a type assignable to the
     * declared return type.  If the value returned by this method is
     * {@code null} and the interface method's return type is
     * primitive, then a {@code NullPointerException} will be
     * thrown by the method invocation on the proxy instance.  If the
     * value returned by this method is otherwise not compatible with
     * the interface method's declared return type as described above,
     * a {@code ClassCastException} will be thrown by the method
     * invocation on the proxy instance.
     *
     *  返回值:Object:代理类实力上被调用的方法的返回值。
     *          如果原方法定义的返回值为基本数据类型,则返回值将会被相应地
     *          转换成对应的包装类型。否则就必须是无需转换但是却能被重新定义的、
     *          (比如String类型)。如果原接口方法定义的返回值为基本数据类型,但是
     *          代理类实例上被调用的方法返回了null,则会抛出异常(NullPointerException),
     *          如果方法返回的数据与接口定义的方法的返回值不兼容,则会抛出
     *          ClassCastException异常。
     *
     *
     *
     * @throws  Throwable the exception to throw from the method
     * invocation on the proxy instance.  The exception's type must be
     * assignable either to any of the exception types declared in the
     * {@code throws} clause of the interface method or to the
     * unchecked exception types {@code java.lang.RuntimeException}
     * or {@code java.lang.Error}.  If a checked exception is
     * thrown by this method that is not assignable to any of the
     * exception types declared in the {@code throws} clause of
     * the interface method, then an
     * {@link UndeclaredThrowableException} containing the
     * exception that was thrown by this method will be thrown by the
     * method invocation on the proxy instance.
     *
     * @see     UndeclaredThrowableException
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
}

总结:

  1. 方法的参数分别是:代理类,被调用的方法,被调用的方法的参数(接口方法无参数时args为null)
  2. 方法的返回值只会返回相应的包装类,比如int会被转换成Integer
  3. 如果接口方法定义的返回值是基本数据类型,但是代理类实例调用方法时,结果为null,则会有代理类实例抛出空指异常
  4. 如果接口定义的方法返回值和代理类实例调用方法 返回值不兼容,则会抛出ClassCast异常,比如Object向下强转为int,但是Object是double向上转的,则会报错。
  5. JDK动态代理必须要实现接口。
  6. 被代理的接口的方法,返回值最好定义为包装类,这样就算代理类实例返回null,也不会影响程序正常运行。

版权声明:本文为weixin_45149504原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。