这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其所以然。

1.插件保存在哪里?

与我们所依赖的构件一样,插件也是基于坐标保存在我们的Maven仓库当中的。在用到插件的时候会先从本地仓库查找插件,如果本地仓库没有则从远程仓库查找插件并下载到本地仓库。

与普通的依赖构件不同的是,Maven会区别对待普通依赖的远程仓库与插件的远程仓库。前面提到的配置远程仓库只会对普通的依赖有效果。当Maven需要的插件在本地仓库不存在时是不会去我们以前配置的远程仓库查找插件的,而是需要有专门的插件远程仓库,我们来看看怎么配置插件远程仓库,在pom.xml加入如下内容:

 <pluginRepositories>
         <pluginRepository>
             <id>nexus</id>
             <name>nexus</name>
             <url>http://192.168.0.70:8081/content/groups/public/</url>
             <releases>
                 <enabled>true</enabled>
             </releases>
             <snapshots>
                 <enabled>true</enabled>
             </snapshots>
         </pluginRepository>
 </pluginRepositories>

大家可以发现,除了pluginRepositories和pluginRepository与以前配置远程仓库不同以外,其他的都是一样的,所代表的含义也是一样的。Maven的父POM中也是有内置一个插件仓库的,我现在用的电脑安装的是Maven 3.0.4版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。

我们来看看默认的远程插件仓库配置的是啥:

 <pluginRepositories>
     <pluginRepository>
       <id>central</id>
       <name>Central Repository</name>
       <url>http://repo.maven.apache.org/maven2</url>
       <layout>default</layout>
       <snapshots>
         <enabled>false</enabled>
       </snapshots>
       <releases>
         <updatePolicy>never</updatePolicy>
       </releases>
     </pluginRepository>
 </pluginRepositories>

默认插件仓库的地址就是中央仓库咯,它关闭了对snapshots的支持,防止引入snapshots版本的插件而导致不稳定的构件。一般来说,中央仓库所包含的插件完全能够满足我们的需要,只有在少数情况下才要配置,比如项目的插件无法在中央仓库找到,或者自己编写了插件才会配置自己的远程插件仓库。

2.插件命令运行解析

我们来看这样一个命令:

mvn compiler:compiler

这个命令会调用maven-compiler-plugin插件并执行compiler目标,大家有木有觉得很神奇?我们在pom.xml中配置插件往往是这样:

         <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-compiler-plugin</artifactId>
             <version>3.1</version>
             <configuration>
                 <source>1.7</source> <!-- 源代码使用的开发版本 -->
                 <target>1.7</target> <!-- 需要生成的目标class文件的编译版本 -->
             </configuration>
         </plugin>    

maven-compiler-plugin插件默认执行的目标为compiler,那么命令的完整写法应该是:mvn org.apache.maven.plugins:maven-compiler-plugin:3.1:compiler才对啊,为什么mvn compiler:compiler也能完美的执行?

我们来看看Maven到底干了些神马来做到如此牛逼的功能:

①插件默认groupId

Maven默认以org.apache.maven.plugins作为groupId,到这里我们的命令应该是长这样的:

mvn org.apache.maven.plugins:compiler:compiler

我们也可以配置自己默认的groupId,在Maven的settings.xml中添加如下内容,前面提过最好将settings.xml放在用户目录的.m2下:

 <pluginGroups>
     <!-- pluginGroup
      | Specifies a further group identifier to use for plugin lookup.
     <pluginGroup>com.your.plugins</pluginGroup>
     -->
     <pluginGroup>com.your.plugins</pluginGroup>
 </pluginGroups>

不过说实在的,没必要动他就别去动他了,我们用Maven只是解决一些刚需的问题,没必要的设置就尽量不去动他,别把Maven搞得太复杂,虽然Maven的却有点小复杂,跟大家扯这些只是希望大家能够对maven理解的更深入那么一点点,并不是建议大家一定要去使用某些东西,大家在平时的开发中要谨记这一点。

②我们来看看Maven插件远程仓库的元数据org/apache/maven/plugins/maven-metadata.xml,Maven默认的远程仓库是http://repo.maven.apache.org/maven2/,所有插件元数据路径则是:http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml,我们找到compiler插件的元数据,如图:

这里会根据prefix指定的前缀找到对应的artifactId,到这里我们的命令应该长成了这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:compiler

③我们再根据groupId和artifactId找到maven-compiler-plugin插件单个的元数据,路径为http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/maven-metadata.xml,如图:

maven将所有的远程插件仓库及本地仓库元数据归并后,就能找到release的版本(maven3后为了保证项目构建的稳定性默认使用release版本),到这里命令就被扩展成为这样:

mvn org.apache.maven.plugins:maven-compiler-plugin:3.6.0:compiler

如果执行的是mvn compiler:compiler命令,由于maven-compiler-plugin的最新版本已经到了3.6.0,则默认会使用此版本。最后的compiler则是插件要执行的目标咯,看到这里大家应该明白mvn compiler:compiler命令为什么能够得到完美的运行了吧。

