人生无法避免之错------分析Maven的依赖
这点上我承认在沟通管理上没有及时发现组内成员的情绪,而且也没充分让开发人员参与到整体设计过程中,让他们缺少对整体的认识,也没很好的调动他们的积极性。
但是,就是在为什么一开始就不采取最后决定的方式去做这点上,我没法赞同的更多了。的确,需求上的改动,是因为经验,或是能力的问题,或是组织环境要求或是,更或是客户有了新的想法。开发人员就觉得你很脑残啊,为什么不早发现,早你干嘛去了。
对于这个问题,首先我觉得不少人混淆了“试错”和“错误”两个事情。而修改功能过程中,都会出现新的问题,而且在代码走查中,发现了很多代码不够健壮,比如通过连接获取信息只获取一次而没有设定超时时间循环获取导致出错,这些都会引入BUG。所以,功能修改的时候发现修改难度过大,那就得先看看自己做的事情是否不够严谨,自己设计的是否不够周全。
有些偏题,回到主题上,每个人也都无法一次就找到正确的方式,乔布斯也是在不断的试错。特别是项目组走的是敏捷开发道路,一般都是简单实现,之后扩展,就是在不断的重构,如果完全拒绝修改、更正。
之所以开发人员会产生误解,主要我觉得是问题反馈的对象的问题。基本上领导、评审人员、客户都是将问题反馈给我,而开发人员又没想去了解这些反馈,甚至在评审会议上打瞌睡觉得事不关己。总之试错是为了让产品更好,能不断进步。如果一个软件完全不用修改,那是因为他没人会去用,没有反馈的问题。
========分割线=========
之前两片基本上把Maven部署和Helloworld的过程以及过程中可能出现的问题都说到了。这篇就来说说Maven的依赖。
[b]依赖类型[/b]
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>
[b]依赖的传递[/b]
项目中,其实经常会出现这种情况,应用了某个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是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围,如下图,最左边一列表示第一直接依赖范围,最上面一行表示第二直接依赖范围,中间交叉单元格表示传递性依赖范围。
[table]
| 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 |
[/table]
注意:X代表不依赖
[b]依赖冲突的调解[/b]
有两个原则,第一原则是路径短优先原则,第二原则是先声明者优先
##路径短优先原则
依赖调解的第一原则是:路径最近者优先。
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]可选依赖[/b]
可选依赖不被传递。例如下例,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>
正常情况不应该使用可选依赖,可选依赖一般是项目有多个特性,在面向对象设计中单一原则意指一个类应该只有一项职责。
[b]排除依赖[/b]
有的时候传递性依赖的依赖包还处于不稳定版本,或者传递性依赖包因为版权问题不存在于中央仓库,这时候需要引入其他等价的依赖包。
所以需要排除依赖,然后自己在配置文件中再引入相应的依赖包。
<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>
[b]归类依赖[/b]
有时候,像Spring框架,当更新依赖时候,需要更新一片的依赖关系,这时候一个一个去修改过于麻烦,不如定义一个常量,更新时候手动修改一个就好了。
可以在pom.xml文件中的project标签下,定义
<properties>
<springframework.version>2.5.6</ springframework.version>
</ properties>
然后引入依赖时候,在version 中使用 ${ springframework.version }即可。
[b]依赖优化[/b]
##依赖列表
mvn dependency:list命令可以列出当前所有依赖(包括直接和传递)的列表,以及范围。
##依赖树
mvn dependency:tree命令可以层次化的列出所有依赖,可以从书中看出依赖传递的关系。
##依赖分析
mvn dependency:analyze命令可以分析当前依赖,包括哪些依赖被import却没引入,哪些引来引入了但是没加入编译。有时候可以用来删除一些没用的依赖,但是不能直接删除,比如sprint-core是Spring的必须依赖,但是会提示没加入编译,但是他又是Spring框架必须的。
Unused declared dependencies 后的内容 : 项目中未使用的,但显示声明的依赖
Used undeclared dependencies 后的内容:项目中使用到的,但是没有显示声明的依赖。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/430904.html
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!相关文章:

人生无法避免之错------分析Maven的依赖
上一个Sprint总结会中,组内有人提出很多需求为什么会变化,这样搞的开发人员多累啊。为什么一开始就不采取最后决定的方式去做,还一定要折腾下呢。恰好最近看了小道消息一篇关于试错的推文,很是感触。 这点上我承认在沟通管理上没有…...

