Fork me on GitHub

动态代理入门

1. 一个方法

  1. 该方法的作用: 在运行时, 动态创建一组指定接口的实现类对象!
  2. 动态代理的作用:学习 AOP(面向切面编程)
  3. JavaSE java.lang.reflect

// 该方法的作用, 动态创建实现了 interfaces 数组中所有指定接口的实现类对象!
Object proxyObject = Proxy.newProxyInstance(ClassLoader classLoader, Class[] interfaces,
                                            InvocationHandler h);

// 参数介绍
    /*
     * ClassLoader: 类加载器
     *         作用: 用来加载类的, 把 .class 文件加载到内存中, 形成 Class 对象!
     * Class[] interfaces : 要实现的接口们
     *         
     * InvocationHandler h
     *   它是调用处理器;
     *   代理对象的所有方法(个别不执行), 都会调用 InvocationHandler 的 invoke() 方法
     */

// 示例
    public class Demo {
        public void fun(){

            // 该方法需要动态生成一个类,这个类实现了 A, B 接口,然后创建这个类的对象!
            // 需要生成一个类,而这个类也需要加载到方法区中, 需要使用 ClassLoader 来加载

            // 使用 Demo 类的类加载器
            ClassLoader loader = this.getClass().getClassLoader();

            // 调用处理器
            InvocationHandler h = new InvocationHandler(){
                public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        System.out.println("这是动态代理......");
                        return null;
                }
            }

            // 使用三大参数创建代理对象!
            // 代理对象实现了所有接口中的方法, 方法的内容都是调用 InvocationHandler 的 invoke 方法
            Object o = Proxy.newProxyInstance(loader, new Class[]{ A.class, B.class}, h);

            // 将 o 类型强转为 A 和 B 类型
            A a = (A)o;
            B b = (B)o;

            // 调用代理对象中的 a 和 b 方法
            a.a();
            b.b();
            Object result = a.aaa("hello",100);
            System.out.println(result);
        }
    }

    // 两个接口
    interface A{
        public void a();
        public Object aaa(String s, int i);
    }
    interface B{
        public void b();
    }

2. InvocationHandler 接口

  1. 该接口只有一个 invoke 方法. 调用代理对象所实现接口中的方法,就是调用 invoke 中的内容.
    • public Object invoke(Object proxy, Method method, Object[] args);
    • Object proxy: 表示当前对象,即代理对象! 在调用谁的方法!
    • Method method: 当前被调用的方法(目标方法)
    • Object[] args: 实参, 表示将调用方法中的参数赋给该参数

3. 动态代理的应用

3.1 增强的手段
  1. 继承
    • 被增强的对象不能变
    • 增强的内容不能变
  2. 装饰者模式
    • 被增强的对象可变
    • 增强的内容不能变
  3. 动态代理
    • 被增强的对象可变
    • 增强的内容可变
3.2 应用示例
  1. 目标对象: 被增强的对象;
  2. 代理对象: 需要目标对象,然后在目标对象上添加了增强方法后的对象;
  3. 目标方法: 增强的内容;
  4. 代理对象 = 目标对象 + 增强
// 示例一
    // 服务员接口
    public interface Waiter{
        // 服务方法
        public void serve();
    }

    // 服务员实现类
    public class ManWaiter implements Waiter{
        public void serve(){
            System.out.println("服务中......");
        }
    }

    // 调用服务员实现类中的方法
    public class Demo {
        public void fun(){
            Waiter waiter = new ManWaiter();
            waiter.serve();
        }
    }

