Java代理——静态代理和动态代理

一、代理模式


代理模式是常用的java设计模式,特征是代理类委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。

代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。  

按照代理的创建时期,代理类可以分为两种:

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

 

二、静态代理

 

 
 
  1. public interface CountDao  
  2. {  
  3.     // 查看账户方法  
  4.     public void queryCount();  
  5.  
  6.     // 修改账户方法  
  7.     public void updateCount();  
  8.  
  9. }  
  10.  
  11. public class CountDaoImpl implements CountDao  
  12. {  
  13.     public void queryCount()  
  14.     {  
  15.         System.out.println("查看账户方法...");  
  16.     }  
  17.  
  18.     public void updateCount()  
  19.     {  
  20.         System.out.println("修改账户方法...");  
  21.     }  
  22. }  
  23.  
  24. public class CountProxy implements CountDao  
  25. {  
  26.     private CountDao countDao;  
  27.  
  28.     public CountProxy(CountDao countDao)  
  29.     {  
  30.         this.countDao = countDao;  
  31.     }  
  32.  
  33.     @Override 
  34.     public void queryCount()  
  35.     {  
  36.         System.out.println("事务处理之前");  
  37.         countDao.queryCount();  
  38.         System.out.println("事务处理之后");  
  39.     }  
  40.  
  41.     @Override 
  42.     public void updateCount()  
  43.     {  
  44.         System.out.println("事务处理之前");  
  45.         countDao.updateCount();  
  46.         System.out.println("事务处理之后");  
  47.     }  
  48. }  
  49.  
  50. public class TestCount  
  51. {  
  52.     public static void main(String[] args)  
  53.     {  
  54.         CountProxy countProxy = new CountProxy(new CountDaoImpl());  
  55.         countProxy.updateCount();  
  56.         countProxy.queryCount();  
  57.     }  
  58. }  

观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且所有的代理操作除了调用的方法不一样之外其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。 


 

三、动态代理

与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。

 

1 JDK动态代理

JDK动态代理中包含一个类和一个接口

InvocationHandler接口

 

 
 
  1. public interface InvocationHandler {   
  2.     public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;   
  3. }   

Object proxy:指被代理的对象。 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数

可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject

 

