博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java框架技术核心基石系列教程(02)——反射技术应用场景剖析
阅读量:1952 次
发布时间:2019-04-27

本文共 4464 字,大约阅读时间需要 14 分钟。


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

反射的定义

Java的反射(Reflection)机制是指在程序运行时动态获取程序信息和动态调用对象的功能。反射是Java实现动态性的关键,其主要作用如下:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时处理注解
  • 在运行时生成动态代理

反射的应用场景

在学习反射之前,我们先来了解反射的应用场景。

插件化编程

在项目的开发过程中使用多个服务(server)处理数据流(data flow),例如:server A、server B、server C;当项目上线之后,需要添加新的服务server D。

图示如下:

在这里插入图片描述

这时候该怎么办呢?此时,我们可利用插件化技术实现该需求。

方案如下:

1、编写服务接口IServer

示意代码如下:

public interface IServer {
public void process(DataPoint point);}

2、服务Server均实现IServer接口

示意代码如下:

public class ServerA implements IServer{
public void process(DataPoint point){
System.out.println("ServerA is processing"); }}public class ServerB implements IServer{
public void process(DataPoint point){
System.out.println("ServerB is processing"); }}public class ServerC implements IServer{
public void process(DataPoint point){
System.out.println("ServerC is processing"); }}

3、编写配置文件

示意代码如下:

project.servers=servers.ServerA, servers.ServerB, servers.ServerC

在配置文件中配置所有的服务的全路径

4、处理数据

示意代码如下:

public class Test{
public static void main(String[] args){
// 读取配置 final String configPath = "config.properties"; Properties properties = ConfigUtils.readProperties(configPath); String p = properties.getProperty("project.servers"); String []tmp = p.split(","); List
svrlist = new ArrayList
(); for(String t: tmp){
svrlist.add(t.trim()); } // 加载servers ArrayList
servers = new ArrayList
(); Iterator
iter = svrlist.iterator(); while(iter.hasNext()){
String str = iter.next(); //生成server IServer server = (IServer) newInstance(str); if(server != null) servers.add(server); } DataPoint point = new DataPoint(); point.setName("point"); point.setValue(1); // servers处理数据 Iterator
iter2 = servers.iterator(); while(iter2.hasNext()){ IServer server = iter2.next(); server.process(point); } } //实例化Server对象 private static Object newInstance(String classname){ try { Class
clazz = Class.forName(classname); Object obj = clazz.newInstance(); return obj; } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }}

要点概述:

  • 1、定义服务接口IServer
  • 2、所有的服务均实现IServer接口
  • 3、在配置文件中配置所有服务的全路径
  • 4、读取配置文件利用反射技术依据服务的全路径字符串创建服务实例
  • 5、服务处理数据

至此,项目开发完毕。不过,没过多久又来了一个新的需求:在原来的基础上新增服务ServerD处理数据流。

方案如下:

第一步:ServerD实现IServer接口

示意代码如下:

public class ServerD implements IServer{
public void process(DataPoint point){
System.out.println("ServerD is processing"); }}

第二步:在配置文件中追加配置ServerD

示意代码如下:

project.servers=servers.ServerA, servers.ServerB, servers.ServerC, servers.ServerD

至此,我们通过插件的方式添加了服务ServerD而不需要修改以往的主程序。在整个插件化编程中最核心的技术就是反射,优势如下:

  • 1、高度灵活,可扩展性较强。
  • 2、新增服务只需要实现暴露的接口。
  • 3、利用反射只需知道新增服务的全路径即可实例化对象。

在开发过程中,不需要事先知道服务Server的名字(其实,很多情况下也无法事先知道);只需要在配置文件中追加配置即可。

服务端编程

