当前位置: 首页 > news >正文

Java 静态代理和动态代理

转自:http://kuangbaoxu.iteye.com/blog/192804

1. 代理模式主要有两种:静态代理和动态代理

2. 静态代理:

比如要在输出“HelloWorld”前打印一个字符串“Welcome”

A:先定义一个接口类

1 package  ttitfly.proxy;    
2    
3 public   interface  HelloWorld  {    
4    public void print();    
5//  public void say();    
6}
 

B: 定义一个该接口的实现类

java 代码

 1 package  ttitfly.proxy;    
 2    
 3 public   class  HelloWorldImpl  implements  HelloWorld {    
 4   
 5    public void print(){    
 6        System.out.println("HelloWorld");    
 7    }
    
 8//  public void say(){    
 9//      System.out.println("Say Hello!");    
10//  }    
11}
    

C:定义一个静态代理类

 1 package  ttitfly.proxy;    
 2    
 3 public   class  StaticProxy  implements  HelloWorld {    
 4   
 5    public HelloWorld helloWorld ;    
 6    public StaticProxy(HelloWorld helloWorld){    
 7        this.helloWorld = helloWorld;    
 8    }
    
 9        
10    public void print(){    
11        System.out.println("Welcome");    
12        //相当于回调    
13        helloWorld.print();    
14    }
    
15        
16//  public void say(){    
17//      //相当于回调    
18//      helloWorld.say();    
19//  }    
20}
    

D: 一个测试类:

 1 package  ttitfly.proxy;    
 2    
 3 public   class  TestStaticProxy  {    
 4   
 5    public static void main(String[] args){    
 6        HelloWorld helloWorld = new HelloWorldImpl();    
 7        StaticProxy staticProxy = new StaticProxy(helloWorld);    
 8        staticProxy.print();    
 9            
10//      staticProxy.say();    
11    }
    
12}
    

可以看出静态代理类有一个很不爽的缺点:当如果接口加一个方法(把上面所有的代码的注释给去掉),所有的实现类和代理类里都需要做个实现。这就增加了代码的复杂度。动态代理就可以避免这个缺点。 
3 。动态代理

动态代理与普通的代理相比较,最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理(invoke),这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。

动态代理类只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类

代理类: 

 1 package  ttitfly.proxy;        
 2        
 3 import  java.lang.reflect.InvocationHandler;        
 4 import  java.lang.reflect.Method;        
 5 import  java.lang.reflect.Proxy;        
 6 // 动态代理类只能代理接口,代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类        
 7 public   class  DynamicProxy  implements  InvocationHandler {        
 8            
 9    private Object object;         
10    //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。    
11    //Proxy.newProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法    
12    public Object bindRelation(Object object){         
13        this.object = object;        
14        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);         
15    }
         
16    //拦截关联的这个实现类的方法被调用时将被执行        
17    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         
18        System.out.println("Welcome");        
19        Object result = method.invoke(object, args);         
20        return result;        
21    }
        
22       
23}
        


测试类:

 1 package  ttitfly.proxy;        
 2        
 3 public   class  TestDynamicProxy  {        
 4    public static void main(String[] args){        
 5       HelloWorld helloWorld = new HelloWorldImpl();        
 6        DynamicProxy dp = new DynamicProxy();        
 7        //在这里绑定的是HelloWorld,也就是HelloWorld是被代理接口。所以绑定关系时,需要传递一个HelloWorld的实现类的实例化对象。        
 8        HelloWorld helloWorld1 = (HelloWorld)dp.bindRelation(helloWorld);         
 9        helloWorld1.print();         
10        helloWorld1.say();        
11            
12        //helloWorld2将不被拦截    
13        HelloWorld helloWorld2 = new HelloWorldImpl();    
14        helloWorld2.print();         
15        helloWorld2.say();    
16            
17    }
        
18}
        

在测试类里调用实现类的print和say方法,因为代理类里代理了HelloWorld的所有方法。所以就不需要像静态代理类那样一一实现了。

相关文章:

  • 【Python开发】Python之re模块 —— 正则表达式操作
  • 《深入浅出 Java Concurrency》—并发容器 ConcurrentMap
  • 不需内测账号,带你体验微信小程序完整开发过程
  • java synchronized与lock区别
  • 深入剖析Java编程中的中文问题及建议最优解决方法
  • linux系统安装php扩展
  • 从Decorator,Adapter模式看Java/IO库
  • 【神经网络与深度学习】什么是HDF
  • java内存模型分析
  • 博客园站内短消息XSS
  • Python 课件笔记
  • java I/O使用总结
  • Symbol not found for architecture arm64 错误
  • java socket编程总结
  • 抉择
  • 07.Android之多媒体问题
  • axios 和 cookie 的那些事
  • css选择器
  • C学习-枚举(九)
  • gf框架之分页模块(五) - 自定义分页
  • github从入门到放弃(1)
  • MySQL数据库运维之数据恢复
  • Python 反序列化安全问题(二)
  • session共享问题解决方案
  • springMvc学习笔记(2)
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Wamp集成环境 添加PHP的新版本
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 关于Flux,Vuex,Redux的思考
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 少走弯路,给Java 1~5 年程序员的建议
  • 深入浅出webpack学习(1)--核心概念
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 一文看透浏览器架构
  • linux 淘宝开源监控工具tsar
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 通过调用文摘列表API获取文摘
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # include “ “ 和 # include < >两者的区别
  • (3)llvm ir转换过程
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (SpringBoot)第二章:Spring创建和使用
  • (三)Honghu Cloud云架构一定时调度平台
  • (算法)求1到1亿间的质数或素数
  • (学习日记)2024.01.19
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)Android学习笔记 --- android任务栈和启动模式
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net流程开发平台的一些难点(1)
  • :O)修改linux硬件时间
  • ?.的用法
  • [ vulhub漏洞复现篇 ] Apache Flink目录遍历(CVE-2020-17519)