SpringBoot学习笔记(一):POM和Maven插件

来源:互联网 发布:软件大全官方网站 编辑:程序博客网 时间:2024/06/16 04:02

POM依赖逻辑和管理(可作为学习Maven的案例教材)

一、spring-boot-starter-parent(POM) : parent引用spring-boot-dependencies


作为打算使用SpringBoot进行开发的私人项目的父类POM引入

 

这样项目若想使用spring-boot-starter-web则只需依赖spring-boot-start-web,其版本由spring-boot-depenencies指定

 

同时提供了大量的内部属性和插件,用以构建项目和使用项目

 

所以这个POM的作用类似于一个使用SpringBoot入口


二、spring-boot-dependencies(POM) : 无parent引用、无import继承

 

管理了大量的propertiesdependencyManagement及插件

 

作用是统一管理了SpringBoot框架项目本身开发的模块及版本号;构建这些子模块依赖的第三方库和插件。

 

这个POMSpringBoot框架项目最顶层的管理POM,被spring-boot项目本身和私人项目所引用。

例如,

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

<version>1.5.8.RELEASE</version>

</dependency>


三、spring-boot-starter(POM):parent引用spring-boot-starter-parent

 

spring-boot-starter-xxx所依赖的父类POM,这个是描述整个spring-boot-start项目的描述POM

其中的modules定义了项目的模块:spring-boot-start-xxx

 

其目的是为了构建各个模块(子库)spring-boot-starter-xxx

 

各模块的版本,及开发所依赖的子modules和第三方库,则由spring-boot-starter-parent-->spring-boot-dependencies统一管理

 

所以这个POM代表了这个spring-boot框架的构成部分,即modules,即spring-boot-starter-xxx


四、spring-boot-starter-xxx(jar)和spring-boot-xxx(jar)

 

parent是spring-boot-starter\spring-boot-parent

 

SpringBoot框架的子模块,默认pacakge类型是jar

 

可以理解成build-path中使用的jar包


SpringBoot的理念就是为了给码农一种全新体验的开发方式。


插件管理和使用方法(抛砖引玉版)

五、插件管理

 

SpringBoot使用spring-boot-maven-plugin,提供了“约定大于配置”的构建体系

 (先解压缩fat-jar或者 jar tvf ***.jar,观察里面的结构)

1、构建一个fat-jar

2、添加spring-boot-loader相关的字节码

3、定义fat-jar结构

4、结构为:BOOT-INFO,META-INFO,提供spring-boot-loader功能的字节码

5、Jar启动的Main-Class为JarLauncher

 

问题1:需要详细阅读spring-boot-maven-plugin的源码(plugin.xml),理解repackage流程

问题2:通过 mvn dependency:tree或者eclipse插件查看工程依赖树,没有发现有对artifactId为spring-boot-loader构建的依赖,但是解压fat-jar后,在BOOT-INFO/lib却发现了这个jar包

Maven插件RepackageMojo的过程:

privatevoid repackage() throws MojoExecutionException {

//maven默认打包的jar文件

File source = this.project.getArtifact().getFile();

 

//获取目标jar文件

File target = getTargetFile();

 

//根据原始jar-original,定义Repackage方案对象

Repackager repackager = getRepackager(source);

 

//获取项目的依赖

Set<Artifact> artifacts =filterDependencies(this.project.getArtifacts(),

getFilters(getAdditionalFilters()));

Libraries libraries = new ArtifactsLibraries(artifacts,this.requiresUnpack,

getLog());

 

try {

//获取执行脚本,脚本文件在spring-boot-loader-tools包中

LaunchScript launchScript = getLaunchScript();

 

//执行repackage流程

repackager.repackage(target, libraries, launchScript);

}

catch (IOException ex) {

throw new MojoExecutionException(ex.getMessage(), ex);

}

updateArtifact(source, target, repackager.getBackupFile());

}

Repackage类中的过程:过程还是比较简单的,直接跳到最后一步

privatevoid repackage(JarFile sourceJar, JarWriter writer,

final List<Library> unpackLibraries, final List<Library>standardLibraries)

throws IOException {

 //这里就是META-INFO里面的MANIFEST.MF最终的形式了

writer.writeManifest(buildManifest(sourceJar));

Set<String> seen = new HashSet<String>();


//函数传递进来的List<Library>分为两类,一类是需要unpack,为了让fat-jar能直接 java -jar运行

writeNestedLibraries(unpackLibraries, seen, writer);

if (this.layout instanceof RepackagingLayout) {

writer.writeEntries(sourceJar, new RenamingEntryTransformer(

((RepackagingLayout) this.layout).getRepackagedClassesLocation()));

}

else {

writer.writeEntries(sourceJar);

}

writeNestedLibraries(standardLibraries, seen, writer);


//这里添加了spring-boot-loader

writeLoaderClasses(writer);

}


/**
* Write the required spring-boot-loader classes to the JAR.
* @param loaderJarResourceName the name of the resource containing the loader classes
* to be written 默认是NESTED_LOADER_JAR:META-INF/loader/spring-boot-loader.jar
* @throws IOException if the classes cannot be written
*/

@Override
public void writeLoaderClasses(String loaderJarResourceName) throws IOException {
URL loaderJar = getClass().getClassLoader().getResource(loaderJarResourceName);
JarInputStream inputStream = new JarInputStream(
new BufferedInputStream(loaderJar.openStream()));
JarEntry entry;
while ((entry = inputStream.getNextJarEntry()) != null) {
if (entry.getName().endsWith(".class")) {
writeEntry(entry, new InputStreamEntryWriter(inputStream, false));
}
}
inputStream.close();
}


spring-boot-maven-plugin总结:

这个maven第三方插件(有时间需要好好学习maven插件的开发),主要用的类和流程框架是spring-boot-loader-tools,正如插件的POM依赖描述的那样

spring-boot-loader-tools定义了reapacke目标所用到的接口流程

例如问题1中的spring-boot-loader这个jar,其实是在放在了spring-boot-loader-toolsjar中被打包发布


还有分析中提到的LaunchScript