美文网首页
java 动态代理

java 动态代理

作者: 风吟空城 | 来源:发表于2019-04-09 17:22 被阅读0次

    java动态代理主要是通过InvocationHandler接口和Proxy类结合实现。下面逐一解释下两者的用法。

    InvocationHandler

    InvocationHandler接口源码

    /**
     * {@code InvocationHandler} is the interface implemented by
     * the <i>invocation handler</i> of a proxy instance.
     *
     * <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.
     *
     * @author      Peter Jones
     * @see         Proxy
     * @since       1.3
     */
    public interface InvocationHandler {
    

    因为找不到合适的称呼,所以把invocation handler统一翻译为调用处理程序,作为名词使用。

    代理类实例的调用处理程序都必须实现InvocationHandler接口,每个代理类实例中都有一个与之关联调用处理程序。当我们通过代理类实例调用一个方法的时候,这个方法调用就会被编码、转发到调用处理程序invoke方法。

    Invoke方法

    invoke源码:

        /**
         * 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.
         *
         * @param   proxy the proxy instance that the method was invoked on
         *
         * @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.
         *
         * @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}.
         */
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;
    

    参数解释

    • proxy 真实对象的真实代理对象。
    • method 与代理实例上调用的接口方法相对应的方法实例。
    • args 代理实例调用的方法的参数值,是一个对象数组。

    Proxy

    Proxy提供了很多静态方法来创建动态代理类和代理类实例,而且它还是所有它创建的动态代理类的超级父类。

    /**
     * {@code 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.
     */
    public class Proxy implements java.io.Serializable {
    

    InvocationHandler结合使用时,主要使用的静态方法是newProxyInstance

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
    throws IllegalArgumentException {
      ...
    }
    
    • loader: 用哪个类加载器去加载代理对象

    • interfaces:动态代理类需要实现的接口

    • h:动态代理方法在执行时,会调用h里面的invoke方法去执行

    demo

    接口代码

    public interface People {
    
        /**
         * 晚餐吃什么
         * @return 食物
         */
        String dinner();
    }
    

    实现类

    public class ItWorker implements People {
    
        @Override
        public String dinner() {
            return "KFC";
        }
    
    }
    

    调用处理程序

    public class PeopleHandler implements InvocationHandler {
    
        private Object obj;
    
        PeopleHandler() {
        }
    
        PeopleHandler(Object obj) {
            this.obj = obj;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(obj, args);
        }
    
    }
    

    PeopleHandler就是我们所说的调用处理程序,会在代理类创建代理实例时,作为参数(测试类中的peopleHandler)使用。通过demo可以更好的理解InvocationHandler的参数及功能。

    测试类

    public class PeopleTest {
    
        public static void main(String [] args){
            //真实对象
            People people = new ItWorker();
            //调用处理程序
            PeopleHandler peopleHandler = new PeopleHandler(people);
            //代理
            People proxy = (People) Proxy.newProxyInstance(peopleHandler.getClass().getClassLoader(),
                    people.getClass().getInterfaces(), peopleHandler);
            System.out.println(proxy.dinner());
        }
    
    }
    

    相关文章

      网友评论

          本文标题:java 动态代理

          本文链接:https://www.haomeiwen.com/subject/eccqbqtx.html