先看看静态代理是如何操作的

定义接口:

 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之静态代理与动态代理的更多相关文章

  1. java静态代理与动态代理

    原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽 ...

  2. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

  3. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  4. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  5. Java基础-静态代理与动态代理比较

    JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...

  6. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

  7. java静态代理与动态代理简单分析

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  8. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  9. Java静态代理和动态代理

    今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理.首先这个设计模式出来的时候先是静态代理模式 ...

  10. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

随机推荐

  1. 20155212Arrays和String测试_MySort

    Arrays和String单元测试 在IDEA中以TDD的方式对String类和Arrays类进行学习 测试相关方法的正常,错误和边界情况 String类 charAt split Arrays类 s ...

  2. 20155222 2016-2017-2 《Java程序设计》实验三

    20155222 2016-2017-2 <Java程序设计>实验三 1 在IDEA中使用工具(Code->Reformate Code)把下面代码重新格式化,再研究一下Code菜单 ...

  3. 20155224 实验一《Java开发环境的熟悉》实验报告

    实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版) ...

  4. 20155313 2016-2017-2 《Java程序设计》第十周学习总结

    20155313 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据. 程序员所作的事情就 ...

  5. 20155317 王新玮 2006-2007-2 《Java程序设计》第4周学习总结

    20155317 王新玮 2006-2007-2 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承共同行为 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那 ...

  6. 20155325实验四 Android程序设计

    实验四 Android程序设计-1 Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBIT,Java for Android 2nd)&g ...

  7. day 2 异常传递 ,抛出

    1.异常的传递 def test1(): print("---test1--") print(num) print('---test1 over---') def test2(): ...

  8. eclipse中编译出现错误undefined reference to `_sbrk'

    1. 在eclipse中使用gcc-arm-none-eabi-7-2017-q4-major-win32编译代码的时候出现了undefined reference to `_sbrk' e:/pro ...

  9. mongdb基础

    查看数据库 show dbs; 切换到需要使用的数据库:use local; 显示集合中的数据库表:show collections; 切换到数据库test,如果数据库不存在,则自动创建 插入数据 d ...

  10. halcon中关于文本的创建以及写入

    原文链接:http://blog.sina.com.cn/s/blog_61cc743001017nxr.html#FileName 1.open_file( : : FileName, FileTy ...