3.Maven超级POM

最后给大家把超级父POM贴出来,再次强调,如果我们没有在自己的pom.xml中配置相应的内容,则默认会使用超级父POM配置的内容。我现在用的电脑安装的是Maven 3.0.4版本,我们可以找到这个文件:${M2_HOME}/lib/maven-model-builder-3.0.4.jar,打开该文件,能找到超级父POM:\org\apache\maven\model\pom-4.0.0.xml,它是所有Maven POM的父POM,所有Maven项目都继承该配置。

 <?xml version="1.0" encoding="UTF-8"?>

 <!--
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 -->

 <!-- START SNIPPET: superpom -->
 <project>
   <modelVersion>4.0.0</modelVersion>

   <repositories>
     <repository>
       <id>central</id>
       <name>Central Repository</name>
       <url>http://repo.maven.apache.org/maven2</url>
       <layout>default</layout>
       <snapshots>
         <enabled>false</enabled>
       </snapshots>
     </repository>
   </repositories>

   <pluginRepositories>
     <pluginRepository>
       <id>central</id>
       <name>Central Repository</name>
       <url>http://repo.maven.apache.org/maven2</url>
       <layout>default</layout>
       <snapshots>
         <enabled>false</enabled>
       </snapshots>
       <releases>
         <updatePolicy>never</updatePolicy>
       </releases>
     </pluginRepository>
   </pluginRepositories>

   <build>
     <directory>${project.basedir}/target</directory>
     <outputDirectory>${project.build.directory}/classes</outputDirectory>
     <finalName>${project.artifactId}-${project.version}</finalName>
     <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
     <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
     <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
     <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
     <resources>
       <resource>
         <directory>${project.basedir}/src/main/resources</directory>
       </resource>
     </resources>
     <testResources>
       <testResource>
         <directory>${project.basedir}/src/test/resources</directory>
       </testResource>
     </testResources>
     <pluginManagement>
       <!-- NOTE: These plugins will be removed from future versions of the super POM -->
       <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) -->
       <plugins>
         <plugin>
           <artifactId>maven-antrun-plugin</artifactId>
           <version>1.3</version>
         </plugin>
         <plugin>
           <artifactId>maven-assembly-plugin</artifactId>
           <version>2.2-beta-5</version>
         </plugin>
         <plugin>
           <artifactId>maven-dependency-plugin</artifactId>
           <version>2.1</version>
         </plugin>
         <plugin>
           <artifactId>maven-release-plugin</artifactId>
           <version>2.0</version>
         </plugin>
       </plugins>
     </pluginManagement>
   </build>

   <reporting>
     <outputDirectory>${project.build.directory}/site</outputDirectory>
   </reporting>

   <profiles>
     <!-- NOTE: The release profile will be removed from future versions of the super POM -->
     <profile>
       <id>release-profile</id>

       <activation>
         <property>
           <name>performRelease</name>
           <value>true</value>
         </property>
       </activation>

       <build>
         <plugins>
           <plugin>
             <inherited>true</inherited>
             <artifactId>maven-source-plugin</artifactId>
             <executions>
               <execution>
                 <id>attach-sources</id>
                 <goals>
                   <goal>jar</goal>
                 </goals>
               </execution>
             </executions>
           </plugin>
           <plugin>
             <inherited>true</inherited>
             <artifactId>maven-javadoc-plugin</artifactId>
             <executions>
               <execution>
                 <id>attach-javadocs</id>
                 <goals>
                   <goal>jar</goal>
                 </goals>
               </execution>
             </executions>
           </plugin>
           <plugin>
             <inherited>true</inherited>
             <artifactId>maven-deploy-plugin</artifactId>
             <configuration>
               <updateReleaseInfo>true</updateReleaseInfo>
             </configuration>
           </plugin>
         </plugins>
       </build>
     </profile>
   </profiles>

 </project>
 <!-- END SNIPPET: superpom -->

很多插件是超级父POM当中并没有配置的,如果用户使用某个插件时没有设定版本,那么则会根据我上述所说的规则去仓库中查找可用的版本,然后做出选择。在Maven2中,插件的版本会被解析至latest。也就是说,当用户使用某个非核心插件且没有声明版本的时候,Maven会将版本解析为所有可用仓库中的最新版本,latest表示的就是最新版本,而这个版本很有可能是快照版本。

当插件为快照版本时,就会出现潜在的问题。昨天还好好的,可能今天就出错了,其原因是这个快照版本发生了变化导致的。为了防止这类问题,Maven3调整了解析机制,当插件没有声明版本的时候,不再解析至latest,而是使用release。这样就避免了由于快照频繁更新而导致的不稳定问题。但是这样就好了吗?不写版本号其实是不推荐的做法,例如,我使用的插件发布了一个新版本,而这个release版本与之前的版本的行为发生了变化,这种变化依然可能导致我们项目的瘫痪。所以使用插件的时候,应该一直显式的设定版本,这也解释了Maven为什么要在超级父POM中为核心插件设定版本咯。

