016 Java中的动态代理
作者:nnngu
GitHub:https://github.com/nnngu
博客园:http://www.cnblogs.com/nnngu
简书:https://www.jianshu.com/users/1df20d76ea5c
知乎:https://www.zhihu.com/people/nnngu/posts
代理
代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
代理可以实现过滤请求、插入横切逻辑等功能,应用场景丰富多彩。
代理的方式分为静态代理和动态代理两种。
静态代理
程序运行前代理类的字节码文件依然存在,需要程序员编写源文件。
缺点:要针对于每一个类撰写代理类;对于单个被代理的类,如果需要被代理的方法很多,又加大了工作量。
优点:直观,可读性较强。
动态代理
程序运行时动态生成代理类的字节码文件,不需要程序员编写代理类java文件。
缺点:由于是运行时动态生成的,因此可读性不是很强;而且受限于被代理类自身的属性(jdk需要提供接口,cglib需要是非私有类)。
优点:代码更加简洁,解放了无谓的编码工作。
实现方式
让你来实现一个代理类,需要哪些上下文,有哪些解决方案?
jdk和cglib两种解决方案。
要生产一个类A的代理类,唯一需要了解的就是生成一个什么类,因此就有了基于该类的接口构造一个“A”。
至于如何生成一个class文件,在既定规则下你当然可以先生产java文件,再编译成class文件。而最好的做法是直接操作字节码文件,jdk和cglib生成字节码文件分别用了sun的ProxyGenerator和开源项目ASM字节码框架。

通过代理层这一中间层,有效的控制对于真实委托类对象的直接访问,同时可以实现自定义的控制策略(Spring的AOP机制),设计上获得更大的灵活性。
JDK的动态代理实现
jdk的动态代理,依赖的是反射包下的InvocationHandler接口,我们的代理类实现InvocationHandler,重写invoke()方法,每当我们的代理类调用方法时,都会默认先经过invoke()方法。
UserService接口
public interface UserService {
public String getName(int id);
public Integer getAge(int id);
}
接口的实现类UserServiceImpl
public class UserServiceImpl implements UserService {
public String getName(int id) {
System.out.println("------getName------");
return "Tom";
}
public Integer getAge(int id) {
System.out.println("------getAge------");
return 10;
}
}
UserInvocationHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class UserInvocationHandler implements InvocationHandler {
private Object target;
UserInvocationHandler() {
super();
}
UserInvocationHandler(Object target) {
super();
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("getName".equals(method.getName())){
System.out.println("++++++before " + method.getName() + "++++++");
Object result = method.invoke(target, args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
}else{
Object result = method.invoke(target, args);
return result;
}
}
}
测试类TestUserInvocationHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class TestUserInvocationHandler {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invocationHandler = new UserInvocationHandler(userService);
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
invocationHandler);
System.out.println(userServiceProxy.getName(1));
System.out.println(userServiceProxy.getAge(1));
}
}
运行结果:

cglib的动态代理实现
cglib需要的jar包:cglib.jar 和 asm.jar
cglib依赖的是cglib包下的MethodInterceptor接口,每调用代理类的方法,都会调用intercept方法
CglibMethodInterceptor.java
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibMethodInterceptor implements MethodInterceptor {
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("------before " + methodProxy.getSuperName() + "------");
Object o1 = methodProxy.invokeSuper(o, args);
System.out.println("------after " + methodProxy.getSuperName() + "------");
return o1;
}
}
TestCglibMethodInterceptor.java
import net.sf.cglib.proxy.Enhancer;
public class TestCglibMethodInterceptor {
public static void main(String[] args) {
CglibMethodInterceptor cglibProxy = new CglibMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(cglibProxy);
UserService o = (UserService) enhancer.create();
o.getName(1);
o.getAge(1);
}
}
运行结果:

