Java基础之代理原理与用法详解

 更新时间:2020年02月07日 10:12:29   作者:扎心了,老铁  
这篇文章主要介绍了Java基础之代理原理与用法,结合实例形式详细分析了java代理的概念、原理、用法及相关操作注意事项,需要的朋友可以参考下

本文实例讲述了Java基础之代理原理与用法。分享给大家供大家参考,具体如下:

1.什么是代理

动态代理技术是整个java技术中最重要的一个技术,它是学习java框架的基础,不会动态代理技术,那么在学习Spring这些框架时是学不明白的。

  动态代理技术就是用来产生一个对象的代理对象的。在开发中为什么需要为一个对象产生代理对象呢?
  举一个现实生活中的例子:歌星或者明星都有一个自己的经纪人,这个经纪人就是他们的代理人,当我们需要找明星表演时,不能直接找到该明星,只能是找明星的代理人。比如刘德华在现实生活中非常有名,会唱歌,会跳舞,会拍戏,刘德华在没有出名之前,我们可以直接找他唱歌,跳舞,拍戏,刘德华出名之后,他干的第一件事就是找一个经纪人,这个经纪人就是刘德华的代理人(代理),当我们需要找刘德华表演时,不能直接找到刘德华了(刘德华说,你找我代理人商谈具体事宜吧!),只能是找刘德华的代理人,因此刘德华这个代理人存在的价值就是拦截我们对刘德华的直接访问!
  这个现实中的例子和我们在开发中是一样的,我们在开发中之所以要产生一个对象的代理对象,主要用于拦截对真实业务对象的访问。那么代理对象应该具有什么方法呢?代理对象应该具有和目标对象相同的方法

  所以在这里明确代理对象的两个概念:
    1、代理对象存在的价值主要用于拦截对真实业务对象的访问。
    2、代理对象应该具有和目标对象(真实业务对象)相同的方法。刘德华(真实业务对象)会唱歌,会跳舞,会拍戏,我们现在不能直接找他唱歌,跳舞,拍戏了,只能找他的代理人(代理对象)唱歌,跳舞,拍戏,一个人要想成为刘德华的代理人,那么他必须具有和刘德华一样的行为(会唱歌,会跳舞,会拍戏),刘德华有什么方法,他(代理人)就要有什么方法,我们找刘德华的代理人唱歌,跳舞,拍戏,但是代理人不是真的懂得唱歌,跳舞,拍戏的,真正懂得唱歌,跳舞,拍戏的是刘德华,在现实中的例子就是我们要找刘德华唱歌,跳舞,拍戏,那么只能先找他的经纪人,交钱给他的经纪人,然后经纪人再让刘德华去唱歌,跳舞,拍戏。

2.代理的分类

静态代理:代理类和委托类在代码运行之前关系就已经确定了,也就是说在代理类的代码一开始就已经存在了。

动态代理:动态代理类的字节码在程序运行的时候生成。

3.Java中的代理

"java.lang.reflect.Proxy"类介绍

现在要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,所以首先要编写用于生成代理对象的类。在java中如何用程序去生成一个对象的代理对象呢,java在JDK1.5之后提供了一个"java.lang.reflect.Proxy"类,通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象,如下所示:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class<?>[] interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情。所以我们只需要调用newProxyInstance方法就可以得到某一个对象的代理对象了。

编写生成代理对象的类

在java中规定,要想产生一个对象的代理对象,那么这个对象必须要有一个接口,所以我们第一步就是设计这个对象的接口,在接口中定义这个对象所具有的行为(方法)

StduentInterface.java--定义对象的行为接口

public interface StduentInterface {
 public int insertStudent(Student student);
}

StudentDao.java--定义目标业务对象类

public class StudentDAO implements StduentInterface {
 @Override
 public int insertStudent(Student student) {
  // 以下这段代码是业务逻辑
  return null == student ? 0 : 1;
 }
}

创建静态代理

public class StudentStaticProxyDAO {
 private StudentDAO studentDAO;
 public StudentStaticProxyDAO(StudentDAO studentDAO) {
  this.studentDAO = studentDAO;
 }
 public int insertStudent(Student student) {
  Logger.info("开始插入一个学生记录: " + student.toString());
  int number = studentDAO.insertStudent(student);
  Logger.info("插入 " + number + " 条学生记录");
  return number;
 }
}

