序言在我们上一篇文章中,我告诉你如何调试maven插件的代码。注意是插件的代码。插件由主框架执行。谁是主要框架?就是mavencore,可以称之为mavencore。maven核心类似于tomcat,maven插件类似于我们部署在tomcat中的webapp应用。估计有人觉得这个比喻有点生硬,不过我也有自己的依据。下面开始正文。tomcat类分散在哪里?按照简单的模型,就是三个地方:1.bin下的启动类等2.lib下的tomcat核心框架类3.webapp类这个我就不说了,大家公务的那种。下面说说maven和tomcat的相似点,再看看maven的jar包的分散情况。1、启动类在mavenhome的boot目录下2、mavencore3、插件代码分布在本地仓库的目录下。综上所述,这两个框架和执行过程中需要用到的jar包,分散在三个地方。按照我们的理解,执行顺序是:从启动类开始--》加载框架核心代码--》框架加载插件/webapp代码执行。当然大家可以想一想,如果你写这个tomcat和maven,你会怎么做?三种代码,三个地方,肯定是三个类加载器。第一个类加载器只能加载到启动类的包中;要调用框架核心,您是否必须创建一个新的类加载器;框架核心,调用插件/webapp代码,还要加载新疆类设备。中间怎么连接?mavenclean(启动类阶段)到底发生了什么如果我们直接在命令行执行mvnclean,实际上调用了如下命令:这个命令是什么?我之前多年的工作经验告诉我,这是一个二进制,打开肯定是一串乱码;而且之前对maven不好奇,也没去研究。我最近才发现这是一个shell/cmd。原来是java命令??果然,经验主义还是不行,大意了。我这边是windows电脑,要打印出最后的执行命令确实很不方便,所以采用了一些迂回的方法。在我的F:\tools\apache-maven-3.8.1-bin\apache-maven-3.8.1\bin目录中,打开gitbash并用shell执行它:你可以在这里的类路径中看到jar,因为我前面提到,mavenhome的boot目录下的jar,启动类,就在这个jar中。在这里,大家可以想想启动类的目标是什么,加载框架的核心。对于启动类,重点是:框架类的代码在哪里?你是依赖默认协议,还是读取配置文件。答案是配置文件。大家可以看上图,有一个:-Dclassworlds.conf=/f/tools/apache-maven-3.8.1-bin/apache-maven-3.8.1/bin/m2.conf这个文件,我们打开它在这里:主要是org.apache.maven.cli.MavenCli来自plexus.coresetmaven.confdefault${maven.home}/conf[plexus.core]load${maven.conf}/loggingoptionally${maven.home}/lib/ext/*.jarload${maven.home}/lib/*.jar只是一个文本文件。里面好像写了一些似是而非的东西。看不懂,但能看懂一点点。在这里,我摘录一下关键信息,其实就是三点:接下来谁来执政?Thisisfromthelinemainisorg.apache.maven.cli.MavenClifromplexus.core,org.apache.maven.cli.MavenCliisthestarterofnextframeworkcorecodemaven安装目录下的主要配置文件在哪里conf下有我们的settings.xml,大家知道框架的核心代码在哪里,所以让下面的人指定加载${maven.conf}/logging可选${maven.home}/lib/ext/*。jarload${maven.home}/lib/*.jarmavenclean,到底发生了什么(framework核心类阶段)这个阶段内容太多了,${maven.home}/lib/*.jar就有十几个jar包,后面有的是时间再说。我们现在重要的是先理清流程。该框架的核心目标是根据参数找到对应的插件代码,加载进去,然后执行。我们前面传递的参数是clean,其实代表的是clean生命周期中的clean阶段,而在clean阶段,绑定的插件是:maven-clean-plugin。我在哪里可以找到这个插件的代码?这一次,正是Maven约定优于配置的理念的体现。不使用配置文件。插件和我们的业务依赖一样,都是放在本地仓库的。如果本地仓库找不到,就去远程中央仓库下载。这里,我们本地已经有了:拿到jar之后,我们创建一个插件专用的classloader来加载插件的jar和插件依赖的jar。哪里可以看到插件依赖的jar?在这个插件的描述文件中,描述文件就是下面这个,描述了插件的方方面面,比如可以执行哪些目标,目标的参数是什么。当然,还包括插件所依赖的jar。插件依赖于:当mavenclean时,发生了什么(插件由框架核心执行)框架被执行。为什么叫:待执行。也就是说,所有的控制逻辑都在框架的核心。至于插件,一定要遵循规范,谁的规范,框架核心的规范,规范是什么。是框架核心设置的一个接口:publicinterfaceMojo{//插件逻辑写在这里面voidexecute()throwsMojoExecutionException,MojoFailureException;voidsetLog(Logvar1);loggetLog();}clean插件的实现逻辑:框架核心做的事情是加载org.apache.maven.plugin.clean.CleanMojo,然后强制向上转型为Mojo,然后优雅地使用多态执行execute方法,调用插件的实际逻辑。以上maven运行过程中的几个类加载器实例赏析。我在插件里sleep了1000秒,然后执行jmap-dump:live,format=b,file=heap16380.bin16380(16380是我maven的java进程.pid)dumpheap后分析为平时看堆中有哪些类加载器:一共有18个,挺多的。然而,其中许多是不必要的。上图中,我们只关注三个:1、启动时的加载器——AppClassloader2、框架核心类加载器,我们可以看到,确实是lib下的jar。3.插件类加载器可以看到,插件jar是加载到本地仓库中的。综上所述,我想说说maven框架核心调试环境的搭建。结果,我来到了这里。毕竟这个不说清楚,就没法交代环境搭建。.环境搭建等部分,见上文。本文由博客多发平台OpenWrite发布!
