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动态代理(测试)

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

五、总结一下

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

原文地址:https://www.cnblogs.com/newwind/p/9283152.html