Java基础—反射与代理(新手向)

Audio_J 2020-11-10 14:28:01
java 代理 反射 基础 新手


第1章 反射与代理

1.1 反射定义

1.1.1 大白话解释一下反射

一般情况下,需要一个功能的前提是遇到了某个问题,这里先列举一些问题,然后再通过反射是如何解决了这些问题,来引出反射的定义。

普通开发人员工作中最常见的问题:需要生成代理对象(不清楚代理模式的话,可以简单理解为需要将一个类,在不改变这个类的代码的基础上,要对这个类的功能添加新的逻辑)

解决方式:将需要加强的类,利用反射加载之后,与补充的逻辑进行融合,产生一个新的对象,这个对象就是代理对象,即具备原有类及新逻辑的“增强后的类”(比如 Man 类里面有个 eat() 方法,我们希望执行 eat() 方法前后分别执行洗手、洗碗逻辑,而我们又不能直接去修改eat()方法)

上面是用简洁的方式给出了关于反射的最直白的解释,下面给出较为专业、全面的解释:

1.1.2 反射是什么?

反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。

通过反射机制,可以在运行时访问 Java 对象的属性,方法,构造方法等

反射的应用场景:

开发通用框架 - 反射最重要的用途就是开发各种通用框架。很多框架(比如 Spring)都是配置化的(比如通过 XML 文件配置 JavaBean、Filter 等),为了保证框架的通用性,它们可能需要根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象
动态代理 - 在切面编程(AOP)中,需要拦截特定的方法,通常,会选择动态代理方式。这时,就需要反射技术来实现了
注解 - 注解本身仅仅是起到标记作用,它需要利用反射机制,根据注解标记去调用注解解释器,执行行为。如果没有反射机制,注解并不比注释更有用
可扩展性功能 - 应用程序可以通过使用完全限定名称创建可扩展性对象实例来使用外部的用户定义类

1.2 反射与代理中涉及术语

为了理解下一节反射与代理的关系,这里先介绍一下会涉及到的术语:

真实对象(被代理对象):就是最原始的类实例化产生的对象,未经过代理模式对其加工增强,比如上面所说的Man类的对象

代理对象:利用代理模式增强后的对象,比如SuperMan对象

动态代理类:可以理解为代理对象逻辑处理器,也可以理解为“增强”的逻辑所处的位置,需要传入真实对象产生关联的动态代理对象

InvocationHandler 接口:动态代理类需要实现这个接口,并且重写 invoke() 方法,“增强”的逻辑就写在invoke方法里,每个代理类的实例都关联到了一个 Handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由 InvocationHandler 这个接口的 invoke 方法来进行调用

Proxy:代理类,用以为将动态代理对象传入之后,产生真正代理对象

1.3 反射与代理的关系

如上所述,代理模式的主要作用产生代理对象从而实现增强后的方法,而反射作为 Java 所提供的一个特性,是实现代理模式的基础。换言之,利用反射技术获取和操作Java程序里面的类,从而可以对这些类进行包装及加工,产生出代理对象。

获得实现类对象的代理对象:

2.1 调用 Proxy.newProxyInstance 来获得一个动态的代理对象,其接收三个参数,三个参数所代表的含义分别是:
①一个 ClassLoader 对象,定义了由哪个 ClassLoader 对象来对生成的代理对象进行加载
②一个 Interface 对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
③ 一个 InvocationHandler 的实现类对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个 InvocationHandler 的实现类对象上

3.获得代理对象的类对象(这里我们可以打印一下代理类的类对象的类名)

4.获得代理类的所有方法(通过暴力反射 getDeclaredMethods()获得)(将所有获得的方法遍历,输出所有的方法名)

5.通过代理对象调用实现类的方法(并赋值),触发我们的重点步骤: InvocationHandler 接口的实现类中的invoked()方法,从而执行实现类的方法(sout输出结果即可)(这一步就是所谓的无侵入式编码规则)
5.1调用 InvocationHandler 接口具体步骤如下:
在触发了实现类的方法后,首先需要在 InvocationHandler 接口中传入三个参数,分别是
① proxy: - 指代我们所代理的那个真实对象
② method: - 指代的是我们所要调用真实对象的某个方法的Method对象()
③ args: - 指代的是调用真实对象某个方法时接受的参数

之后会执行接口独有的invoked()方法,传入两个参数,分别是真实的实现类对象和传入的参数args,最后返回方法。

1.4 JDK动态代理和CGLIB动态代理的区别

代理方式,其实都是通过继承真实对象(被代理对象)的类或者实现其所实现的接口之后,将增强的逻辑补充进去完成的。
JDK动态代理就是通过实现接口完成的,所以当一个类是通过实现接口产生的,就是用JDK动态代理
CGLIB动态代理是通过继承类完成的,所以当一个类没有实现接口,那只能使用JDK动态代理

1.5 Reflection框架

Java里面提供了反射获取类的各个属性及方法的类,但是前提是拿到该类之后才能获取并进行相应的操作,而反射框架Reflections不但能获取classpath下面的类,还能根据特定的注解进行获取。

Reflections通过扫描classpath,索引元数据,并且允许在运行时查询这些元数据。

使用Reflections可以很轻松的获取以下元数据信息:

  1. 获取某个类型的全部子类
  2. 只要类型、构造器、方法,字段上带有特定注解,便能获取带有这个注解的全部信息(类型、构造器、方法,字段)
  3. 获取所有能匹配某个正则表达式的资源
  4. 获取所有带有特定签名的方法,包括参数,参数注解,返回类型
  5. 获取所有方法的名字
  6. 获取代码里所有字段、方法名、构造器的使用

1.6 JsonCat里面对于的动态代理的使用

jsoncat项目链接:https://github.com/Snailclimb/jsoncat

1.7 参考

https://blog.csdn.net/yaomingyang/article/details/80981004
https://zhuanlan.zhihu.com/p/60805342
https://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful

版权声明
本文为[Audio_J]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/ArvinB/p/13953511.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云