一:代理模式(静态代理)

代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。

静态代理由 业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的业务方法。

静态代理的实现:

1:首先定义一个接口,说明业务逻辑。

    package net.battier.dao;      /** * 定义一个账户接口 * @author Administrator*/  public interface Count {  // 查询账户public void queryCount();  // 修改账户  public void updateCount();  }  

2:然后,定义业务实现类,实现业务逻辑接口

import net.battier.dao.Count;
/** * 委托类(包含业务逻辑) *  * @author Administrator *  */
public class CountImpl implements Count {  @Override  public void queryCount() {  System.out.println("查看账户...");  }  @Override  public void updateCount() {  System.out.println("修改账户...");  }
}  

3:定义业务代理类:通过组合,在代理类中创建一个业务实现类对象来调用具体的业务方法;通过实现业务逻辑接口,来统一业务方法;在代理类中实现业务逻辑接口中的方法时,进行预处理操作、通过业务实现类对象调用真正的业务方法、进行调用后操作的定义。

public class CountProxy implements Count {  private CountImpl countImpl;  //组合一个业务实现类对象来进行真正的业务方法的调用/** * 覆盖默认构造器 *  * @param countImpl */  public CountProxy(CountImpl countImpl) {  this.countImpl = countImpl;  }  @Override  public void queryCount() {  System.out.println("查询账户的预处理——————");  // 调用真正的查询账户方法countImpl.queryCount();  System.out.println("查询账户之后————————");  }  @Override  public void updateCount() {  System.out.println("修改账户之前的预处理——————");  // 调用真正的修改账户操作countImpl.updateCount();  System.out.println("修改账户之后——————————");  }
}  

4:在使用时,首先创建业务实现类对象,然后把业务实现类对象作构造参数创建一个代理类对象,最后通过代理类对象进行业务方法的调用。

 public static void main(String[] args) {  CountImpl countImpl = new CountImpl();  CountProxy countProxy = new CountProxy(countImpl);  countProxy.updateCount();  countProxy.queryCount();  }  

静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码。这时我们可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用。——那就是动态代理。

二:动态代理的第一种实现——JDK动态代理

  JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。我们需要做的,只需指定代理类的预处理、调用后操作即可。

1:首先,定义业务逻辑接口

public interface BookFacade {  public void addBook();
} 

2:然后,实现业务逻辑接口创建业务实现类

public class BookFacadeImpl implements BookFacade {   @Override  public void addBook() {  System.out.println("增加图书方法。。。");  }  } 

3:最后,实现 调用管理接口InvocationHandler  创建动态代理类

public class BookFacadeProxy implements InvocationHandler {  private Object target;//这其实业务实现类对象,用来调用具体的业务方法 /** * 绑定业务对象并返回一个代理类  */  public Object bind(Object target) {  this.target = target;  //接收业务实现类对象参数//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类return Proxy.newProxyInstance(target.getClass().getClassLoader(),  target.getClass().getInterfaces(), this); }  /** * 包装调用方法:进行预处理、调用后处理 */  public Object invoke(Object proxy, Method method, Object[] args)  throws Throwable {  Object result=null;  System.out.println("预处理操作——————");  //调用真正的业务方法  result=method.invoke(target, args);  System.out.println("调用后处理——————");  return result;  }  }  

4:在使用时,首先创建一个业务实现类对象和一个代理类对象,然后定义接口引用(这里使用向上转型)并用代理对象.bind(业务实现类对象)的返回值进行赋值。最后通过接口引用调用业务方法即可。(接口引用真正指向的是一个绑定了业务类的代理类对象,所以通过接口方法名调用的是被代理的方法们)

public static void main(String[] args) {  BookFacadeImpl bookFacadeImpl=new BookFacadeImpl();BookFacadeProxy proxy = new BookFacadeProxy();  BookFacade bookfacade = (BookFacade) proxy.bind(bookFacadeImpl);  bookfacade.addBook();  }  

JDK动态代理的代理对象在创建时,需要使用业务实现类所实现的接口作为参数(因为在后面代理方法时需要根据接口内的方法名进行调用)。如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了。并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。

三:动态代理的第二种实现——CGlib

  cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。

1:首先定义业务类,无需实现接口(当然,实现接口也可以,不影响的)

public class BookFacadeImpl1 {  public void addBook() {  System.out.println("新增图书...");  }
}  

2:实现 MethodInterceptor方法代理接口,创建代理类

public class BookFacadeCglib implements MethodInterceptor {  private Object target;//业务类对象,供代理方法中进行真正的业务方法调用//相当于JDK动态代理中的绑定public Object getInstance(Object target) {  this.target = target;  //给业务对象赋值Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦        enhancer.setCallback(this);        // 创建动态代理类对象并返回         return enhancer.create();     }    // 实现回调方法     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {         System.out.println("预处理——————");        proxy.invokeSuper(obj, args); //调用业务类(父类中)的方法        System.out.println("调用后操作——————");        return null;     } 

3:创建业务类和代理类对象,然后通过  代理类对象.getInstance(业务类对象)  返回一个动态代理类对象(它是业务类的子类,可以用业务类引用指向它)。最后通过动态代理类对象进行方法调用。

public static void main(String[] args) {      BookFacadeImpl1 bookFacade=new BookFacadeImpl1();BookFacadeCglib  cglib=new BookFacadeCglib();  BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(bookFacade);  bookCglib.addBook();  }  

四:比较

静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;

JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;

CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;

转载于:https://www.cnblogs.com/barrywxx/p/8602538.html

Java动态代理之JDK实现和CGlib实现相关推荐

  1. java动态代理(JDK和cglib)

    2019独角兽企业重金招聘Python工程师标准>>> JAVA的动态代理  代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托 ...

  2. Java提高班(六)反射和动态代理(JDK Proxy和Cglib)

    反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多.要怎么理解以上这句话,请看下文. 一.反射 反射机制是 Ja ...

  3. 代理模式——静态代理,动态代理(JDK代理和CGLib代理)

    概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问. 这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. Java中的代理按照代理类生成时机不同又分为 ...

  4. 【过程记录】aop学习·实现动态代理的jdk方法和cglib方法和使用实例

    文章目录 介绍 jdk动态代理实例 cglib动态代理实例 介绍 JDK的动态代理只能代理实现了接口的类,而不能实现接口的类就不可以使用JDK动态代理,cglib是针对类来实现代理的,它的原理是针对指 ...

  5. Java动态代理代码案例:使用cglib实现对无接口的类进行动态代理

  6. Java动态代理实现(转载\整理)

    在深入解析MapReduce架构设计与实现原理一书中读到动态代理这个东东. 代理是一种常用的设计模式,其目的是为其他对象提供一种代理一控制对这个对象的访问.代理类负责为委托类进行预处理(如安全检查.权 ...

  7. Java 动态代理原理图解 (附:2种实现方式详细对比)

    动态代理在 Java 中有着广泛的应用,例如:Spring AOP 面向切面编程,Hibernate 数据查询.以及 RPC Dubbo 远程调用等,都有非常多的实际应用@mikechen 目录 Ja ...

  8. Java动态代理简述

    Java动态代理简述 一.代理简介 代理一词含义十分宽泛,例如金融领域的股票发行代理.营销领域的销售代理.以及计算机领域中的代理设计模式等.尽管代理一词被使用的领域如此广泛,但是代理一词的大致的抽象含 ...

  9. java动态代理(JDK和cglib)详解

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

最新文章

  1. 处理JS中数据失真问题-随笔
  2. 数独求解 DFS DLX
  3. anchor译中文_anchor的意思在线翻译,解释anchor中文英文含义,短语词组,音标读音,例句,词源,同义词【澳典网ODict.Net】...
  4. java web scala_spring boot+scala编写web接口
  5. bbb u-boot 验证 emmc
  6. vector 修改 java_java对vector动态数组中的对象排序,以下代码有何问题,如何修改?...
  7. 【华为云技术分享】云小课 | 如何通过虚拟私有云保障服务安全
  8. 【完结】深度学习CV算法工程师从入门到初级面试有多远,大概是25篇文章的距离...
  9. 力扣617. 合并二叉树(JavaScript)
  10. Unity常用工具类
  11. CodeForces 632C The Smallest String Concatenation(水)
  12. gvim【一】【安装和基本使用】
  13. 【Redis】Redis常用命令
  14. python按enter退出_【cmd按任意键退出 python】
  15. 二维码和app扫码下载
  16. TTL接口笔记本液晶屏改液晶显示器
  17. Android 渐变色背景样式
  18. Qt QTreeWidget 详解
  19. 【机器学习|数学基础】Mathematics for Machine Learning系列之线性代数(20):用配方法化二次型为标准形
  20. LeetCode之玩筹码

热门文章

  1. mysql表空间_浅谈mysql中各种表空间(tablespaces)的概念
  2. php 5.6 zend opcache,使用Zend OpCache 提高 PHP 5.5+ 性能
  3. Node.js webpack 加载器
  4. javacript Function parameters(函数参数)
  5. C语言 pthread_cancelpthread_detach
  6. MongoDB 用户管理
  7. 3.8 Softmax 回归
  8. C语言size_t类型
  9. 网站如何和服务器匹配,匹配服务器
  10. Mysql学习总结(56)——MySQL用户管理和权限设置