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动态代理(测试)
待续。。。。。。。。。。。。。
五、总结一下
待续。。。。。。。。。。。。。