maven启动脚本mvn.bat,借助于Plexus容器启动,Plexus提供完整的软件栈,用于创建和执行软件项目,是IoC框架,和spring类似
有兴趣想了解Plexus的,可以在github上下载代码,https://github.com/codehaus/plexus.git
boot目录下的plexus-classworlds-2.5.2.jar文件就是Plexus包
set CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
%MAVEN_JAVA_EXE%%MAVEN_OPTS% -classpath %CLASSWORLDS_JAR%
"-Dclassworlds.conf=%M2_HOME%\bin\m2.conf"
"-Dmaven.home=%M2_HOME%"%CLASSWORLDS_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
m2.conf配置文件
main isorg.apache.maven.cli.MavenCli from plexus.core
setmaven.home default ${user.home}/m2
[plexus.core]
optionally${maven.home}/lib/ext/*.jar
load ${maven.home}/lib/*.jar
load ${maven.home}/conf/logging
org.apache.maven.cli.MavenCli类就是maven启动的入口方法,Plexus通过读取m2.conf配置文件,反射invoke,org.apache.maven.cli.MavenCli类的main方法
try
{
initialize( cliRequest );//初始化工作目录变量,以及maven.home变量
cli( cliRequest );// 解析commandLine参数
logging( cliRequest );//配置日志,是否-X开启debug日志,是否-q只显示错误日志
version( cliRequest );//打印maven版本信息
properties( cliRequest );//装载systemProperties、userProperties、buildProperties
localContainer = container(cliRequest );//创建IoC容器,并获取maven等必要类实例
commands( cliRequest );//打印部分状态信息
settings( cliRequest );//加载settings.xml文件,包含globalsettings和user settings,然后进行merge合并
populateRequest( cliRequest );//装配请求对象
encryption( cliRequest );//deploy时候需要setting.xml里面存明文密码,此处可以把密码加密保存
repository( cliRequest );//处理是否使用LegacyLocalRepository仓库
return execute( cliRequest );//真正执行的地方
}
catch ( ExitException e )
{
return e.exitCode;
}
下面主要分析下DefaultMaven类中doExecute方法
1. 初始化属性
2. 验证本地仓库目录是否存在或是否可以访问
validateLocalRepository(request );
3. 创建RepositorySystemSession,带有authentication,mirror, proxy和其它系统环境信息
newRepositorySession(request ) ;
4. 创建MavenSession,带有容器,RepositorySystemSession,请求对象,返回结果对象
newMavenSession( container, repoSession, request, result );
5. 执行AbstractLifecycleParticipant.afterSessionStart(session)
6. 获取依赖的项目,检查是否有pom错误
projects= getProjectsForMavenReactor( session );
validateProjects(projects );
7. 创建ProjectDependencyGraph,带有剪裁反应堆,如:-pl,-rf
//获取经过依赖关系进行排序之后的模块结合
activeProjects= projectDependencyGraph.getSortedProjects();
//获取-pl指定的以及所依赖的
activeProjects= trimSelectedProjects( activeProjects, projectDependencyGraph, request );
//排除指定的模块-pl !xxx
activeProjects= trimExcludedProjects( activeProjects, request );
//从-rf指定的模块开始
activeProjects= trimResumedProjects( activeProjects, request );
8. 创建ReactorReader,用于查找maven反应堆模块
reactorWorkspace= container.lookup( WorkspaceReader.class, ReactorReader.HINT );
9. 执行AbstractLifecycleParticipant.afterProjectsRead(session)
10. 创建ProjectDependencyGraph,不带剪裁
11. 执行LifecycleStarter.start(),开始执行生命周期任务
lifecycleStarter.execute(session );
分析LifecycleStarter类中,execute方法
//计算任务,如:clean,package,install,deploy
taskSegments= lifecycleTaskSegmentCalculator.calculateTaskSegments( session );
//计算执行任务的模块,就是哪些模块需要执行以上任务
projectBuilds= buildListCalculator.calculateProjectBuilds( session, taskSegments );
//执行任务,内部两层循环,依据任务列表和模块列表循环执行
builder.build(session, reactorContext, projectBuilds, taskSegments, reactorBuildStatus );
以下是calculateProjectBuilds方法执行的结果:
[DEBUG]=== REACTOR BUILD PLAN ================================================
[DEBUG]Project: org.apache.maven:maven:pom:3.2.5
[DEBUG]Tasks: [clean]
[DEBUG]Style: Regular
[DEBUG]-----------------------------------------------------------------------
[DEBUG]Project: org.apache.maven:maven-model:jar:3.2.5
[DEBUG]Tasks: [clean]
[DEBUG]Style: Regular
[DEBUG]-----------------------------------------------------------------------
…
…
…
[DEBUG]Project: org.apache.maven:apache-maven:pom:3.2.5
[DEBUG]Tasks: [clean]
[DEBUG]Style: Regular
[DEBUG] =======================================================================
下一步则是DefaultBuildPluginManager类中executeMojo()方法执行具体的mojo插件的execute方法:mojo.execute();
publicinterface Mojo
{
String ROLE = Mojo.class.getName();
void execute() throws MojoExecutionException,MojoFailureException;
void setLog( Log log );
Log getLog();
}
maven插件开发,需要继承AbstractMojo类,而此类则实现了Mojo接口。