Proxy类

Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:

 
 
  1. public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,   
  2. InvocationHandler h) throws IllegalArgumentException  

ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例

 
 
  1. public interface PersonService  
  2. {  
  3.     public void save();  
  4. }  
  5.  
  6. public class PersonServiceImpl implements PersonService  
  7. {  
  8.     public void save()  
  9.     {  
  10.         System.out.println("人员增加");  
  11.     }  
  12. }  
  13.  
  14. import java.lang.reflect.InvocationHandler;  
  15. import java.lang.reflect.Method;  
  16. import java.lang.reflect.Proxy;  
  17.  
  18. public class PersonProxy implements InvocationHandler  
  19. {  
  20.     // 目标对象  
  21.     private Object target;  
  22.  
  23.     // 返回一个代理类对象  
  24.     public Object createProxyInstance(Object target)  
  25.     {  
  26.         this.target = target;  
  27.         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);  
  28.     }  
  29.  
  30.     // 上述代码中调用的this就是当前代理对象,会自动调用该方法  
  31.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
  32.     {  
  33.         Object result = null;  
  34.         System.out.println("前置通知");  
  35.         try 
  36.         {     
  37.             result = method.invoke(target, args);  
  38.             System.out.println("后置通知");  
  39.         }  
  40.         catch(Exception e)  
  41.         {  
  42.             System.out.println("例外通知——出错啦");  
  43.         }  
  44.         finally 
  45.         {  
  46.             System.out.println("最终通知——结束啦");   
  47.         }  
  48.         return result;  
  49.     }  
  50. }  
  51.  
  52. public class TestProxy  
  53. {  
  54.     public static void main(String[] args)  
  55.     {  
  56.         PersonProxy bp = new PersonProxy();  
  57.         PersonService ps = (PersonService)bp.createProxyInstance(new PersonServiceImpl());  
  58.         ps.save();  
  59.     }  

前置通知
人员增加
后置通知
最终通知——结束啦

JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。 

 

2 CGLIB动态代理

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承所以不能对final修饰的类进行代理。

 
 
  1. public interface PersonService  
  2. {  
  3.     public void save();  
  4. }  
  5.  
  6. public class PersonServiceImpl implements PersonService  
  7. {  
  8.     public void save()  
  9.     {  
  10.         System.out.println("人员增加");  
  11.     }  
  12. }  
  13.  
  14. import java.lang.reflect.InvocationHandler;  
  15. import java.lang.reflect.Method;  
  16. import java.lang.reflect.Proxy;  
  17.  
  18. /**  
  19.  * 使用CGLIB动态代理  
  20.  */ 
  21. public class PersonProxy implements MethodInterceptor  
  22. {  
  23.     private Object target;  
  24.  
  25.     // 返回一个代理类对象  
  26.     public Object createProxyInstance(Object target)  
  27.     {  
  28.         this.target = target;  
  29.         Enhancer enhancer = new Enhancer();  
  30.  
  31.         // 设置目标类为父类,会覆盖目标类的非final方法  
  32.         enhancer.setSuperclass(this.target.getClass());  
  33.  
  34.         // 回调方法  
  35.         enhancer.setCallback(this);  
  36.  
  37.         // 创建代理对象  
  38.         return enhancer.create();  
  39.     }  
  40.  
  41.     // 上述代码中调用的this就是当前代理对象,会自动调用该方法  
  42.     // 方法一  
  43.     @Override 
  44.     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable  
  45.     {  
  46.         Object result = null;  
  47.         System.out.println("前置通知");  
  48.         try 
  49.         { 
  50.             result = method.invoke(target, args);  
  51.             System.out.println("后置通知");  
  52.         }  
  53.         catch (Exception e)  
  54.         {  
  55.             System.out.println("例外通知——出错啦");  
  56.         }  
  57.         finally 
  58.         {  
  59.             System.out.println("最终通知——结束啦");  
  60.         }  
  61.         return result;  
  62.     }  
  63. }  
  64.  
  65. public class PersonProxy2 implements MethodInterceptor  
  66. {  
  67.     private Object target;  
  68.  
  69.     // 返回一个代理类对象  
  70.     public Object createProxyInstance(Object target)  
  71.     {  
  72.         this.target = target;  
  73.         Enhancer enhancer = new Enhancer();  
  74.  
  75.         // 设置目标类为父类,会覆盖目标类的非final方法  
  76.         enhancer.setSuperclass(this.target.getClass());  
  77.  
  78.         // 回调方法  
  79.         enhancer.setCallback(this);  
  80.  
  81.         // 创建代理对象  
  82.         return enhancer.create();  
  83.     }  
  84.       
  85.     // 方法二  
  86.     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable  
  87.     {  
  88.         Object result = null;  
  89.         System.out.println("前置通知");  
  90.         try 
  91.         {   
  92.             result = proxy.invokeSuper(obj, args);  
  93.             System.out.println("后置通知");  
  94.         }  
  95.         catch (Exception e)  
  96.         {  
  97.             System.out.println("例外通知——出错啦");  
  98.         }  
  99.         finally 
  100.         {  
  101.             System.out.println("最终通知——结束啦");    
  102.         }  
  103.         return result;  
  104.     }  
  105. }  
  106.  
  107. public class TestProxy  
  108. {  
  109.     public static void main(String[] args)  
  110.     {  
  111.         PersonProxy cglib = new PersonProxy();  
  112.         PersonServiceClass ps1 = (PersonServiceClass) cglib.createProxyInstance(new PersonServiceClass());  
  113.         ps1.save();  
  114.         System.out.println("--------------------");  
  115.         PersonProxy2 cglib2 = new PersonProxy2();  
  116.         PersonServiceClass ps2 = (PersonServiceClass) cglib2.createProxyInstance(new PersonServiceClass());  
  117.         ps2.save();  
  118.     }  

前置通知
增加人员
后置通知
最终通知——结束啦
--------------------
前置通知
增加人员
后置通知
最终通知——结束啦

 

参考并演绎自地址:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip
毕设新项目基于python3.7+django+sqlite开发的学生就业管理系统源码+使用说明(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 学生就业管理系统(前端) ## 项目开发环境 - IDE: vscode - node版本: v12.14.1 - npm版本: 6.13.4 - vue版本: @vue/cli 4.1.2 - 操作系统: UOS 20 ## 1.进入项目目录安装依赖 ``` npm install ``` ## 2.命令行执行进入UI界面进行项目管理 ``` vue ui ``` ## 3.编译发布包(请注意编译后存储路径) #### PS:需要将编译后的包复制到后端项目的根目录下并命名为'static' 学生就业管理系统(后端) ## 1.项目开发环境 - IDE: vscode - Django版本: 3.0.3 - Python版本: python3.7.3 - 数据库 : sqlite3(测试专用) - 操作系统 : UOS 20 ## 2.csdn下载本项目并生成/安装依赖 ``` pip freeze > requirements.txt pip install -r requirements.txt ``` ## 3.项目MySQL数据库链接错误 [点击查看解决方法](https://www.cnblogs.com/izbw/p/11279237.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值