zoukankan      html  css  js  c++  java
  • JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(3):常用动态代理之JDK动态代理、CGLIB动态代理

    一、动态代理的理解  

            动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问。
            先来谈谈什么是代理模式。
            假设这样一个场景:你的公司是一家软件公司,你是一位软件工程师。客户带着需求去找公司显示不会直接和你谈,而是找商务谈,此时客户认为商务代表公司。

            显然客户是通过商务区访问软件工程师的,那么商务(代理对象)的意义在于什么呢?
    商务可以进行谈判,比如项目启动前的商务谈判,软件的价格,交付,进度的时间节点等,或者项目完成后的商务追讨应收账务等。商务有可能谈判失败,此时商务就会根据公司规则去结束和客户的合作关系,这些都不用工程师来处理。
    因此,代理的作用就是,在真实对象访问之前后者之后加入对应的逻辑,或者根据其他规则控制是否使用真实对象,显然在这个例子里商务控制了客户对软件工程师的访问。
            经过上面的论述,我们知道上午和软件工程师是代理和被代理的关系。客户经过商务区访问工程师。此时客户就是程序的调用者,商务就是代理对象,工程师就是真实对象。我们需要在调用者调用对象之前产生一个代理对象,而这个代理对象需要和真实对象建立代理关系,所以我们代理必须分为两个步骤:

    (1)代理对象和真实对象之间建立代理关系。

    (2)实现代理对象的代理逻辑方法。

    二、常用的动态代理

          在Java中有多种代理技术,比如:JDK、CGLIB、Javassist、ASM,其中最常用代理技术有两种:一种是JDK动态代理,这是JDK自带的功能,另一种是CGLIB,这是第三方提供的技术。目前Spring常用JDK和CGLIb,而MyBatis还使用了Javassist,但是无论哪种技术,它们的理念是相似的。

    三、JDK动态代理(测试)

      创建一个接口:HelloWorld.java

    1 package com.xfwl.proxy;
    2 
    3 public interface HelloWorld {
    4     public void  sayHelloWorld();
    5 }

     创建一个实现子类:HelloWorldImpl.java

    1 package com.xfwl.proxy;
    2 
    3 public class HelloWorldImpl implements HelloWorld {
    4 
    5     public void sayHelloWorld() {
    6         System.out.println("Hello World!");
    7     }
    8 }

     创建一个代理类:JdkProxyExample.java

    package com.xfwl.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    /**
     * JDK的动态代理
     * @function  两个步骤:(1)建立代理对象和真实服务对象的关系。(2)实现代理逻辑。
     * @author 小风微凉
     * @time  2018-7-9 上午10:45:53
     */
    public class JdkProxyExample implements InvocationHandler {
        //真实对象
        private Object target=null;
        /**
         * 建立代理对象和真实对象之间的代理关系,并返回代理对象
         * @param target 真实对象
         * @return 代理对象
         */
        public Object bind(Object target){
            this.target=target;
            return Proxy.newProxyInstance(
                        target.getClass().getClassLoader(), //类加载器
                        target.getClass().getInterfaces(),    //动态代理所挂的接口
                        this                                //实现方法逻辑的代理类,必须实现InvocationHandler接口的invoke方法
                    );
        }
        /**
         * 代理方法逻辑
         * @param proxy 代理对象
         * @param method 当前调度方法
         * @param args 当前方法参数
         * @return 代理结果返回
         * @throws Throwable 异常
         */
        public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
            System.out.println("进入代理方法");
            System.out.println("在调度真实方法之前的服务");
            Object obj=method.invoke(this.target, args);//相当于调用sayHelloWorld方法
            System.out.println("在调度真实方法之后的服务");        
            return obj;
        }
    }

     创建一个测试类:TestProxy.java

     1 package com.xfwl.proxy;
     2 /**
     3  * 测试JDK代理
     4  * @function  分析JDK是如何实现代理的
     5  * @author 小风微凉
     6  * @time  2018-7-9 上午10:47:14
     7  */
     8 public class TestProxy {
     9     /**
    10      * 测试入口
    11      */
    12     public static void main(String[] args) {
    13         JdkProxyExample jdk=new JdkProxyExample();
    14         //绑定关系,因为挂在接口HelloWorld下,所以生命代理对象HelloWorld proxy
    15         HelloWorld proxy=(HelloWorld)jdk.bind(new HelloWorldImpl());
    16         //注意,此时HelloWorld对象已经是一个代理对象,它会进入代理的逻辑方法invoke里
    17         proxy.sayHelloWorld();
    18     }
    19 }

     测试结果:

    进入代理方法
    在调度真实方法之前的服务
    Hello World!
    在调度真实方法之后的服务

     四、CGLIB动态代理(测试)

     待续。。。。。。。。。。。。。

    五、总结一下

    待续。。。。。。。。。。。。。

  • 相关阅读:
    [LA] 3027
    [POJ] 3264 Balanced Lineup [ST算法]
    [LA] 3644
    [Codeforces Round #248 (Div. 2)] B. Kuriyama Mirai's Stones
    [Codeforces Round #248 (Div. 2)] A. Kitahara Haruki's Gift
    [Codeforces Round #247 (Div. 2)] B. Shower Line
    [Codeforces Round #247 (Div. 2)] A. Black Square
    [UVA] 784
    [OpenJudge] 百练2754 八皇后
    449 Set、Map数据结构
  • 原文地址:https://www.cnblogs.com/newwind/p/9283152.html
Copyright © 2011-2022 走看看