4_Maven原理以及重要概念


1_Maven原理中的重要概念。

【1】Maven原理模型。


简而言之:如图所示,Maven的灵魂就是pom.xml,通过pom的定义项目依赖的jar,进行依赖管理,通过pom定义第3方插件,进行插件的扩展;、

       通过pom的定义,描述项目基本信息,开发者,进行项目信息管理。具体的配置方法请参考pom的文档。

【2】Maven中插件的运行主要依赖于图中所示的:lifecycle,phase,goal,mojo。这4个概念对于maven插件很重要。

         lifecycle:生命周期,这是maven最高级别的的控制单元,它是一系列的phase组成,也就是说,一个生命周期,就是一个大任务的总称,不管它里面分成多少个子任务,反正就是运行一个lifecycle,就是交待了一个任务,运行完后,就得到了一个结果,中间的过程,是phase完成的,自己可以定义自己的lifecycle,包含自己想要的phase,maven本身具有clean,default,site生命周期。

lifecycle可以包含任意个phase,phase的执行是按顺序的,一个phase可以绑定很多个goal,至少为一个,没有goal的phase是没有意义的

         goal:这是执行任务的最小单元,它可以绑定到任意个phase中,一个phase有一个或多个goal,goal也是按顺序执行的,一个phase被执行时,绑定到phase里的goal会按绑定的时间被顺序执行,不管phase己经绑定了多少个goal,你自己定义的goal都可以继续绑到phase中 

mojo: lifecycle与phase与goal都是概念上的东西,mojo才是做具体事情的,可以简单理解mojo为goal的实现类,它继承于AbstractMojo,有一个execute方法,goal等的定义都是通过在mojo里定义一些注释的anotation来实现的,maven会在打包时,自动根据这些anotation生成一些xml文件,放在plugin的jar包里。

lifecycle与phase与goal就是级别的大小问题,引用必须是从高级引用下级,不能跨级引用


2_Maven中依赖的概念

【1】依赖的配置

<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
			<scope>test</scope>
		</dependency>		
</dependencies>

上面给出了最基本的依赖配置,<dependency>中前3行驶定义了一个构建的Maven坐标。

<scope>是依赖范围,用来控制依赖和编译,测试,运行的classpath的关系

配置中还有2个重要配置项<optional>和<exclusion>

依赖是具有传递性的,如  A 依赖于 B,B依赖于 C,那么B 对 C 的依赖关系也会传递给 A,如果我们不需要这种传递性依赖,也可以用<optional> 去除这种依赖的传递

基础实例: 设置optional 为true便可以取消依赖传递。

<dependency> 
	<groupId>junit</groupId> 
	<artifactId>junit</artifactId> 
	<version>4.9</version> 
	<optional>true<optional> 
</dependency>

更多参考: Maven可选依赖实战

假设第三方的 jar 包中没有使用 <optional> 来去除某些依赖的传递性,那么可以在当前的 POM 文件中使用 <exclusions> 元素声明排除依赖,exclusions 可以包含一个或者多个exclusion 子元素,因此可以排除一个或者多个传递性依赖

基础实例:

    <dependency>    
         <groupId>org.springframework</groupId>  
         <artifactId>spring-core</artifactId>  
         <exclusions>  
               <exclusion>      
                    <groupId>commons-logging</groupId>          
                    <artifactId>commons-logging</artifactId>  
               </exclusion>  
         </exclusions>  
    </dependency>


还有个属性<classifer>,大部分情况下这个属性不需要配置。一下列出2种需要配置的情况

第一种:

当我们需要依赖类似TestNG的时候,简单的声明GAV会出错,因为TestNG强制需要你提供分类器,以区别jdk14jdk15TestNG必须要求jdk5.0以上,我们需要这样声明对TestNG的依赖:

<dependency>  
  <groupId>org.testng</groupId>  
  <artifactId>testng</artifactId>  
  <version>5.3</version>  
  <classifier>jdk15</classifier>  
</dependency>  
第二种:

我们可以用它来声明对test构件的依赖,比如,我们在一个核心模块的src/test/java中声明了一些基础类,然后我们发现这些测试基础类对于很多其它模块的测试类都有用。没有分类器,我们是没有办法去依赖src/test/java中的内容的,因为这些内容不会被打包到主构件中,它们单独的被打包成一个模式为<artifactId>-<version>-test.jar的文件。

我们可以使用分类器来依赖这样的 test 构件:

<dependency>  
  <groupId>edu.fudan.app</groupId>  
  <artifactId>testCore</artifactId>  
  <version>${project.version}</version>  
  <classifier>test</classifier>  
</dependency>

【2】传递依赖

(1)传递依赖范围:假设A依赖B,B依赖C,我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围,如下图,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格表示传递性依赖范围

2)依赖冲突解决原则:

第一原则是路径短优先原则,第二原则是先声明者优先

第一原则:路径短优先

A->B->C->X(2.0) 
A ->D->X(
1.0) 
这样A会传递性依赖X(
1.0) 

第二原则是先声明者优先

A->C->X(1.0) 
A ->D->X(2.0) 
这样A传递性依赖了X(1.0),因为他是先声明的。

【3】归类依赖

当项目中依赖了同一项目的不同模块,它们的版本都是相同的,因此在升级的时候,这些依赖的版本会一起升级。为了避免重复,且需要修改时只修改一处,可以通过 归类依赖来解决。    使用properties元素定义Maven属性,如springframework.version子元素,并定义其值。有了这个属性定义,maven运行时会将POM中所有的${s pringframwork.version}替换成定义的实际值

<properties>
        <springframework.version>2.1.1</springframework.version>
</properties>


<dependency>
<span style="white-space:pre">	</span><version>${springframework.version}</version>
</dependency>

【4】依赖优化

使用dependency:list和dependency:tree 帮助我们详细了解项目中所有依赖的具体信息。

使用dependency:analyze工具可以帮助分析当前项目的依赖。

analyze的结果中包含了两部分:

Used undeclareddependencies:项目中使用但未显式声明的依赖。这种依赖意味着潜在的风险;

Unuseddeclared dependencise:项目中未使用的,但显式声明的依赖。对于这种依赖不能直接删除,因为analyze只会分析编译和测试需要的依赖,其他依赖它无法发现,因此需要仔细分析。

3_Maven中继承和聚合

继承是可重用,即消除重复编码的行为,我们通过构建父模块将子模块共用的依赖,插件等进行统一声明。

可以继承的元素

基本配置

<parent> 
	<groupId>com.dugeng.mavenproject</groupId> 
	<artifactId>com.dugeng.parent</artifactId> 
	<version>0.0.1-SNAPSHOT</version> 
	<relativePath>../Parent/pom.xml</relativePath> 
</parent>

聚合:

现实中一个项目往往是由多个 project 构成的,在进行构建时,我们当然不想针对多个 project 分别执行多次构建命令,这样极容易产生遗漏也会大大降低效率。Maven 的聚合功能可以通过一个父模块将所有的要构建模块整合起来,将父模块的打包类型声明为 POM,通过 <modules> 将各模块集中到父 POM 中。其中 <module></module>中间的内容为子模块工程名的相对路径。

<modules>    
	<module>../project1</module> 
	<module>../project2</module> 
</modules>

当然具体实现中还需要配置依赖管理,具体结合Maven的最佳实践在项目文章中给出。

4_更多资料

http://www.ibm.com/developerworks/cn/java/j-lo-maven/

http://www.tuicool.com/articles/6BvEZb

关于依赖

关于继承和聚合

更多文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值