我是靠谱客的博主 慈祥钢笔,最近开发中收集的这篇文章主要介绍Dubbo源码学习(一):dubbo如何检查重复的jar包和获取当前dubbo版本号,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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版本号所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部