016 Java中的动态代理的更多相关文章
- 使用Java中的动态代理实现数据库连接池
2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的 ...
- java中的动态代理机制
java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...
- 十分钟理解Java中的动态代理
十分钟理解 Java 中的动态代理 一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道 ...
- 深度剖析java中JDK动态代理机制
https://www.jb51.net/article/110342.htm 本篇文章主要介绍了深度剖析java中JDK动态代理机制 ,动态代理避免了开发人员编写各个繁锁的静态代理类,只需简单地指定 ...
- 一文读懂Java中的动态代理
从代理模式说起 回顾前文: 设计模式系列之代理模式(Proxy Pattern) 要读懂动态代理,应从代理模式说起.而实现代理模式,常见有下面两种实现: (1) 代理类关联目标对象,实现目标对象实现的 ...
- java中的动态代理
1.动态代理的定义:为其他对象提供一个代理以控制对这个对象的访问 2.通过api看下proxy生成代理类的2中写法: 创建某一接口 Foo 的代理: InvocationHandler handler ...
- 代理模式与java中的动态代理
前言 代理模式又分为静态代理与动态代理,其中动态代理是Java各大框架中运用的最为广泛的一种模式之一,下面就用简单的例子来说明静态代理与动态代理. 场景 李雷是一个唱片公司的大老板,很忙, ...
- java中的动态代理Proxy
动态代理是java语言的一个神奇的地方,不是很好理解,下面来看看关键的地方. InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHa ...
- Java 代理模式(二) Java中的动态代理
动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Objec ...
随机推荐
- 【日常训练】数据中心(CSP 201812-4)
分析 题目实际上是在要在给定的边上构建出一个树,使得这个树的最长边尽可能小. 这实际上是最小生成树的性质(反证法).问题从而得到解决. 代码 /* * Code name => csp20181 ...
- 【SIKIA计划】_06_Unity2D游戏开发-拾荒者笔记
[新增分类]Animations 动画——Animation——AnimatorControllerPrefabs 预制 [素材导入]unitypackage 素材包Sprites Editor 编辑 ...
- Shader Variants 打包遇到的问题
1. 遇到的问题 最常见的是打包到手机后效果与PC上不一致,具体情况比如: 光照贴图失效 雾失效 透明或者cutoff失效 以上首先需要检查的地方是Shader变体的编译设置 2. 超级着色器编译成N ...
- NO17--vue父子组件间单向数据流的解决办法
在上一篇中讲解了父子组件之间是如何传值的,如果子组件需要改变传过来的数据供自己使用,或者想在子组件中改变传过来的数据并同步到父组件,那么直接改肯定是不行的,如果你这么做了,Vue 会在控制台给出警告. ...
- web小结
一.ajax 1.用于前端向服务器异步获取数据 json数组:可以直接通过数组下标获取到值 json对象:可以用“data.xx”获取到值 2.注意事项 同时请求两个ajax时,容易出现异常,第一个a ...
- 虚拟机中安装MAC OS X教程(适用所有电脑方法,特别是cpu不支持硬件虚拟化的电脑)
前言 之前写了一篇在Windows上搭建Object-C开发环境,并且写了一个HelloWorld程序.但真正开发苹果软件是在MAC OS X系统中(以下简称OSX)中.买不起MacBook,也没有O ...
- 使用Python一年多了,总结八个好用的Python爬虫技巧
用python也差不多一年多了,python应用最多的场景还是web快速开发.爬虫.自动化运维:写过简单网站.写过自动发帖脚本.写过收发邮件脚本.写过简单验证码识别脚本. 爬虫在开发过程中也有很多复用 ...
- Scrum立会报告+燃尽图(Final阶段第三次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2481 项目地址:https://coding.net/u/wuyy694 ...
- Visual Studio AI配置环境
参考链接:http://www.cnblogs.com/ms-uap/p/9123033.html 背景: 1.能联网的电脑:Win7 64 SP1 2.鼠标.键盘.显示器好使 3.已安装VS2010 ...
- java thread start() 和 run() 区别
1.start() public static void main(String[] args) { // TODO 自动生成的方法存根 Thread t = new Thread() { publi ...