`

人生无法避免之错------分析Maven的依赖

阅读更多
上一个Sprint总结会中,组内有人提出很多需求为什么会变化,这样搞的开发人员多累啊。为什么一开始就不采取最后决定的方式去做,还一定要折腾下呢。恰好最近看了小道消息一篇关于试错的推文,很是感触。
这点上我承认在沟通管理上没有及时发现组内成员的情绪,而且也没充分让开发人员参与到整体设计过程中,让他们缺少对整体的认识,也没很好的调动他们的积极性。
但是,就是在为什么一开始就不采取最后决定的方式去做这点上,我没法赞同的更多了。的确,需求上的改动,是因为经验,或是能力的问题,或是组织环境要求或是,更或是客户有了新的想法。开发人员就觉得你很脑残啊,为什么不早发现,早你干嘛去了。
对于这个问题,首先我觉得不少人混淆了“试错”和“错误”两个事情。而修改功能过程中,都会出现新的问题,而且在代码走查中,发现了很多代码不够健壮,比如通过连接获取信息只获取一次而没有设定超时时间循环获取导致出错,这些都会引入BUG。所以,功能修改的时候发现修改难度过大,那就得先看看自己做的事情是否不够严谨,自己设计的是否不够周全。
有些偏题,回到主题上,每个人也都无法一次就找到正确的方式,乔布斯也是在不断的试错。特别是项目组走的是敏捷开发道路,一般都是简单实现,之后扩展,就是在不断的重构,如果完全拒绝修改、更正。
之所以开发人员会产生误解,主要我觉得是问题反馈的对象的问题。基本上领导、评审人员、客户都是将问题反馈给我,而开发人员又没想去了解这些反馈,甚至在评审会议上打瞌睡觉得事不关己。总之试错是为了让产品更好,能不断进步。如果一个软件完全不用修改,那是因为他没人会去用,没有反馈的问题。
========分割线=========
之前两片基本上把Maven部署和Helloworld的过程以及过程中可能出现的问题都说到了。这篇就来说说Maven的依赖。
依赖类型
Maven会用到的依赖基本就是5种,compile,test,provided,runtime,system
1.compile:编译依赖范围,默认使用该范围。编译、测试、运行都有效
2.test:测试依赖范围。支队测试的classpath有效。例如Junit,greenMail。
3.provided:对编译和测试有效,对运行无效,常用于容器提供了的运行环境。例如servlet-api,容器以提供,所以只需要编译和测试有效即可。
4.runtime:运行时依赖范围。例如jdbc驱动,编译和测试并不需要,只需要使用JDK提供的JDBC接口即可。
5.system:系统依赖范围,依赖Maven仓库意外的依赖。
例如



<dependencies>
    <dependency>
      <groupId>javax.sql</groupId>
      <artifactId>jdbc-stdext</artifactId>
      <version>2.0</version>
      <scope>system</scope>
	  <systemPath>${java.home}/lib/rt.jar</systemPath>
    </dependency>
  </dependencies>

依赖的传递
项目中,其实经常会出现这种情况,应用了某个Jar包,然后使用时候报错缺少某个类,这就是因为缺少了该jar包所依赖的jar包的原因。例如工程A依赖了,spring-core,spring-core依赖commons-logging,那A依赖spring-core时候依旧传递的依赖了commons-logging。

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

注意:X代表不依赖

依赖冲突的调解
有两个原则,第一原则是路径短优先原则,第二原则是先声明者优先

##路径短优先原则
依赖调解的第一原则是:路径最近者优先。
A ->B->C->X(1.0)
A ->D->X(2.0)

这样A会传递性依赖X(2.0)

##先声明者优先原则
赖调解的第二原则是:先声明者优先。
当路径长度相同时候,第一原则已经不能解决问题了,Maven2.0.9以后版本就有了第二原则,声明在先者有效。
A ->C->X(1.0)
A ->D->X(2.0)

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

可选依赖
可选依赖不被传递。例如下例,B有一个持久层工具包依赖,他依赖了两种数据库驱动,这两种特性只需要选择一种,这种传递性依赖是不会给传递的,需要在A项目中另外依赖数据库驱动依赖。
<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.10</version>
      <option>true</option>
    </dependency>
	<dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>8.4.701.jdbc3</version>
      <option>true</option>
    </dependency>


正常情况不应该使用可选依赖,可选依赖一般是项目有多个特性,在面向对象设计中单一原则意指一个类应该只有一项职责。

排除依赖
有的时候传递性依赖的依赖包还处于不稳定版本,或者传递性依赖包因为版权问题不存在于中央仓库,这时候需要引入其他等价的依赖包。
所以需要排除依赖,然后自己在配置文件中再引入相应的依赖包。

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


归类依赖
有时候,像Spring框架,当更新依赖时候,需要更新一片的依赖关系,这时候一个一个去修改过于麻烦,不如定义一个常量,更新时候手动修改一个就好了。
可以在pom.xml文件中的project标签下,定义
<properties>
	<springframework.version>2.5.6</ springframework.version>
</ properties>



然后引入依赖时候,在version 中使用 ${ springframework.version }即可。

依赖优化

##依赖列表
mvn dependency:list命令可以列出当前所有依赖(包括直接和传递)的列表,以及范围。
##依赖树
mvn dependency:tree命令可以层次化的列出所有依赖,可以从书中看出依赖传递的关系。
##依赖分析
mvn dependency:analyze命令可以分析当前依赖,包括哪些依赖被import却没引入,哪些引来引入了但是没加入编译。有时候可以用来删除一些没用的依赖,但是不能直接删除,比如sprint-core是Spring的必须依赖,但是会提示没加入编译,但是他又是Spring框架必须的。
Unused declared dependencies 后的内容 : 项目中未使用的,但显示声明的依赖
Used undeclared dependencies 后的内容:项目中使用到的,但是没有显示声明的依赖。
1
0
分享到:
评论
2 楼 liubey 2013-12-02  
xly_971223 写道
maven这东西搞得有点复杂,
个人认为不会长久

用Maven的人简直太多太多了
1 楼 xly_971223 2013-11-29  
maven这东西搞得有点复杂,
个人认为不会长久

相关推荐

    apache-maven-3.6.0

    2. **依赖管理**:Maven通过POM中的依赖配置自动下载并管理项目所需的所有库,避免了手动管理jar文件的繁琐工作。只需在POM中声明依赖,Maven会自动解决依赖关系,并从Maven仓库中下载。 3. **构建生命周期**:...

    apache-maven-3.5.4压缩型安装包

    开发者只需在POM中声明所需的库,Maven会自动下载并管理这些依赖,避免了手动管理jar包的困扰。 3. **插件系统**:Maven的插件机制使其功能强大且可扩展。每个构建阶段都可以通过相应的插件来实现,例如编译代码、...

    mybatis+spring maven下 整合 完整demo

    在IT行业中,MyBatis和Spring...通过这个完整的demo,开发者可以学习到如何在Maven环境下将MyBatis和Spring整合,理解它们之间的交互方式,以及如何利用Maven管理项目依赖。这为后续的企业级应用开发打下了坚实的基础。

    Maven在企业中的使用

    - **依赖管理**:Maven能够自动解决项目依赖问题,避免了手动管理依赖的复杂性。 - **配置管理**:Maven支持集成SCM系统,如Git、SVN等,便于代码版本控制和管理。 - **发布管理**:Maven提供了标准化的发布流程,...

    jar包依赖冲突排查和解决方案.docx

    ### jar包依赖冲突排查与...4. **依赖分析工具**:利用诸如Maven Helper之类的工具定期检查依赖关系,及时发现并解决问题。 通过以上方法,可以有效地管理和解决项目中的依赖冲突问题,确保项目的稳定性和可维护性。

    阿里云E-MapReduce-SDK手册.pdf

    - 为了方便管理依赖,推荐使用Maven构建系统,并在pom.xml文件中添加对应的依赖项。 - 如果不使用Maven,可以直接下载jar文件,然后在Eclipse等IDE中将其添加到项目的类路径中。 3. **快速开始**: - 要开始使用...

    jar包冲突的原理和解决方案.docx

    在Java开发中,Maven作为主流的构建工具,它的依赖管理功能强大,但同时也可能导致jar包冲突的问题。本文主要探讨jar包冲突的原理以及在Maven中的解决方案。 **jar包冲突原理** 1. **依赖传递**:Maven的依赖管理...

    Jar包冲突问题及解决方案.docx

    ### Jar包冲突问题及解决方案 ...Jar包冲突是Java开发中常见的问题之一,其根源在于依赖管理和版本控制不当。通过理解冲突的本质及其产生原因,并采取有效的策略来解决冲突,可以显著提高项目的稳定性和可靠性。

    阿里云-消息队列-API指南-D.docx

    - **SDK源码下载**:由于`aliyun-java-sdk-ons`包未部署到公共软件仓库,用户需要从阿里云官网下载源码,编译后添加到本地Maven仓库。 - **JAR包下载**:另一种方式是直接下载预编译的JAR包并导入项目。这里涉及的...

    spring boot 快速入门

    ### Spring Boot 快速入门详解 #### 一、Spring Boot 概述 Spring Boot 是由 Pivotal 团队提供的一款旨在简化 Spring 应用程序...Spring Boot 的强大之处在于其提供了丰富的 starter 依赖,极大地简化了开发过程。

    阿里云-表格存储服务SDK参考手册.pdf

    - Maven用户可以在`pom.xml`中添加依赖,以便在项目中集成SDK。 - 对于非Maven项目,可以通过Eclipse将JAR包导入到项目的类路径中。 3. **版本兼容性** - 版本2.2.4是当前的最新版本,该系列SDK与2.x.x版本兼容...

    Java-Junit单元测试无法使用scanner输入和I-O流的解决方案.docx

    ### Java-Junit单元测试无法使用scanner输入和I-O流的解决方案 #### 一、单元测试的概念及重要性 单元测试是一种软件开发中的测试方法,它主要用于验证软件中的最小可测试单元或组件是否按预期工作。在Java编程...

    阿里云-访问控制服务SDK使用手册-D.docx

    要将这些SDK引入到项目中,可以通过Maven仓库添加依赖,或者手动下载jar包并将其添加到项目类路径中。以下是使用Maven添加依赖的示例: ```xml &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;artifactId&gt;aliyun-java-sdk-ram ...

    springboot008基于springboot的房屋租赁系统毕业源码案例设计.zip

    - `pom.xml`:Maven项目的配置文件,定义了项目依赖和插件。 - `src/main/java`:Java源代码目录,包含主启动类(`Application.java`)和其他业务逻辑类。 - `src/main/resources`:资源文件夹,包括配置文件(如...

    springboot测试Redis连接,启动之后各种报错的解决方案.docx

    这将清理项目并重新安装所有依赖到本地 Maven 仓库,确保所有模块都存在于本地环境中。 3. **确认测试类位置**: - 确认测试类的位置是否正确。检查类名、包名是否与实际文件结构一致。 通过以上步骤,通常可以...

    sharding-jdbc-mybatis 2.zip

    首先,你需要在项目中引入Sharding-JDBC和MyBatis的依赖,这可以通过Maven的pom.xml文件来完成。然后,配置Sharding-JDBC的核心规则,包括分片策略、数据源、规则注册等。分片策略可以根据业务需求选择哈希、范围或...

    JSP基于SSM献血者管理献血网设计可升级SpringBoot毕业源码案例设计.zip

    - **核心特性**:SpringBoot简化了Spring应用程序的初始搭建以及开发过程,通过自动配置,避免了大量的XML配置。 - **起步依赖**:通过引入starter-pom,可以快速集成各种功能模块,如Web、数据访问、安全等。 - ...

    Android多模块构建合并aar解决方案.docx

    尤其是当涉及到模块间的依赖时,简单的单独打包往往无法满足需求,这就引出了多模块构建合并aar的需求。 #### AAR与JAR的区别 在深入探讨解决方案之前,我们需要先了解一下AAR和JAR的基本概念及其区别。 **AAR...

    阿里云-访问控制服务SDK手册-D.docx

    如果项目是基于Maven构建的,可以在pom.xml文件中添加STS SDK的依赖。以版本2.1.6为例,需要在`&lt;dependencies&gt;`标签内加入如下内容: ```xml &lt;groupId&gt;com.aliyun&lt;/groupId&gt; &lt;artifactId&gt;aliyun-java-sdk-sts ...

    springboot电商秒杀项目源码+springboot案例

    - **起步依赖**:SpringBoot 通过起步依赖(Starter POMs)简化了 Maven 配置,开发者只需要引入相应模块的起步依赖,就可以得到所需功能。 - **内嵌容器**:SpringBoot 内嵌了 Tomcat 或 Jetty 等 Web 容器,无需...

Global site tag (gtag.js) - Google Analytics