java之静态代理与动态代理
先看看静态代理是如何操作的
定义接口:
public interface Person {
public void sayHello(String content, int age);
public void sayGoodBye(boolean seeAgin, double time);
}
实际的类:
public class Student implements Person{ @Override
public void sayHello(String content, int age) {
// TODO Auto-generated method stub
System.out.println("student say hello" + content + " "+ age);
} @Override
public void sayGoodBye(boolean seeAgin, double time) {
// TODO Auto-generated method stub
System.out.println("student sayGoodBye " + time + " "+ seeAgin);
}
14 }
代理类:
public class ProxyTest implements Person{ private Person o; public ProxyTest(Person o){
this.o = o;
} @Override
public void sayHello(String content, int age) {
// TODO Auto-generated method stub
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
o.sayHello(content, age);
System.out.println("ProxyTest sayHello end");
} @Override
public void sayGoodBye(boolean seeAgin, double time) {
// TODO Auto-generated method stub
System.out.println("ProxyTest sayHello begin");
//在代理类的方法中 间接访问被代理对象的方法
o.sayGoodBye(seeAgin, time);
System.out.println("ProxyTest sayHello end");
} public static void main(String[] args) {
// TODO Auto-generated method stub
//s为被代理的对象,某些情况下 我们不希望修改已有的代码,我们采用代理来间接访问
Student s = new Student();
//创建代理类对象
ProxyTest proxy = new ProxyTest(s);
//调用代理类对象的方法
proxy.sayHello("welcome to java", 20);
System.out.println("******");
//调用代理类对象的方法
proxy.sayGoodBye(true, 100); } }
可以看到,静态代理类要求实现与实际类型相同的接口,这个虽然在某些情况下有使用场景,但是其实扩展起来很麻烦,需要一个个的进行重载,相比之下,动态代理就好多了。
动态代理也需要一个代理类,实现特定的接口InvocationHandler:
public class MyInvocationHandler implements InvocationHandler{ private Object object; public MyInvocationHandler(Object object){
this.object = object;
} @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("MyInvocationHandler invoke begin");
System.out.println("proxy: "+ proxy.getClass().getName());
System.out.println("method: "+ method.getName());
for(Object o : args){
System.out.println("arg: "+ o);
}
//通过反射调用 被代理类的方法
method.invoke(object, args);
System.out.println("MyInvocationHandler invoke end");
return null;
} public static void main(String [] args){
//创建需要被代理的类
Student s = new Student();
//这一句是生成代理类的class文件,前提是你需要在工程根目录下创建com/sun/proxy目录,不然会报找不到路径的io异常
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
//获得加载被代理类的 类加载器
ClassLoader loader = Thread.currentThread().getContextClassLoader();
//指明被代理类实现的接口
Class<?>[] interfaces = s.getClass().getInterfaces();
// 创建被代理类的委托类,之后想要调用被代理类的方法时,都会委托给这个类的invoke(Object proxy, Method method, Object[] args)方法
MyInvocationHandler h = new MyInvocationHandler(s);
//生成代理类
Person proxy = (Person)Proxy.newProxyInstance(loader, interfaces, h);
//通过代理类调用 被代理类的方法
proxy.sayHello("yujie.wang", 20);
proxy.sayGoodBye(true, 100);
System.out.println("end");
} }
这个灵活性就好多了,不用关心自己代理的类到底有多少方法,只用实现一个invoke方法,去做自己想做的事情就好,如果需要根据特定的方法做事情,可能就需要根据method判断了,不如静态代理写在重载方法中感觉好。
那么,java到底是怎么实现动态代理的,不妨反编译一下,拿到的结果如下,可以看到其实是jvm帮你做了静态代理的事情:
public final class $Proxy0 extends Proxy implements Person{
private static Method m4;
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2; public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
//实现了Person接口的方法,这就是我们调用这个方法Proxy.newProxyInstance必须提供第二个参数的作用
public final void sayGoodBye(boolean paramBoolean, double paramDouble)
throws
{
try
{
// 我们看到通过调用代理类的方法时,最终方法都会委托给InvocationHandler实现类的invoke方法
// m4为代理类通过反射获得的Method
this.h.invoke(this, m4, new Object[] { Boolean.valueOf(paramBoolean), Double.valueOf(paramDouble) });
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
//实现了Person接口的方法,这就是我们调用这个方法Proxy.newProxyInstance必须提供第二个参数的作用
public final void sayHello(String paramString, int paramInt)
throws
{
try
{
// 我们看到通过调用代理类的方法时,最终方法都会委托给InvocationHandler实现类的invoke方法
// m4为代理类通过反射获得的Method
this.h.invoke(this, m3, new Object[] { paramString, Integer.valueOf(paramInt) });
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
} static
{
try
{//代理类通过反射 获得的接口方法Method
m4 = Class.forName("com.yujie.proxy.dynamic.Person").getMethod("sayGoodBye", new Class[] { Boolean.TYPE, Double.TYPE });
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
//代理类通过反射 获得的接口方法Method
m3 = Class.forName("com.yujie.proxy.dynamic.Person").getMethod("sayHello", new Class[] { Class.forName("java.lang.String"), Integer.TYPE });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
本文参考了https://blog.csdn.net/u011784767/article/details/78281384
java之静态代理与动态代理的更多相关文章
- java静态代理与动态代理
原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽 ...
- java的静态代理和动态代理(jdk、cglib)
一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...
- 【Java】代处理?代理模式 - 静态代理,动态代理
>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...
- Java:静态代理 and 动态代理
代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...
- Java基础-静态代理与动态代理比较
JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...
- java中静态代理,动态代理知识的补充
文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...
- java静态代理与动态代理简单分析
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- Java静态代理和动态代理
今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理.首先这个设计模式出来的时候先是静态代理模式 ...
- java中的静态代理和动态代理,入门整理
静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...
随机推荐
- js 修改字符串中某些字符的样式
var str = 'abcdefghijklmnobqrstuvwxyz'; function HightLight(e){ var reg = new RegExp(e, 'g') str = s ...
- Go语言反射之类型反射
1 概述 类似于 Java,Go 语言也支持反射.支持反射的语言可以在运行时对程序进行访问和修改.反射的原理是在程序编译期将反射信息(如类型信息.结构体信息等)整合到程序中,并给提供给程序访问反射信息 ...
- vim 查找
一.用/和?的区别:/后跟查找的字符串.vim会显示文本中第一个出现的字符串.?后跟查找的字符串.vim会显示文本中最后一个出现的字符串.二.注意事项:不管用/还是?查找到第一个字符串后,按回车,vi ...
- texterea 水平居中
例子:<div style="width: 100%;text-align: center;"> <textarea class="xinde_msg& ...
- WPF 动画:同为控件不同命 - 简书
原文:WPF 动画:同为控件不同命 - 简书 1. 及格与优秀 读大学的时候,有一门课的作业是用 PPT 展示. 但是我们很多同学都把 PPT 当做 Word 来用,就单纯地往里面堆文字. 大家都单纯 ...
- Hibernate框架用法
一,Hibernate框架介绍 没有Hibernate之前,使用jdbc来连接数据库时,需要反射加载驱动,再获取连接 在连接上获取sql承载块,传入sql语句执行,获取结果集,解析结果 Hiberna ...
- day1 Ubuntu 使用
ctrl + shift + + 放大终端 ctrl + - 缩小终端 软连接,硬链接 ln python@ubuntu:~/Desktop$ vim .txt python@ubuntu ...
- 【LG5022】[NOIP2018]旅行
[LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...
- Walle代码发布
一.概述 Walle 一个web部署系统工具,配置简单.功能完善.界面流畅.开箱即用!支持git.svn版本管理,支持各种web代码发布,PHP,Python,JAVA等代码的发布.回滚,可以通过we ...
- Python+MySQL开发医院网上预约系统(课程设计)一
一:开发环境的配置 1:桌面环境为cnetos7+python2.7 2:MySQL的安装与配置 1)MySQL的安装 MySQL官方文档: http://dev.mysql.com/doc/mysq ...