zoukankan      html  css  js  c++  java
  • 动态代理

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 动态代理
     */
    public interface Subject {
        public void rent();
        public void hello(String str);
    }
    
    class RealSubject implements Subject {
    
        @Override
        public void rent() {
            System.out.println("I want to rent my house");
        }
    
        @Override
        public void hello(String str) {
            System.out.println("hello: " + str);
        }
    }
    
    class DynamicProxy implements InvocationHandler {
    
        private Object subject; //代理的真实对象
    
        /**
         * 构造方法,给我们要代理的真实对象赋初值
         * @param subject
         */
        public DynamicProxy(Object subject) {
            this.subject = subject;
        }
    
        /**
         *
         * @param proxy 动态代理类的引用,通常情况下不需要它。但可以使用getClass()方法,得到proxy的Class类从而取得实例的类信息,
         *                  如方法列表,annotation等。
         * @param method 方法对象的引用,代表动态代理类调用的方法。从中可得到方法名,参数,返回类型等等
         * @param args 对象数组,代表被调用方法的参数。注意基本类型(int, long)会被装箱成对象类型(Integer,Long)
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在代理真实对象前我们可以添加一些自己的操作
            System.out.println("before rent house");
            System.out.println("Method: " + method);
            // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法进行调用
            method.invoke(subject, args);
            // 在代理真实对象后也可以添加一些自己的操作
            System.out.println("after rent house");
            return null;
        }
    }
    
    class Client {
        public static void main(String[] args) {
            // 我们要代理的真实对象
            Subject realSubject = new RealSubject();
            //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
            InvocationHandler handler = new DynamicProxy(realSubject);
    
            /*
             * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
             * 第一个参数:handler.getClass().getClassLoader(),我们这里使用handler这个类的ClassLoader对象
             *      来加载我们的代理对象
             * 第二个参数:realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实现的接口,
             *      表示我们要代理的是该真实对象,这里我就能调用这组接口中的方法了
             * 第三个参数handler,我们这里将这个代理对象关联到了上方的InvocationHandler这个对象上
             *
             * Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader()
             *      , realSubject.getClass().getInterfaces(), handler);
             *  1. 为什么我们这里可以将其转化为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,
             *          我们给这个代理对象提供了一组什么接口 ,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以
             *          将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。
             *     通过Proxy.newProxyInstance 创建的代理对象是在jvm运行是动态生成的一个对象,它并不是我们的InbacationHandler类型,
             *     二是在运行时动态生成的一个对象,并且命名方式都是这样的形式(com.sun.proxy.$Proxy0),以$开头,proxy为中,最后一个数字表示对象的标号。
             */
            Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader()
                    , realSubject.getClass().getInterfaces(), handler);
            System.out.println(subject.getClass().getName());
            subject.rent();
            subject.hello("world");
        }
    }
  • 相关阅读:
    HDOJ 2076 夹角有多大(题目已修改,注意读题)
    HDOJ 2058 The sum problem
    HDOJ 2099 整除的尾数
    HDOJ 2075 A|B?
    HDOJ 2071 Max Num
    HDOJ 2056 Rectangles
    HDOJ 2055 An easy problem
    HDOJ 2053 Switch Game
    HDOJ 2052 Picture
    P4139 上帝与集合的正确用法
  • 原文地址:https://www.cnblogs.com/xinlichai0813/p/8287873.html
Copyright © 2011-2022 走看看