概述
hi,乡亲们好:
菜鸟最近打算学习一下dubbo背后的实现,但又不知道从哪里看起。幸好有位大牛提供了思路。于是就有了第一篇文章,后续还会更新哒!
一、提出疑问:
(1).Dubbo是利用什么来检查项目中是否出现重复的jar包?
(2).Dubbo又是如何来获取项目中的dubbo版本号呢?
- 带着这两个疑问首先找到代码的入口:在dubbo-config子工程中的org.apache.dubbo.config.spring.schema包中的DubboNamespaceHandler类中的静态代码块中,而该类又继承了spring-bean的NamespaceHandlerSupport,至于为什么要集成它,下一篇文章再陈述。
//防痴设计来检查是否有重复的jar包 @link:https://blog.csdn.net/youling_lh/article/details/11829779
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
- 在Version类中,主要的两个方法分别是:getVersion(Class<?> cls, String defaultVersion)和checkDuplicate(String path, boolean failOnError)
getVersion(Class<?> cls, String defaultVersion)
checkDuplicate(String path, boolean failOnError)
(3).先说一下checkDuplicate(String path, boolean failOnError)这个方法实现,该方法就是检查是否存在重复的jar包:
-
首先将Version这个类作为唯一的标识,获取项目中的Version这个类的文件路径,然后再新建一个SET集合,将获取到的路径放判断是否还有更多的节点,如果有则获取下一个节点,当节点不为空时;再将url对象放入set集合中;为什么要这么做,因为项目中如果出现了重复的jar包,那么就会出现两个Version类,而实际正确情况只能有一个jar包。当两个jar包在不同的路径时,放入不可重复,不能为空的set集合中,如果set的size大于1则说明有重复的jar包。以下是实现的代码:
/**
* 获取dubbo的版本和检查是否有重复的类,检查是否存在重复的jar包
* @param path
* @param failOnError
*/
public static void checkDuplicate(String path, boolean failOnError) {
try {
Enumeration<URL> urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path);
Set<String> files = new HashSet<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String file = url.getFile();
if (file != null && file.length() > 0) {
files.add(file);
}
}
}
// duplicated jar is found
if (files.size() > 1) {
String error = "Duplicate class " + path + " in " + files.size() + " jar " + files;
if (failOnError) {
throw new IllegalStateException(error);
} else {
logger.error(error);
}
}
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
- Enumeration接口中定义了一些方法,通过这些方法可以枚举(一次获得一个)对象集合中的元素。
- 大家可以自己在本地测试一下:
@Test
public void getFile() throws Exception {
Enumeration<URL> urls = ClassHelper.getCallerClassLoader(JsonResult.class).getResources(JsonResult.class.getName().replace('.', '/') + ".class");
System.out.println("urls is {}"+JSON.toJSONString(urls));
}
输出的是:urls is {}["file:/Users/zjc/Documents/github-sources/springboot-mybatis/target/classes/com/zjc/springboot/common/JsonResult.class"]
(4).然后说一下getVersion(Class<?> cls, String defaultVersion)这个方法实现,该方法就是获取dubbo的版本号:
- 首先是查找MANIFEST.MF规范中的版本号,如果这时候得到了版本号则会直接返回当前的版本号;如果规范中没有版本号则会基于jar包名获取版本号。如果这时也没有获取到版本号,则会返回默认的版本号为"";如果获取到了则会得到jar包的路径path,判断path是否以".jar"结尾,然后根据lastIndexOf()和indexOf()方法,得出版本号(jar包一般是项目名,加上一个“-”,后面再加上数字版本号),一下是实现的代码:
public static String getVersion(Class<?> cls, String defaultVersion) {
try {
// find version info from MANIFEST.MF first
// 先从MANIFEST.MF文件中的版本号 jar文件中必然存在MANIFEST.MF文件;
String version = cls.getPackage().getImplementationVersion();
if (version == null || version.length() == 0) {
//此方法返回执行的版本
version = cls.getPackage().getSpecificationVersion();
}
if (version == null || version.length() == 0) {
// guess version fro jar file name if nothing's found from MANIFEST.MF
CodeSource codeSource = cls.getProtectionDomain().getCodeSource();
if (codeSource == null) {
logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion);
} else {
//得到jar文件
String file = codeSource.getLocation().getFile();
if (file != null && file.length() > 0 && file.endsWith(".jar")) {
file = file.substring(0, file.length() - 4);
int i = file.lastIndexOf('/');
if (i >= 0) {
file = file.substring(i + 1);
}
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
}
while (file.length() > 0 && !Character.isDigit(file.charAt(0))) {
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
} else {
break;
}
}
version = file;
}
}
}
// return default version if no version info is found
return version == null || version.length() == 0 ? defaultVersion : version;
} catch (Throwable e) {
// return default version when any exception is thrown
logger.error("return default version, ignore exception " + e.getMessage(), e);
return defaultVersion;
}
}
Version类中除了当前这两个方法,其它都是些辅助的方法,在这里不做过多的解释。下一篇将学习一下,Dubbo是如何来解析XMl配置文件的,是如何寻找注册中心、服务提供者、服务消费者功能入口。也就是说为什么前面说DubboNamespaceHandler继承NamespaceHandlerSupport;
最后
以上就是慈祥钢笔为你收集整理的Dubbo源码学习(一):dubbo如何检查重复的jar包和获取当前dubbo版本号的全部内容,希望文章能够帮你解决Dubbo源码学习(一):dubbo如何检查重复的jar包和获取当前dubbo版本号所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复