Java动态代理的理解
代码内容:
https://github.com/cjy513203427/Java_Advanced_Knowledge/tree/master/src/com/advance/dynamic_proxy
Subject接口
- package com.advance.dynamic_proxy;
- /**
- * Created by hasee on 2018/8/22.
- */
- public interface Subject
- {
- public void rent();
- public void hello(String str);
- }
RealSubjec类t实现Subject
- package com.advance.dynamic_proxy;/**
- * Created by hasee on 2018/8/22.
- */
- /**
- * @Auther: 谷天乐
- * @Date: 2018/8/22 19:35
- * @Description:
- */
- public class RealSubject implements Subject
- {
- @Override
- public void rent()
- {
- System.out.println("I want to rent my house");
- }
- @Override
- public void hello(String str)
- {
- System.out.println("hello: " + str);
- }
- }
DynamicProxy实现InvocationHandler,必须要实现InvocationHandler类
- package com.advance.dynamic_proxy;/**
- * Created by hasee on 2018/8/22.
- */
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- /**
- * @Auther: 谷天乐
- * @Date: 2018/8/22 19:36
- * @Description:
- */
- public class DynamicProxy implements InvocationHandler
- {
- // 这个就是我们要代理的真实对象
- private Object subject;
- // 构造方法,给我们要代理的真实对象赋初值
- public DynamicProxy(Object subject)
- {
- this.subject = subject;
- }
- @Override
- public Object invoke(Object object, Method method, Object[] args)
- throws Throwable
- {
- // 在代理真实对象前我们可以添加一些自己的操作
- System.out.println("before rent house");
- System.out.println("Method:" + method);
- // 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
- method.invoke(subject, args);
- // 在代理真实对象后我们也可以添加一些自己的操作
- System.out.println("after rent house");
- return null;
- }
- }
启动类
- package com.advance.dynamic_proxy;/**
- * Created by hasee on 2018/8/22.
- */
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Proxy;
- /**
- * @Auther: 谷天乐
- * @Date: 2018/8/22 19:36
- * @Description:
- */
- public class Client
- {
- public static void main(String[] args)
- {
- // 我们要代理的真实对象
- Subject realSubject = new RealSubject();
- // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
- InvocationHandler handler = new DynamicProxy(realSubject);
- /*
- * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
- * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
- * 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
- * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
- */
- Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
- .getClass().getInterfaces(), handler);
- System.out.println(subject.getClass().getName());
- subject.rent();
- subject.hello("world");
- }
- }
原理:
通过代理类关联到InvocationHandler中的invoke方法调用了真实对象的方法,而不是直接调用的
我们可以对代理的方法前后自由的增加操作
先看InvocationHandler是什么东西
- /**
- * {@code InvocationHandler} is the interface implemented by
- * the <i>invocation handler</i> of a proxy instance.
- * InvocationHandler是一个被代理实例的调用程序实现的接口
- * <p>Each proxy instance has an associated invocation handler.
- * When a method is invoked on a proxy instance, the method
- * invocation is encoded and dispatched to the {@code invoke}
- * method of its invocation handler.
- * 每个代理实例都有相关联的调用处理程序
当一个方法被代理实例调用时,调用方法会被编码并分派它的调用程序的调用方法- * @author Peter Jones
- * @see Proxy
- * @since 1.3
- */
再看InvocationHandler中唯一一个方法invoke
- /**
- * Processes a method invocation on a proxy instance and returns
- * the result. This method will be invoked on an invocation handler
- * when a method is invoked on a proxy instance that it is
- * associated with.
- *
- * @param proxy the proxy instance that the method was invoked on
- * 参数proxy是指方法被调用的代理实例
- * @param method the {@code Method} instance corresponding to
- * the interface method invoked on the proxy instance. The declaring
- * class of the {@code Method} object will be the interface that
- * the method was declared in, which may be a superinterface of the
- * proxy interface that the proxy class inherits the method through.
- * 参数method是一个实例,它就是调用在代理实例上的接口方法。声明的
方法对象类是该方法声明的接口,这个接口是所有继承当前method的代理接口的父接口- * @param args an array of objects containing the values of the
- * arguments passed in the method invocation on the proxy instance,
- * or {@code null} if interface method takes no arguments.
- * Arguments of primitive types are wrapped in instances of the
- * appropriate primitive wrapper class, such as
- * {@code java.lang.Integer} or {@code java.lang.Boolean}.
- * 参数args是包含了代理方法调用中传输的对象数组参数。
或者这个接口没有参数。
原始类型的参数被打包在合适的包装类中,如Integer或者Boolean
意思就是int会包装成Integer...- */
- public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
我们真正执行rent()和hello(String str)方法的地方在DynamicProxy类中
- //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
- method.invoke(subject, args);
声明一个真实对象,InvocationHandler引用子类(在C++中接口实际就是一个父类,所以我这么说)传入真实对象
- //我们要代理的真实对象
- Subject realSubject = new RealSubject();
- //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
- InvocationHandler handler = new DynamicProxy(realSubject);
Proxy的newProxyInstance()方法
- * @param loader the class loader to define the proxy class
loader是加载类类加载定义代理类- * @param interfaces the list of interfaces for the proxy class
- * to implement
- interfaces是代理类实现的interface的集合
- * @param h the invocation handler to dispatch method invocations to
- h是一个handler用来分派方法去调用
- @CallerSensitive
- public static Object newProxyInstance(ClassLoader loader,
- Class<?>[] interfaces,
- InvocationHandler h)
- throws IllegalArgumentException
- {
- Objects.requireNonNull(h);
- //在这里对我们的接口进行了复制
- final Class<?>[] intfs = interfaces.clone();
- final SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
- }
- /*
- * Look up or generate the designated proxy class.
- */
- Class<?> cl = getProxyClass0(loader, intfs);
- /*
- * Invoke its constructor with the designated invocation handler.
- */
- try {
- if (sm != null) {
- checkNewProxyPermission(Reflection.getCallerClass(), cl);
- }
- final Constructor<?> cons = cl.getConstructor(constructorParams);
- final InvocationHandler ih = h;
- if (!Modifier.isPublic(cl.getModifiers())) {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- cons.setAccessible(true);
- return null;
- }
- });
- }
- return cons.newInstance(new Object[]{h});
- } catch (IllegalAccessException|InstantiationException e) {
- throw new InternalError(e.toString(), e);
- } catch (InvocationTargetException e) {
- Throwable t = e.getCause();
- if (t instanceof RuntimeException) {
- throw (RuntimeException) t;
- } else {
- throw new InternalError(t.toString(), t);
- }
- } catch (NoSuchMethodException e) {
- throw new InternalError(e.toString(), e);
- }
- }
控制台输出结果
第一个结果com.sun.proxy.$Proxy0是System.out.println(subject.getClass().getName());
可以清晰地看到,我们用到了代理类,而不是自己定义的Subject类
- com.sun.proxy.$Proxy0
- before rent house
- Method:public abstract void com.advance.dynamic_proxy.Subject.rent()
- I want to rent my house
- after rent house
- before rent house
- Method:public abstract void com.advance.dynamic_proxy.Subject.hello(java.lang.String)
- hello: world
- after rent house
总结:
代理是通过代理类关联到InvocationHandler中的invoke方法调用了真实对象的方法,从而完成了代理过程
Java动态代理的理解的更多相关文章
- 对JAVA动态代理的理解
叫动态代理就代表着有“静态代理”这回事. 而且,通常“动态”至少听着更NB一点. 关键就在于不明白啥叫“动”,这个得跟“静”比较下. 在我的理解,静态代理得自己声明一个类,实现跟被代理对象同样的接口. ...
- java高级---->Java动态代理的原理
Java动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程 ...
- Java 动态代理机制分析及扩展
Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...
- Java 动态代理机制分析及扩展,第 1 部分
Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...
- 深入理解 Java 动态代理机制
Java 有两种代理方式,一种是静态代理,另一种是动态代理.对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节.很多 API 就是通过这种形式来封装的. 代理模式结构图(图片来 ...
- 理解java动态代理
java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实 ...
- JAVA动态代理的全面深层理解
Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过 ...
- JAVA动态代理模式(从现实生活角度理解代码原理)
所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...
- 彻底理解JAVA动态代理
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public ...
随机推荐
- 在.net Core中使用StackExchange.Redis 2.0
StackExchange.Redis 2.0做了大量的改进包括使用了高性能的IO库System.IO.Pipelines来提升性能以及解决Timeouts问题, 但是在.net Core2.2之前为 ...
- 在 android 上运行 python 的方法
在android上运行python脚本,或者在android上使用python交互界面,对熟悉python的研究或开发人员来说,是一件很有吸引力的事情,因为python脚本真是非常高效,另外,有很多非 ...
- Mac与iPhone的使用
1.mac操作 苹果Mac操作系统下怎么显示隐藏文件(shift+cmmand+. ) Mac屏幕录制Gif Mac 键盘快捷键 Mac 上安装python3 2.iPhone操作 iPhone如何设 ...
- 8、insert、delete、update语句总结
insert常用语句 > insert into tb1 (name,age) values('tom',33); > insert into tb1 (name,age) values( ...
- “全栈2019”Java第七十四章:内部类与静态内部类相互嵌套
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- ZJOI round1游记
Day 0 到镇海报道了 大佬们太多了--话说镇海的晚饭还真好吃啊-- 听说某人要咱去找bwh--不过咱和他也不是很熟啊--还是算了吧--(才不是因为嫌麻烦懒得去呢) 晚上吃完晚饭之后在镇海校园里参观 ...
- ArchLinux下Ecplise软件报错
如果你的Java出现了一下问题:An error has occurred. See error log for more details.java.lang.NullPointerException ...
- 「美团 CodeM 复赛」城市网络
题目链接 题意分析 首先 \([u,v]\)在树上是一条深度递增的链 那么我们可以使用倍增找 \(x\)的祖先当中深度最大的值大于\(x\)的点 然后维护一个\(pre\) 重新建树 这样从\(x\) ...
- Scrapy 抓取股票行情
安装scrapy会出现错误,我们选择anaconda3作为编译环境,搜索scrapy安装(有错误自查) 创建scrapy爬虫项目: 调出cmd,到相应目录:输入: scrapy startprojec ...
- HTML attribute 与 DOM property 的对比
HTML attribute vs. DOM property 要想理解 Angular 绑定如何工作,重点是搞清 HTML attribute 和 DOM property 之间的区别. attri ...