Proxy代理对象是如何调用invoke()方法的.
直奔主题,不说废话.先看java使用Proxy创建代理对象的代码.
//一个开发者接口
public interface Developer {
String code();
void debug();
}
//一个具体的开发者,实现两个接口
public class JavaDeveloper implements Developer { private String name; public JavaDeveloper(String name) {
this.name = name;
} @Override
public String code() {
System.out.println(name + "写代码");
return "写好了";
} @Override
public void debug() {
System.out.println(name + "调试bug");
}
}
public class JavaDynamicProxy {
public static void main(String[] args) {
/*这个根据情况自行输入,主要功能是将生成出的代理对象Class文件存到本地.
我用的idea编辑器,最终生成的文件在 工作空间下的 com\sun\proxy 文件夹中*/
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//具体类,需要增强的类
JavaDeveloper zack = new JavaDeveloper("Zack");
/*Proxy.newProxyInstance 方法三个参数
* 1 一个类加载器
* 2 需要增强的类都实现了哪些接口,或哪些父类.这个很重要,因为最终生成的代理类,是要重写父类的方法的.
* 3 一个调用处理器.是一个接口,需要实现接口中的方法,就一个invoke().这个方法很重要,你使用代理对象中的方法,
* 每次都会经过这个方法.这也就是增强的核心.invoke()的三个参数
* 1 需要增强原始对象.这里需要指定一个原型方法.
* 2 即将执行的增强方法,这个Method 当你调用代理对象的A方法,这个Method就是A方法的Class对象.
* 3 方法参数.A方法的参数. 熟悉反射的朋友应该能理解,一个Method方法执行,需要一个实例对象,和方法参数列表.
* */
Developer zackProxy = (Developer) Proxy.newProxyInstance(zack.getClass().getClassLoader(),
zack.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/* 我这里分别对两个方法进行了不同的增强.需要注意的是 返回值
* 如果你的方法没有返回值可以 return null*/
if (method.getName().equals("code")) {
System.out.println("正在祈祷.....");
method.invoke(zack, args);
return "动态的写好了";
}
if (method.getName().equals("debug")) {
System.out.println("已经祈祷了,怎么还有bug");
method.invoke(zack, args);
}
return null;
}
});
//使用代理对象
String s = zackProxy.code();
zackProxy.debug();
System.out.println(s);
/*打印结果
正在祈祷.....
Zack写代码
已经祈祷了,怎么还有bug
Zack调试bug
动态的写好了*/
}
}
我这里不关注代理对象的生成.有兴趣的可以自行查看.下边是生成代理对象的Class源文件,经过反编译后.
/*注意 当前反编译文件其中还有hashCode()toString()equals(Object obj)三个Object的方法.
这三个方法都是Object中可以被覆盖的方法.这也就是Proxy.newProxyInstance()方法第二个参数
的作用.*/
public final class $Proxy0 extends Proxy
implements Developer { //这里我把object的方法去掉了.直奔主题
private static Method m3;//debug 自定义的方法
private static Method m4;//code 自定义的方法 static {
try {
//初始化了两个Method,通过类名创建Class对象,在通过方法名获取Method对象.
m3 = Class.forName("sis.proxytest.Developer").getMethod("debug", new Class[0]);
m4 = Class.forName("sis.proxytest.Developer").getMethod("code", new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
} public $Proxy0(InvocationHandler invocationhandler) {
// 这里我把父类也就是 Proxy 部分代码贴上.
// protected InvocationHandler h;//父类成员变量
// protected Proxy(InvocationHandler h) {//父类构造子
// Objects.requireNonNull(h);
// //就是把我们new出来的 InvocationHandler传递给了父类
// this.h = h;
// }
super(invocationhandler);
} //这才是重点
public final void debug() {
try {
/* 当我们使用代理对象调用 debug()方法时.会使用父类Proxy的h成员变量的invoke()
这个h就是我们开篇使用Proxy.newProxyInstance创建代理对象中的第三个参数*/
super.h.invoke(this, m3, null);
return;
} catch (Error) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
} public final String code() {
try {
return (String) super.h.invoke(this, m4, null);
} catch (Error) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
以上就是Proxy生成代理对象,是如果使用invoke()方法的过程.如有不足请补充.
Proxy代理对象是如何调用invoke()方法的.的更多相关文章
- 从Mybatis源码理解jdk动态代理默认调用invoke方法
一.背景最近在工作之余,把开mybatis的源码看了下,决定自己手写个简单版的.实现核心的功能即可.写完之后,执行了一下,正巧在mybatis对Mapper接口的动态代理这个核心代码这边发现一个问题. ...
- 当使用System,out.println()打印一个对象是自动调用toString方法
在Java中,所有的对象都是继承自Object,自然继承了toString方法,在当使用System,out.println()里面为一个对象的引用时,自动调用toString方法讲对象打印出来.如果 ...
- java根据方法名动态调用invoke方法!
public class Activity { public void deal(String name, long id) { System.out.println(name + id + &quo ...
- InvocationHandler中invoke()方法的调用问题
转InvocationHandler中invoke()方法的调用问题 Java中动态代理的实现,关键就是这两个东西:Proxy.InvocationHandler,下面从InvocationHandl ...
- java动态代理中的invoke方法是如何被自动调用的(转)
一.动态代理与静态代理的区别. (1)Proxy类的代码被固定下来,不会因为业务的逐渐庞大而庞大: (2)可以实现AOP编程,这是静态代理无法实现的: (3)解耦,如果用在web业务下,可以实现数据层 ...
- java动态代理中的invoke方法是如何被自动调用的
转载声明:本文转载至 zcc_0015的专栏 一.动态代理与静态代理的区别. (1)Proxy类的代码被固定下来,不会因为业务的逐渐庞大而庞大:(2)可以实现AOP编程,这是静态代理无法实现的:(3) ...
- InvocationHandler中invoke方法中的第一个参数proxy的用途
最近在研究Java的动态代理时对InvocationHandler中invoke方法中的第一个参数一直不理解它的用处,某度搜索也搜不出结果,最后终于在stackoverflow上找到了答案. 这是原文 ...
- java Proxy(代理机制)
我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习 ...
- [转]Proxy代理详解
一.代理的概念 动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的. 动态代理技术就是用来产生一个对象的代理对 ...
随机推荐
- Jenkins的使用(一)
Jenkins 介绍: Jenkins是一个独立的开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成 变成可能.前身是Huds ...
- win10系统本地iis或nginx服务器部署vue.js项目
1.前端框架一般依赖node.js,我们首先要安装node.js.请参考: http://www.cnblogs.com/wuac/p/6381819.html to:安装好node.js后npm也安 ...
- windows10风格 springboot vue.js html 跨域 前后分离 activiti 整合项目框架源码
官网:www.fhadmin.org 此项目为Springboot工作流版本 windows 风格,浏览器访问操作使用,非桌面应用程序. 1.代码生成器: [正反双向](单表.主表.明细表.树形表,快 ...
- 在dockers中调试dump的dotnet程序
其他调试参考文章 centos7使用lldb调试netcore应用转储dump文件 centos7 lldb 调试netcore应用的内存泄漏和死循环示例(dump文件调试) 生成dump文件 如何在 ...
- Spring boot配置MongoDB以及Morphia踩坑记录
pom 因为项目中采用Morphia(MongoDB的ODM框架,对象-文档映射(object-document mapper)),因此需要在pom文件中引入相应依赖: <dependency& ...
- nginx实现反向代理 配置多域名以及多端口号
多个服务部署在同一个服务器,使用不同的端口. 一.思考过程 如果不想带上端口号,就只能访问 80 或 443 端口. 可以用过二级目录区分服务,通过反向代理转发到不同的 Server. 可以用过子域名 ...
- Django框架(十三)--Django分页组件
一.分页器 数据量大的话,可以分页获取,查看 例如:图书管理中,如果有成千上万本书,要是都在一个页面中渲染出来,会影响页面美观,所以就要用分页器分页渲染 二.分页器的使用 基本写法 基本写法: 后端: ...
- 迁移生产环境的GItLab11.3.5到新的服务器
在新的服务器上 rpm安装git 首先停止,Gitlab服务 root@localhost # gitlab-ctl stop 参考了 以下链接: https://blog.csdn.net/liul ...
- 【JavaScript】案例三:使用JS完成页面定时弹出广告——事件(onload)
事件(onload) *注意点: 变量加var局部变量,不加var全局变量 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭. 返回值:返回 ...
- 在ISTIO中让GRAFANA跑起来
比较轻车熟路了. 这个GRAFANA内,已集成了ISTIO常见的DASHBOARD了. 一,映射本地端口 kubectl port-forward -n istio-system $(kubectl ...