// 升级版本
//   使用动态代理给服务员添加功能
    public class Demo2 {
        public void fun(){
            Waiter manWaiter = new ManWaiter();

            // 给出三大参数, 来创建方法,得到代理对象
            ClassLoader loader = this.getClass().getClassLoader();
            Class[] interfaces = {Waiter.class};
            // 参数 manWaiter 表示目标对象
            InvocationHandler h = new WaiterInvocationHandler(manWaiter);

            // 得到代理对象
            Waiter waiterProxy = (Waiter)Proxy.newProxyInstance(loader,interfaces,h);

            waterProxy.serve(); // 前面添加 "您好", 后面添加 "再见"
        }
    }

    class WaiterInvocationHandler implements InvocationHandler{
            private Waiter waiter; // 目标对象

            public WaiterInvocationHandler(Waiter waiter){
                this.waiter = waiter;
            }

            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable{

                System.out.println("您好!");
                this.waiter.serve(); // 调用目标对象的目标方法
                System.out.println("再见!");
            }
    }
3.3 代理工厂实现
  1. 代理工厂的目标: 是让目标对象和增强都可以替换.

  2. 代理工厂使用步骤

    创建代理工厂
    给代理工厂设置三样东西

    • 目标对象: setTargetObject(xxx);
    • 前置增强: setBeforeAdvice(该接口的实现);
    • 后置增强: setAfterAdvice(该接口的实现);

    调用 createProxy() 得到代理对象

    • 执行代理对象方法时的步骤:
    • 执行 BeforeAdvice 的 before 方法
    • 执行目标对象的目标方法
    • 执行 AfterAdvice 的 after 方法
// 示例二: 代理工厂
    public class Demo3{

        // 使用代理工厂类
        public void fun(){

            // 创建代理工厂
            ProxyFactory factory = new ProxyFactory();

            // 设置目标对象
            factory.setTargetObject(new ManWaiter());

            // 设置前置增强(此处为匿名内部类)
            factory.setBeforeAdvice(new BeforeAdvice(){
                public void before(){
                    System.out.println("您好!");
                }
            });

            // 设置后置增强
            factory.setAfterAdvice(new AfterAdvice(){
                public void after(){
                    System.out.println("再见!");
                }
            });

            // 生成代理对象
            Waiter waiter = (Waiter)factory.createProxy();
            waiter.serve();
        }
    }

    // 代理工厂类
    /*
     * 它用来生成代理对象
     * 它需要所有的参数
     *   目标对象
     *   增强
     */
    public class ProxyFactory{
        private Object targetObject; // 目标对象
        private BeforeAdvice beforeAdvice; // 前置增强
        private AfterAdvice afterAdvice; // 后置增强

        // 用来生成代理对象
        public Object createProxy(){
            // 1. 给出三大参数
            ClassLoader loader = this.getClass().getClassLoader();

            // 获取目标对象的接口
            Class[] interfaces = targetObject.getClass().getInterfaces();

            InvocationHandler h = new InvocationHandler(){
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable{

                    // 在调用代理对象的方法时, 会执行这里的内容

                    // 执行前置增强
                    if(beforeAdvice != null){
                        beforeAdvice.before();
                    }    

                    // 执行目标对象的目标方法
                    Object result = method.invoke(targetObject,args);

                    // 执行后置增强
                    if(afterAdvice != null){
                        afterAdvice.after();
                    }

                    // 返回目标对象的返回值
                    return result;
                }
            };

            // 得到代理对象
            Object proxyObject = Proxy.newProxyInstance(loader, interfaces, h);
            return proxyObject;
        }

        public Object getTargetObject(){
            return targetObject;
        }
        public void setTargetObject(Object targetObject){
            this.targetObject = targetObject;
        }

        public BeforeAdvice getBeforeAdvice(){
            return beforeAdvice;
        }
        public void setBeforeAdvice(){
            this.beforeAdvice = beforeAdvice;
        }

        public AfterAdvice getAfterAdvice(){
            return afterAdvice;
        }
        public void setAfterAdvice(){
            this.afterAdvice = afterAdvice;
        }

    }

    // 前置增强
    public interface BeforeAdvice{
        public void before();
    }

    // 后置增强
    public interface AfterAdvice{
        public void after();    
    }

参考资料:

posted @ 2017-10-17 15:01  小a的软件思考  阅读(329)  评论(0编辑  收藏  举报