动态代理

public class LoggerDynamicProxy implements InvocationHandler{
 private Object target;
 public LoggerDynamicProxy(Object obj) {
  this.target = obj;
 }
 /**
  * 动态代理类中的 invoke 方法
  *
  * 三个参数的意义:
  *
  * proxy :代理对象
  * method : 委托类中要调用的方法
  * args :method 方法的参数
  */
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  Logger.info("before 业务方法调用之前");
  Object obj = method.invoke(target, args);
  Logger.info("before 业务方法调用之前");
  return obj;
 }
}

测试类

public class ProxyTest {
 public static void main(String[] args) {
  /**
   * 基础组件准备
   */
  StudentDAO studentDao = new StudentDAO();
  Student student = new Student(100000);
  StudentStaticProxyDAO studentProxyDAO = new StudentStaticProxyDAO(studentDao);
  /**
   * 测试委托类的功能
   */
  System.out.println(studentDao.insertStudent(student));
  /**
   * 测试静态代理类的功能
   */
  System.out.println(studentProxyDAO.insertStudent(student));
  /**
   * 测试动态代理类的功能
   */
  StduentInterface newProxyInstance = (StduentInterface)Proxy.newProxyInstance(studentDao.getClass().getClassLoader(),
    studentDao.getClass().getInterfaces(),
    new LoggerDynamicProxy(studentDao));
  int insertStudent = newProxyInstance.insertStudent(student);
  System.out.println(insertStudent);
}

运行结果

1
INFO: 开始插入一个学生记录: Student [id=100000, name=null]
INFO: 插入 1 条学生记录
1
INFO: before 业务方法调用之前
INFO: before 业务方法调用之前
1
INFO: before 业务方法调用之前
INFO: before 业务方法调用之前
1

更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • SpringBoot项目导入aliyun oss starter依赖后启动报错问题

    SpringBoot项目导入aliyun oss starter依赖后启动报错问题

    这篇文章主要介绍了SpringBoot项目导入aliyun oss starter依赖后启动报错问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Spring MVC项目开发踩过的一些bug

    Spring MVC项目开发踩过的一些bug

    这篇文章主要给大家介绍了关于Spring MVC项目开发踩过的一些bug,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • 解读httpclient的validateAfterInactivity连接池状态检测

    解读httpclient的validateAfterInactivity连接池状态检测

    这篇文章主要为大家介绍了httpclient的validateAfterInactivity连接池状态检测解读*,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Struts2实现CRUD(增 删 改 查)功能实例代码

    Struts2实现CRUD(增 删 改 查)功能实例代码

    CRUD是Create(创建)、Read(读取)、Update(更新)和Delete(删除)的缩写,它是普通应用程序的缩影。接下来通过本文给大家介绍Struts2实现CRUD(增 删 改 查)功能实例代码,感兴趣的朋友一起看看吧
    2016-06-06
  • java实现登录之后抓取数据

    java实现登录之后抓取数据

    这篇文章给大家分享了用JAVA实现在登陆以后抓取网站的数据的相关知识,有兴趣的朋友可以测试参考下。
    2018-07-07
  • Java如何获取word文档的条目化内容

    Java如何获取word文档的条目化内容

    这篇文章主要介绍了Java获取word文档的条目化内容的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-05-05
  • Spring-cloud-eureka使用feign调用服务接口

    Spring-cloud-eureka使用feign调用服务接口

    这篇文章主要为大家详细介绍了Spring-cloud-eureka使用feign调用服务接口,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • SpringMVC 实现用户登录实例代码

    SpringMVC 实现用户登录实例代码

    这篇文章主要介绍了SpringMVC 实现用户登录实例代码的相关资料,需要的朋友可以参考下
    2017-02-02
  • Java Map集合与Collection类的使用详解

    Java Map集合与Collection类的使用详解

    这篇文章主要介绍了Java Map集合的使用及Collection工具类使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • Java学习关于循环和数组练习题整理

    Java学习关于循环和数组练习题整理

    在本篇文章里小编给各位整理了关于Java学习关于循环和数组练习题相关内容,有兴趣的朋友们跟着参考学习下。
    2019-07-07

最新评论