结束语:当你感到悲哀痛苦时,最好是去学些什么东西,学习会使你从悲哀痛苦中走出来,学习会使你永远立于不败之地。说实在的,不要太在意眼前所发生的一切,更重要的是培养自己的个人能力,如今待在公司亦或者跳槽,决定你能不能继续走下去的一定是你的个人能力,作为年轻人,在公司更看重的不应该是薪水的高低,而是公司能给你带来多大的成长环境。找个好的公司其实不比找个合适的女朋友简单,作为年轻人我们一定要不断的提升个人能力,就跟找女朋友似的,往往就是你越有本事就越能够不将就,你个人能力越强则越有选择公司的资本。

可爱博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文出自博客园,欢迎大家加入博客园。

(十三)Maven插件解析运行机制的更多相关文章

  1. Maven 教程(13)— Maven插件解析运行机制

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79551210 这里给大家详细说一下Maven的运行机制,让大家不仅知其然,更知其 ...

  2. 使用Apache Tomcat Maven插件部署运行 Web 项目

    什么是Apache Tomcat Maven Plugin? Maven Plugin 是Apache Tomcat 提供的一个Maven插件,它可以在你没有tomcat容器时将任何一个war项目文件 ...

  3. Maven之(三)Maven插件

    Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,像编译是通过maven-compile-plugin实现的.测试是通过maven-surefire-p ...

  4. 3.Maven之(三)Maven插件

    转自:https://yq.aliyun.com/ziliao/312162 Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,像编译是通过maven- ...

  5. [maven] 常用插件解析

    参考资料:http://my.oschina.net/zh119893/blog/276090 我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完 ...

  6. 第二节:Maven的运行机制

    Maven 的运行机制分为两个分别是生命周期和插件 首先我们来说说Maven的生命周期 1.1:生命周期是个个阶段组成的 1.2:Maven的生命周期是相互独立的,他们之间没有交集 1.3:阶段是有顺 ...

  7. grunt源码解析:整体运行机制&grunt-cli源码解析

    前端的童鞋对grunt应该不陌生,前面也陆陆续续的写了几篇grunt入门的文章.本篇文章会更进一步,对grunt的源码进行分析.文章大体内容内容如下: grunt整体设计概览 grunt-cli源码分 ...

  8. PULL解析XML的运行机制详解

    PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...

  9. 源码深度解析SpringMvc请求运行机制(转)

    源码深度解析SpringMvc请求运行机制 本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制.通过源码我们可以知道从客户端发送一个URL请 ...

随机推荐

  1. Bellman-Ford 单源最短路径算法

    Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...

  2. ABP框架 - 动态Web Api层

    文档目录 本节内容: 创建动态Web Api控制器 ForAll 方法 重写 ForAll ForMethods Http 动词 WithVerb 方法 HTTP 特性 命名约定 Api 浏览器 Re ...

  3. python装饰器

    今天看了装饰器的一些内容,感觉@修饰符还是挺抽象的. 装饰器就是在不用改变函数实现的情况下,附加的实现一些功能,比如打印日志信息等.需要主意的是装饰器本质是一个高阶函数,她可以返回一个函数. 装饰器需 ...

  4. Google翻译之路

    如何将整个网站都翻译成某种语言,想必大家都有碰到这样的问题吧. 如果能够访问Google的话, 那这个太容易不过了. 来看,下面的就是Google提供的直接翻译某个网站. http://transla ...

  5. 测试计划(Test Plan)

    测试计划(Test Plan) 版权声明:本文为博主原创文章,未经博主允许不得转载. 测试计划的概念: 测试计划是一个文档,描述了进行测试的测试范围,测试策略和方法,测试资源和进度.是对整个测试活动进 ...

  6. 前端开发面试题收集(css部分)

    http://davidshariff.com/quiz/ 做了下这里面前端开发面试的题,发现有些不会,所以在此做个整理以供自己学习,参考,总结. 1.问: CSS属性是否区分大小写? ul { Ma ...

  7. $(document).ready() 与window.onload的区别

    1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 ...

  8. Lisp和SICP

         大概不少programmer都看过<黑客与画家>,作者用了整整一章的篇幅讨论Lisp的强大.我自然就会手痒痒.      几个月前,几天内攻城略地搞定了Python,用的方法便是 ...

  9. Django:手把手带你入门

    一.开发环境: Python:2.7:PyCharm 4 二.Django的安装: 打开Pycharm --> 新建项目--> 看图操作--> 自动安装Django环境 三.创建第一 ...

  10. Install and Configure SharePoint 2013 Workflow

    这篇文章主要briefly introduce the Install and configure SharePoint 2013 Workflow. Microsoft 推出了新的Workflow ...