看完了插件化编程,我们再来瞅瞅大家熟悉的Tomcat是如何调用Servlet的。在JavaWeb项目中存在众多的Servlet处理各种请求;比如,LoginServlet专门用于处理用户的登录请求;其流程概述如下:

  • 1、编写实现Servlet接口的Servlet类
  • 2、部署并运行程序
  • 3、Tomcat收到浏览器发送的登录请求
  • 4、Tomcat依据请求路径判定由LoginServlet处理该请求
  • 5、Tomcat读取配置文件web.xml获取到LoginServlet的全路径类名
  • 6、Tomcat根据该全路径字符串通过反射创建LoginServlet类的实例
  • 7、LoginServlet类的实例处理用户请求

在整个过程当中,其实现原理和插件化编程有着相似的思路:

  • 1、自定义Servlet类实现服务端暴露的Servlet接口
  • 2、在配置文件中对自定义Servlet进行配置
  • 3、利用反射技术根据自定义Servlet的全路径字符串生成Servlet实例

在整个过程中,不需要事先知道自定义Servlet的名字(其实,很多情况下也无法事先知道);只需要在配置文件中添加相应的配置即可。

作为一个初学者,如果想理解反射的应用场景可以把自己想象成为一个Tomcat,尝试着反问自己一个问题并尝试作答:你知道有哪些项目会部署到Tomcat么?不知道!你根本不知道哪些项目会被部署到Tomcat,你也不知道项目中有哪些请求,你更不知道项目中有哪些Servlet用于处理请求。既然都无法知道有哪些Servlet,更不用说预先通过new的方式创建好Servlet实例用于以后处理各种请求了。所以,作为Tomcat它无法预知有哪些请求,它也无法预知有哪些Servlet处理请求;这些都是未知数。

其实,不管是插件化编程还是服务器编程都属于同一类情况:

  • 1、框架和平台是事先编译好的
  • 2、可通过类的字符串全路径名称实例化对象
  • 3、不需要在编译期依赖业务系统的类和代码

无.java源文件

在某些较为特殊的情况下,没有.java源文件只有.class字节码文件。此时,不能再使用原来new的方式创建对象而可利用.class通过反射方式的方式创建对象。

获取类的所有信息

获取类中的所有信息。例如:属性、成员方法、构造函数、泛型等等。

调用私有属性和方法

普通情况下,我们无法访问对象的私有属性和私有方法。此时,反射是一个非常不错的选择。

反射实现原理概论

当程序完成编译之后,类加载器(ClassLoader)将字节码文件加载进内存并在堆内存的方法区中产生一个Class类型的对象,该对象包含了类的所有信息。 我们可以通过该对象清晰而完整地看到类内部的结构与构成。换句话说, Class对象就像一面镜子映出了类的轮廓。所以, 我们形象地将此过程称之为反射。

其实,从反射的实现原理我们也可摸索出反射技术的学习路径:

  • 1、ClassLoader
  • 2、Class
  • 3、Reflection API
你可能感兴趣的文章
mysql删除表数据恢复
查看>>
Mysql连接数和状态
查看>>
Mysql表被锁的解决
查看>>
oracle删除ASM
查看>>
oracle移动数据文件
查看>>
oracle删除数据文件
查看>>
oracle临时数据文件
查看>>
oracle默认临时表空间
查看>>
Nginx配置SSL证书时——nginx:[emerg]unknown directive ssl错误
查看>>
升级nginx,编译make的时候报undefined reference to `SSL_CTX_set_alpn_select_cb'
查看>>
oracle表空间组
查看>>
升级openssh报 PAM headers not found
查看>>
oracle内存管理的相关初始化参数
查看>>
CentOS8服务器搭建L2TP服务器(over IPsec)操作指南
查看>>
华为模拟器eNSP安装初体验
查看>>
RFC768:用户数据报协议(UDP)
查看>>
RFC791:INTERNET PROTOCOL网络协议
查看>>
RFC7209:以太网VPN(EVPN)的要求
查看>>
虚拟可扩展局域网 (VXLAN):基于三层网络实现二层虚拟化的框架
查看>>
手机端安装步骤构思
查看>>