《跟二师兄学Nacos吧》EXT-03篇 Nacos中此处为什么采用反射机制?

简介: 《跟二师兄学Nacos吧》EXT-03篇 Nacos中此处为什么采用反射机制?

学习不用那么功利,二师兄带你从更高维度轻松阅读源码~

大家可能看到过很多写Java反射机制的文章,但如果在阅读源码的过程中,遇到反射机制的使用,你是否想过为什么要这么用吗?

这篇文章就带大家来看看Nacos中对Java反射机制的一处实践案例。这篇文章既属于知识点的分析,也属于Nacos设计层面的分析。

Nacos中反射机制实践

先来介绍一下Nacos反射机制使用的背景。

nacos-client项目中,可以通过NacosFactory获得NamingService,然后基于NamingService来进行服务实例的注册功能:

NamingService namingService = NacosFactory.createNamingService(properties);
namingService.registerInstance("nacos.test.1", instance);

而在NacosFactory中又是基于NamingFactory来实现NamingService的创建的:

public static NamingService createNamingService(Properties properties) throws NacosException {
    return NamingFactory.createNamingService(properties);
}

NamingFactory具体创建部分代码如下:

public static NamingService createNamingService(Properties properties) throws NacosException {
    try {
        Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.naming.NacosNamingService");
        Constructor constructor = driverImplClass.getConstructor(Properties.class);
        return (NamingService) constructor.newInstance(properties);
    } catch (Throwable e) {
        throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
    }
}

到这里,终于看到了反射机制的使用了,通过Class#forName方法获取Class对象,然后获取构造方法,创建实例。

如果你阅读源码时只看到这些,可能你会错过一些有意思的设计和事情。你是否思考过,为什么这里要采用反射机制呢?直接new一个对象不行吗?

在解答上述问题之前,我们先来简单科普一下Java发反射机制。

Java反射机制

这里从基本概念、原理、简单实践说起。

Java反射简介

Java是预编的语言,对象的类型在编译期已经确定。在程序运行时可能需要动态加载某些类,这些类之前用不到,所以就没有被加载到JVM中。需要时,可通过反射在运行时动态地创建对象并调用其属性或方法,而不需要在编译期就知道运行的对象是谁。

Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而能够操作类或对象的属性和方法。

Java反射的优缺点

Java反射的优点:

  • 增加程序的灵活性,避免将程序写死到代码里;
  • 代码简洁,提高代码的复用率,外部调用方便;
  • 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;

反射的原理

在了解反射的基本原理之前,我们需要知道在Java程序编译完成之后,会把所有class文件中所包含的类的基本元信息装载到JVM内存中,以Class类的形式保存。Class类可理解为描述类的类,每一个Class类对象代表一个具体类的基本元信息。反射就是在Class类的基础上进行的,Class类对象存储着类的所有相关信息。image.png关于JVM内部的操作步骤,我们这里不做拓展。需要了解的就是Class对象是JVM加载.class文件之后生成的对象,而反射机制提供了获取该对象,可以基于此进行属性访问或对象构造。而这一步是发生在运行时期间。

反射的基本使用

通常使用反射有三种方式:

// 方式一:使用Class.forName静态方法
Class clz = Class.forName("java.lang.String");
// 方式二:使用.class方法
Class clz = String.class;
// 方式三:使用类对象的getClass()方法
String str = new String("Hello");
Class clz = str.getClass();

上述三种方式,一般常用第一种,字符串参数可以传入也可以写在配置文件中。第二种需要导入类包,依赖太强,不导包就抛编译错误。第三种对象都有了还要反射干什么。

所以说,通常我们学习的时候,知道了很多种方式,而真正使用时,还是需要根据场景进行选择。而Nacos的源码中就采用了第一种的方式。

关于反射的其他API的使用此处就不再展开了,下面回到主题,来思考一下Nacos为什么使用反射,同时为什么采用第一种方式。

Nacos反射机制原理分析

在分析之前,我们先来看一下项目结构。首先,nacos-client项目依赖于nacos-aip项目,NamingFactory和NamingService位于nacos-api项目当中。而具体被实例化的对象类com.alibaba.nacos.client.naming.NacosNamingService,很明显位于nacos-client当中。image.png通过上图我们可以看到,NamingFactory中实现了NamingService的实例化业务逻辑,但此时nacos-api项目并没有NacoNamingService,也就无法采用上面提到的其他两种方法,只能通过Class.forName方式来进行实现了。

其实这里的设计与数据库驱动程序类似,nacos-api中通过NamingService定义了一个接口,也就是定义了一个标准。而nacos-client中实现了这个标准,并且还要满足两个条件:第一,该实现类实现自NamingService;第二,该类的全路径名要与NamingFactory中的实例化对象时的名称一样。

回头再仔细想象,Nacos的用法,也不正是反射机制很典型的使用场景之一吗?

小结

本文从Nacos的反射机制出发,深入思考提出问题,并简单介绍了Java的反射机制。最终进一步分析Nacos项目结构,解答了最开始的疑问。你会如此阅读源代码吗?你学到了吗?赶紧关注上车!后续更多干货输出。

目录
相关文章
|
9月前
|
监控 关系型数据库 MySQL
Nacos架构与原理 - 健康检查机制
Nacos架构与原理 - 健康检查机制
204 0
|
2月前
|
Nacos
Nacos注册中心的心跳机制
Nacos注册中心的心跳机制
|
2月前
|
存储 JSON Java
Nacos心跳机制解读(含简单源码分析)
Nacos心跳机制解读(含简单源码分析)
|
9月前
|
关系型数据库 MySQL Nacos
Nacos实战(19)-Nacos健康检查机制:保障你的服务稳定运行!
Nacos实战(19)-Nacos健康检查机制:保障你的服务稳定运行!
329 0
|
11月前
|
Java Nacos 微服务
nacos的心跳机制详解
nacos的心跳机制详解
398 0
|
11月前
|
存储 缓存 Java
Nacos 和 Apollo中的 长轮询 定时机制,太好用了
今天这篇文章来介绍一下Nacos配置中心的原理之一:长轮询机制的应用 为方便理解与表达,这里把 Nacos 控制台和 Nacos 注册中心称为 Nacos 服务器(就是 web 界面那个),我们编写的业务服务称为 Nacso 客户端; Nacos 动态监听的长轮询机制原理图,本篇将围绕这张图剖析长轮询定时机制的原理:
|
12月前
|
存储 SpringCloudAlibaba Kubernetes
springCloudAlibaba组件-Nacos-服务注册与心跳机制(二)
springCloudAlibaba组件-Nacos-服务注册与心跳机制(二)
|
12月前
|
设计模式 程序员 Nacos
Nacos 服务端健康检查及客户端服务订阅机制源码分析(三)(下)
Nacos 服务端健康检查及客户端服务订阅机制源码分析(三)(下)
115 0
|
12月前
|
存储 缓存 网络协议
Nacos 服务端健康检查及客户端服务订阅机制源码分析(三)(上)
Nacos 服务端健康检查及客户端服务订阅机制源码分析(三)
162 0
|
Nacos
Nacos配置中心之服务端长轮询处理机制
Nacos配置中心之服务端长轮询处理机制
829 0