工作中的那些不得意---Maven生命周期以及插件详解
今天写的比较多,有时间在整理格式,这格式在logdown排版还行。ITeye没去重排,有兴趣可以去看看我的Logdown[urlhttp://yuezaixz.logdown.com/posts/165674-not-proud-of-maven-life-cycle-as-well-as-those-in-the-plugin-details]http://yuez…...

不得意后的些许收获-----Maven的聚合和集成
[urlhttp://yuezaixz.logdown.com/posts/166009-not-complacent-after-harvest]LogDown发布的地址[/url]上篇博文狠狠抱怨了下工作中的那些不得意。那天后我也临时召开了一个谈心会议,主题也就是各自说说对彼此间的不满意。会议的开头我也主动先自我检讨了自己觉得自…...

亡羊补牢---Maven的约定和反应堆
[urlhttp://logdown.com/account/posts/166939-questions-must-expose-maven-conventions-and-reactors/preview][colorred][sizex-large][b]logdown博文地址[/b][/size][/color][/url]不得不说,时间过得还真挺快的,两个月的时间一下过去了,向…...

Just be fun ---centos6安装nodejs0.9.0全过程
[urlhttp://yuezaixz.logdown.com/posts/167870-just-be-fun-centos6-nodejs090-the-whole-process]logdown地址[/url] 。。 不是我故意每次都要发logdown地址的,是iteye的排榜感觉做的没logdown好。有时候没太多时间我就没好好排版了。也许看到标题,看过…...

学会提问---nodejs初体验
[aligncenter][urlhttp://yuezaixz.logdown.com/posts/168301-learn-to-nodejs-first-experience][colorred][b][sizelarge]惯例,先上logdown地址[/size][/b][/color][/url][/align]大学时候有一门课程是linux编程,这门课的老师可以算是整个大学最让班上…...

摸着石头过河---nodejs的express框架
[urlhttp://yuezaixz.logdown.com/posts/168553-the-stones-nodejs-express-frame][colorred][b][sizexx-large]logdown博文链接[/size][/b][/color][/url] 今天博文比较长,就没重新排版了,欢迎各位戳logdown博文的地址。今天家里有事没上班,…...

元总结---express框架之模板引擎、片段视图、视图助手
[urlhttp://yuezaixz.logdown.com/posts/169164-summary-of-express-frame-template-engine-a-fragment-of-a-view-the-view-helper][u][b][colorred][sizexx-large]Logdown博文地址[/size][/color][/b][/u][/url][b][sizex-large]#元总结[/size][/b] 什么是元总结?…...

FLV文件格式分析实例
FLV 文件格式介绍请看博客: http://blog.csdn.net/tianyue168/article/details/5994962 以下是FLV文件格式实例 HEAD://头部 46 4C 56 FLV 01 VERSION 05 [00000][音频标签][0][视频标签] 00 00 00 09 从FILEHEAD到FILEBODY开始的字节数 END HEAD …...

RTMP二进制分析实例
RTMP文件格式介绍请参考 http://blog.csdn.net/xiaguamanshu/article/details/5457290 以下内容是根据OBS代码中RTMP模块的发送日志对于RTMP文件格式的一种实例解释,整个流程从开始推流到结束推流。中间省略了部分音视频数据包。 [WriteN][1537] 0x03, C0 1字节…...

Java中的默认值和构造器
默认值: 数据类型的默认值为0; boolean的默认为false; 对象类型的默认值为null。 但在写程序的时候,一定要手动给个值,不然在后期容易出错。 构造器: 如果不手动写构造器,程序在编译的时候…...

构造器的用法
关于构造器: 还有this的用法 还有个地方要注意,像下面的代码中,构造器2中调用构造器1的语句,必须放在构造器2的第一句。必须!!! public class Main {private String name;private double sal…...

关于类继承中子类方法比父类方法丰富,一个引用值传递的小问题
对于前两个程序,一个父类一个子类,我们如果这样: public class ForTest {public static void main(String[] args) {// TODO Auto-generated method stubEmployee e1new Employee("小张",9800,1998,2,14);Employee e2new Employee…...

ArrayList和变参
其实没什么好说的,只是写下来作个备忘录 1.ArrayList的声明和实例化 import java.util.ArrayList; …… ArrayList<String> strnew ArrayList<>(99);//写法1 ArrayList<String> str1new ArrayList<String>();//写法2 其拥有add(Object o)…...

反射机制知识点(new和newInstance之区别)
在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此…...

Java反射机制--肤浅认知
本来不是很懂,看了很多文章解析,感觉貌似有点懂了。 记下备忘。待后来回头查看,以便更正。 Java反射机制是:在程序编译以后,运行过程中,实时获取新的类名,并且可以获知新类的方法、域和构造器…...

Java反射机制--佐证
这个例子很好的证明了,类加载和实例化的区别: public class NewInstancesTest {public static void main(String[] args) {TestOne onenull;try {//类加载Class clClass.forName("reflectTest.TestOne");//引号内的作用,是指定要加…...

定时器与回调
测试类 import java.awt.event.ActionListener; import javax.swing.JOptionPane; import javax.swing.Timer;public class Test {public static void main(String[] args) {ActionListener listennew TimeToPrint();Timer tnew Timer(10,listen);t.start();JOptionPane.showM…...

内部类、异常、断言和Loger日志
以后补充...

泛型的简单写法
在写程序的时候,有时候没办法必须用一个泛型的类或者方法,提前学到这个写法,对以后应该会很有好处。 public class PairTest1 {public static void main(String[] args){String [] temString{"a","c","e",&qu…...