代理模式是一种经典的设计模式,代理的意义在于生成代理对象,在服务提供方和使用方之间充当一个媒介,控制真实对象的访问。

代理分为静态代理和动态代理两种。

静态代理需要通过手动或工具生成代理类并编译,代理类和委托类的关系在编译期就已经确定。动态代理允许开发人员在运行时动态的创建出代理类及其对象。

Spring AOP 的主要技术基础就是 Java 的动态代理机制。


静态代理

静态代理的实现需要一个接口(表示要完成的功能),一个真实对象和一个代理对象(两者都需实现这个接口)。

示例如下:

interface Shopping {void buy();
}class Client implements Shopping {public void buy() {System.out.println("我想买这件商品");}
}class StaticProxy implements Shopping {private Shopping shopping;public StaticProxy(Shopping shopping) {this.shopping = shopping;}public void buy() {System.out.println("降价促销,疯狂大甩卖了!");shopping.buy();}
}public class StaticProxyTest {public static void main(String[] args) {Client client = new Client();StaticProxy service = new StaticProxy(client);service.buy();}
}

输出结果:

降价促销,疯狂大甩卖了!
我想买这件商品

动态代理

动态代理可以让我们在运行时动态生成代理类,解耦程度更高。Java 动态代理的实现主要借助于 java.lang.reflect 包中的 Proxy 类与 InvocationHandler 接口,所有对动态代理对象的方法调用都会转发到 InvocationHandler 中的 invoke() 方法中实现。一般我们称实现了 InvocationHandler 接口的类为调用处理器

我们可以通过 Proxy 的静态工厂方法 newProxyInstance 创建动态代理类实例。

方法如下:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
  • loader:类加载器
  • interfaces:类实现的全部接口
  • h:调用处理器

示例如下:

