面试填坑笔记-从代理模式到SpringAOP的动态代理
代理模式是一种理论上非常简单,但是各种地方的实现往往却非常复杂。本文将从代理模式的基本概念出发,探讨代理模式在java领域的应用与实现。读完本文你将get到以下几点:
- 为什么需要代理模式,它通常用来解决什么问题,以及代理模式的设计与实现思路
- Java领域中代理模式3种不同实现类型(静态代理,jdk动态代理,cglib)
- 代理模式的面试考点
为什么要使用代理模式
所谓控制,其实使用接口隔离其他对象与这个对象之间的交互;就是为client对象对RealSubject对象的访问一种隔离,本质上就是CLient→RealSuject的关系变成了Client→Subject, Proxy→RealSubject。 需要注意的时,代理类(Proxy)并不一定要求保持接口的完整的一致性(既也可以完全不需实现Subject接口),只要能够实现间接控制即可。
代理模式代码演进#
背景:假设已有一个订单系统,可以保存订单信息。
需求:打印保存订单信息消耗时间。
/** * 订单服务 * * @author cruder * @date 2019-11-23 15:42 **/ public class OrderService2 { /** * 保存订单接口 */ public void saveOrder(String orderInfo) throws InterruptedException { // 随机休眠,模拟订单保存需要的时间 Thread.sleep(System.currentTimeMillis() & 100); System.out.println("订单:" + orderInfo + " 保存成功"); } }
普通方式实现#
直接修改源代码,这通常也是最简单和最容易想到的实现。
/** * 保存订单接口, 直接修改代码 */ public void saveOrder(String orderInfo) throws InterruptedException { long start = System.currentTimeMillis(); // 随机休眠,模拟订单保存需要的时间 Thread.sleep(System.currentTimeMillis() & 100); System.out.println("订单:" + orderInfo + " 保存成功"); System.out.println("保存订单用时: " + (System.currentTimeMillis() - start) + "ms"); }
面向对象设计原则中的“开闭原则”告诉我们,开闭原则规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。
代理模式实现#
/** * 1. 定义接口,为了使代理被代理对象看起来一样。当然这一步完全可以省略 * * @author cruder * @date 2019-11-23 15:58 **/ public interface IOrderService { /** * 保存订单接口 * @param orderInfo 订单信息 */ void saveOrder(String orderInfo) throws InterruptedException; } /** * 2. 原有订单服务,也实现这个接口。注意 此步骤也完全可以省略。 * * @author cruder * @date 2019-11-23 15:42 **/ public class OrderService implements IOrderService{ /** * 保存订单接口 */ @Override public void saveOrder(String orderInfo) throws InterruptedException { // 随机休眠,模拟订单保存需要的时间 Thread.sleep(System.currentTimeMillis() & 100); System.out.println("订单:" + orderInfo + " 保存成功"); } } /** * 3. 创建代理类,实现订单服务接口【这才是代理模式的实现】 * * @author cruder * @date 2019-11-23 16:01 **/ public