Java基础—反射与代理(新手向)
第1章 反射与代理
1.1 反射定义
一般情况下,需要一个功能的前提是遇到了某个问题,这里先列举一些问题,然后再通过反射是如何解决了这些问题,来引出反射的定义。
普通开发人员工作中最常见的问题:需要生成代理对象(不清楚代理模式的话,可以简单理解为需要将一个类,在不改变这个类的代码的基础上,要对这个类的功能添加新的逻辑)
解决方式:将需要加强的类,利用反射加载之后,与补充的逻辑进行融合,产生一个新的对象,这个对象就是代理对象,即具备原有类及新逻辑的“增强后的类”(比如 Man 类里面有个 eat() 方法,我们希望执行 eat() 方法前后分别执行洗手、洗碗逻辑,而我们又不能直接去修改eat()方法)
上面是用简洁的方式给出了关于反射的最直白的解释,下面给出较为专业、全面的解释:
反射是什么?
反射(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.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
Java基础—反射与代理(新手向)的更多相关文章
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- Java基础-反射(reflect)技术详解
Java基础-反射(reflect)技术详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.类加载器 1>.JVM 类加载机制 如下图所示,JVM类加载机制分为五个部分 ...
- Java的反射和代理以及注解
最近接触到java的反射和代理(接触的有点迟了...),还是有必要总结下 1. Java的反射 有的时候我们需要在程序运行的时候获取类.方法等信息用于动态运行,这个时候反射就能够帮我们找到类.方法.成 ...
- 利用Java的反射与代理机制实现AOP
在上一篇文章中,我们讲述了利用Java的反射机制中实现Spring中的IOC,在本文中,我们将更进一步,讲述用Java的反射和动态代理机制来实现Spring的AOP. 一.AOP概述 AOP(Aspe ...
- Java基础——反射
今天学到Java基础中的反反射.依照我学习后的个人理解呢,反射就是一套获取类.属性.方法等的工具吧.(其实,感觉学完反射后,有点像喝凉水,解渴但确实我也没体会出它有什么味道,我可能没有学到精髓吧.自己 ...
- Java反射机制详解(3) -java的反射和代理实现IOC模式 模拟spring
IOC(Inverse of Control) 可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”.在Spring中,通过IOC可以将实现类.参数信息等配置在其对应的配置文件中,那么当 需要更 ...
- Java基础反射(二)
原文地址http://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Cla ...
- java基础(反射,注解,多线程,juc)
JAVA基础 java反射 class对象 三种方式获取class加载时对象 1.class.forName("全类名"):将字节码文件加载进内存,返回class对象 2.类名.c ...
- [java 基础]反射入门
原文 概况 使用java的反射,可以让我们检查(或者修改)类,接口,字段,方法的特性.当你在编译期不知道他们的名字的时候非常有用. 除此之外,可以使用反射来创建实例,调用方法或者get/set 字段值 ...
随机推荐
- notepad快捷使用
1.快捷键 参考:https://www.php.cn/tool/notepad/428638.html notepad++是经常使用的一款编辑器软件,在编辑特殊文本的时候(html,java...) ...
- (入门)matlab中创建和调用m文件
大学学过的一款软件,说实话没好好学,老师直接讲到高深的做仿真之类的 综合网上的教程讲述基础的matlab创建遇到的问题: 参考: 1. https://blog.csdn.net/weixin_423 ...
- 如何选择JVM垃圾回收器?
明确垃圾回收器组合 -XX:+UseSerialGC 年轻代和老年代都用串行收集器 -XX:+UseParNewGC 年轻代使用ParNew,老年代使用 Serial Old -XX:+UsePara ...
- linux查看进程内存使用情况,以及将线程情况输出文件
用jmap把进程内存使用情况dump到文件中,再用jhat分析查看.jmap进行dump命令格式如下: jmap -dump:format=b,file=/tmp/dump.dat 21711 -- ...
- day22 Pyhton学习 re模块和正则表达式
正则表达式本身也和python没有什么关系,就是匹配字符串内容的一种规则. 官方定义:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个" ...
- 简单的Linux下的socket通信,小程序,方便以后查看。
首先是我的一个出错提示的头文件<myerr.h>,自从用了根本停不下来啊!!! #ifndef _MYERR_H_ #define _MYERR_H_ #include <stdio ...
- 【C语言/C++程序员编程】一小时做出来的数字雨(一颗开花的树)!
相信大家看过许许多多的关于计算机黑客.骇客.人工智能.AI方面的电影,每当黑客入侵某个五角大楼,某个网站时,都会出现这样一副画面: 入侵 或者这样的: 数字雨 然后就轻而易举的成功入侵夺取管理员权限了 ...
- jmeter_04_常用取样器
目录 常用取样器详解 http取样器 1.1 基本配置 1.2 高级配置 jdbc取样器 2.1 JDBC Connection Configuration 2.1.1 **Variable Name ...
- golang xpath解析网页
https://github.com/antchfx/htmlquery package main import ( "fmt" "github.com/antchfx/ ...
- kinaba 安装踩坑: FATAL Error: [elasticsearch.url]: definition for this key is missing 转
安装 https://www.jianshu.com/p/875457cb8da6 操作系统:Linux kibana 版本: 7.4.0 1. 在/etc/yum.repos.d/ 下新建 ...