public class DynamicProxy implements InvocationHandler {private Object target = null;DynamicProxy(Object target) {this.target = target;}/*** 代理方法逻辑** @param proxy  代理对象* @param method 调度方法* @param args   调度方法参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理前");method.invoke(target, args);System.out.println("代理后");return null;}
}
public class DyProxyTest {public static void main(String[] args) {Shopping client = new Client();DynamicProxy dyProxy = new DynamicProxy(client);Shopping shop = (Shopping) Proxy.newProxyInstance(Shopping.class.getClassLoader(), new Class[]{Shopping.class}, dyProxy);shop.buy();}
}

输出结果:

代理前
我想买这件商品
代理后

当然我们也可以将 Proxy.newProxyInstance 方法放到调用处理器中,使客户端编程更为简单。

示例如下:

public class DynamicProxy implements InvocationHandler {private Object target = null;DynamicProxy() {}DynamicProxy(Object target) {this.target = target;}public Object bind(Object target) {this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}/*** 代理方法逻辑** @param proxy  代理对象* @param method 调度方法* @param args   调度方法参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理前");method.invoke(target, args);System.out.println("代理后");return null;}
}
public class DyProxyTest {public static void main(String[] args) {Shopping client = new Client();DynamicProxy dyProxy = new DynamicProxy();Shopping shop = (Shopping) dyProxy.bind(client);shop.buy();}
}

拦截器

拦截器主要就是靠动态代理实现,它可以简化动态代理的使用,我们只需要知道拦截器接口的使用方法即可,无须知道动态代理的实现细节。

示例如下:

public interface Interceptor {public boolean before(Object proxy, Object target, Method method, Object[] args);public void around(Object proxy, Object target, Method method, Object[] args);public void after(Object proxy, Object target, Method method, Object[] args);
}
public class MyInterceptor implements Interceptor {@Overridepublic boolean before(Object proxy, Object target, Method method, Object[] args) {System.out.println("before");return false;}@Overridepublic void around(Object proxy, Object target, Method method, Object[] args) {System.out.println("around");}@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println("after");}
}
public class InterceptorProxy implements InvocationHandler {private Object target = null;Interceptor interceptor = null;InterceptorProxy(Interceptor interceptor) {this.interceptor = interceptor;}public Object bind(Object target) {this.target = target;return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);}/*** 代理方法逻辑** @param proxy  代理对象* @param method 调度方法* @param args   调度方法参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (interceptor == null) {method.invoke(target, args);}Object result = null;if (interceptor.before(proxy, target, method, args)) {result = method.invoke(target, args);} else {interceptor.around(proxy, target, method, args);}interceptor.after(proxy, target, method, args);return result;}
}
public class InerceptorTest {public static void main(String[] args) {InterceptorProxy interceptor = new InterceptorProxy(new MyInterceptor());Shopping shop = (Shopping) interceptor.bind(new Client());shop.buy();}
}

输出结果:

before
around
after

开发者只需要知道拦截器的作用,设置拦截器,因而相对简单一些。

拦截器在 Spring AOP 与 Spring MVC 中都有应用。在 Spring AOP 中,

  • 针对接口做代理默认使用的是 JDK 自带的 Proxy+InvocationHandler
  • 针对类做代理使用的是 Cglib

在 Spring MVC中, 主要通过 HandlerInterceptor 接口实现拦截器的功能。

HandlerInterceptor 接口中包含3个方法:

  • preHandle:执行 controller 处理之前执行,返回值为true时接着执行 postHandle 和 afterCompletion,返回false则中断执行
  • postHandle:在执行 controller 后,ModelAndView 处理前执行
  • afterCompletion :在执行完 ModelAndView 之后执行

此外,Spring MVC 提供了抽象类 HandlerInterceptorAdapter,实现了 HandlerInterceptor 接口。


cglib

因为 Java 自带的动态代理工具必须要有一个接口,cglib 不需要接口,只需要一个非抽象类就能实现动态代理。

示例如下:

class ClientProxy implements MethodInterceptor {@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("before");Object obj = methodProxy.invokeSuper(proxy, args);System.out.println("after");return obj;}}
public class CglibTest {public static void main(String[] args) {ClientProxy clientProxy = new ClientProxy();Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Client.class);enhancer.setCallback(clientProxy);Client client = (Client) enhancer.create();client.buy();}
}

输出结果:

before
我想买这件商品
after

Java 中的代理(proxy)相关推荐

  1. 【java】深入分析Java反射-动态代理 proxy

    1.概述 转载:深入分析Java反射(四)-动态代理 [Java]Java 反射机制浅析 [Java]java代理 静态代理 动态代理 proxy [java]静态代理 proxy 2.动态代理的简介 ...

  2. Java中动态代理的两种方式JDK动态代理和cglib动态代理以及区别

    视频功能审核通过了,可以看视频啦!记得点关注啊~ 注意:因为网络原因,视频前一两分钟可能会比较模糊,过一会儿就好了 记得点关注啊,视频里的wx二维码失效了,wx搜索:"聊5毛钱的java&q ...

  3. 网络中的代理(proxy)和NAT

    简介ip地址和子网掩码 答: ip地址包括网络地址(前三段数字)和主机地址(第四段数字) 子网掩码用于计算出网络地址,控制广播范围. 网络中的代理(proxy)是什么意思?NAT是什么意思? 答: p ...

  4. 轻松学,Java 中的代理模式(proxy)及动态代理

    我们先来分析代理这个词. 代理 代理是英文 Proxy 翻译过来的.我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了. 她们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人. 按理说,顾客 ...

  5. java中动态代理实现机制

    v前言: 代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关 ...

  6. Java中通过代理对类进行修改

    JAVA中的静态代理.动态代理及JDK proxy和CGLIB.Javassist.ASM实践 简介 Java中对已经有的类进行修改,改变或调整其执行,这可以通过代理来实现.Java的class文件是 ...

  7. Java中的代理模式

    1.什么是代理模式 代理模式:就是为其他对象提供一种代理以控制对这个对象的访问. 代理可以在不改动目标对象的基础上,增加其他额外的功能(扩展功能). 举个例子来说明代理的作用: 一般我们想邀请明星来当 ...

  8. 模式代码 java中aes_深入浅出:Java中的代理模式

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象,用来在系统中对原始的接口进行替换,然后在内部做一些增强处理.代理模式不会破坏系统的原有接口,不去修改原有的 ...

  9. JAVA面试要点006---.net中的委托与java中的代理模式和委托

    1.1.1 定义 委托是一种引用方法的类型.一旦为委托分配了方法,委托将与该方法具有完全相同的行为.委托方法的使用可以像其他任何方法一样,具有参数和返回值,如下面的示例所示: //Code in C# ...

  10. 轻松学,Java 中的代理模式及动态代理

    前几天我写了<秒懂,Java 注解 (Annotation)你可以这样学>,因为注解其实算反射技术中的一部分,然后我想了一下,反射技术中还有个常见的概念就是动态代理,于是索性再写一篇关于动 ...

最新文章

  1. 天天都会写接口(interface),但它的用途和好处有多少人能说得清楚?
  2. 迎接 2019:软件开发新趋势预测
  3. 基于VTK User Guide和VTK Textbook学习
  4. python的心得体会200字_python_学习心得
  5. 提取一个二进制位最右侧的1
  6. 模切ERP和免费OA系统是互相结合提高效率
  7. Java工作笔记-webService发布时通用的4个注解
  8. Java深入 - servlet和Spring的DispatcherServlet详解
  9. elasticsearch+kibana使用中踩的坑,持续更新中。
  10. 去掉字符串首尾逗号_去除字符串首尾空格和特殊字符
  11. 20165320 第七周学习总结
  12. 怎么看软件的编写代码
  13. 精通Java事务编程(3)-弱隔离级别之快照隔离和可重复读
  14. vs2008中caption属性如何设置为中文
  15. 数学建模-多元线性回归
  16. 使用百度翻译API实现一键翻译
  17. C++中文件后缀的区别:cxx、cpp和txx,c、cc和cpp、hpp和h等
  18. python对英语的要求_对英文【对英文英语头条】- 对英文知识点 - 中企动力
  19. ESP8266-NodeMCU网络服务器——通过网页将文件上传到闪存文件系统
  20. android .trace 文件,android - 了解Android应用程序的.trace文件 - SO中文参考 - www.soinside.com...

热门文章

  1. uniapp实现贪吃蛇小游戏
  2. 微信QQ在线客服基本功能介绍
  3. 安卓手机格式化怎么弄_安卓手机怎么格式化
  4. 计算机英语作文初中,初中关于电脑的英语作文
  5. 怎样批量替换Word中的文字?这一招Word文字替换技巧你会吗
  6. 【毕设教程】python区块链实现 - proof of work工作量证明共识算法
  7. 四川眉山中院宣判两起特大跨国电信诈骗案
  8. 【NOI OJ】4977 怪盗基德的滑翔翼
  9. 西部世界IPFS科普:什么是非对称加密?
  10. 计算机太极之光,3000多名研究生赛太极,五大太极拳流派名家展风采