Month: January 2012

《Maven实战》笔记 2.5 - 依赖的调解

Maven的依赖调解机制     1.如果存在App->A->B-0.9, 又存在App->C->D->B-1.0,那App在打包时会不会把B-0.9和B-1.0都纳入进来?如果不会,倒底选择哪个B?    答案:只会纳入一个,即B-0.9,因为它离App较近(中间只隔了一个A,B-1.0和App之间则隔了D,C两个)   2.App到B存在两条依赖路径,怎么识别这种情况?    答案: mvn dependency:tree -Dverbose,它会显示哪些项目由于这种情况而被“omitted for conflict”   3.B-0.9被选中,会不会导致依赖B-1.0的D在运行时出错?    答案:会的。如果D依赖了B-1.0中有而B-0.9里没有的东西,就会在运行时出错   4.那该怎么办?    答案:      办法1. 在App的pom里,屏蔽掉A对B的依赖 <dependency> <groupId>kent.learn</groupId> <artifactId>maven-a</artifactId> <exclusions> <exclusion> <groupId>kent.learn</groupId> <artifactId>maven-b</artifactId> </exclusion> </exclusions> </dependency>      办法2. 让App直接依赖B-1.0,让其他的对B的传递依赖都失效

《Maven实战》笔记 2.6 – Used undeclared 和 Unused declared

你的项目会直接依赖一些项目,也可能会传递依赖一些项目;有的直接依赖,可能你本应该降格为传递依赖;有的传递依赖,你可能应该用作直接依赖;还有些直接依赖,可能你已经用不上应该去掉了。 mvn dependency:analyze就是用来帮你发现上述情况的一条命令。它会对两种情况作出警告:   1. Used undeclared dependencies。 你的App的代码直接调用了B里的API,但当前B是通过App->A->B的关系被纳入到Classpath的。这种情况下,你应该将B升级为直接依赖。否则的话,如果A不再依赖B了,你依赖B的那些代码就会有编译错误,而且可能是很难找到原因的编译错误。   2. Unused declared dependencies。你的App的代码没用直接调用B里的API,但却把B声明为App的直接依赖。 这种情况下,你要谨慎     a.App可能确实不需要直接依赖B,不过,可能会这样:App->A,A调用了B里的API,但A的pom里没有声明B。如果A的作者不负责任,这种情况就会出现,而且在大型组织里经常会遇到。这种情况下,你就要仍然把B留下来作为依赖,否则运行时A就会说找不到B而报错。     b.App的java代码里不需要直接依赖B,但是经过xml配置文件或者以反射方式调用了B里的API,这种情况下你也要保留B作为直接依赖。     c.App依赖了A,A依赖了B,这时你可以去除对B的直接依赖     d.App没有调用B里的代码,App的其他所有直接依赖和传递依赖的pom里都没有依赖B,也没有调用B里的API,这时也应该去除对B的直接依赖。 要判断App打包后是否需要B出现在classpath里,可以使用JarJar工具。它可以分析App打包后、包里所有的jar文件之间的java调用关系。

《Maven实战》笔记 2.3 - 传递依赖:Maven的核心竞争力之一

如果你的项目要引入Spring,而你又不用Maven,你怎么把Spring本身所需的jar文件找出来?   1.办法一:先只纳入spring.jar,然后创建你的应用,根据编译和运行时的错误,结合Spring的文档,把Spring所需的第三方jar一个一个下载,再纳入进来 — 不用说,会费劲死   2.办法二:把spring-with-dependencies.zip包里的spring.jar和第三方库一次性纳入进来,这样是省事很多,但你纳入的第三方库存在两个问题:     a.有些则可能和你已经存在的第三方库重复(如apache-commons系列),但版本不一样。这时你就得手动解决这种重复问题,即选择留下哪个,去掉哪个     b.有些库可能并不需要纳入进来,因为spring只是某块功能会用到它们,而这块功能你的应用根本用不上。这些不需要的库放在你的应用里,很容易跟未来引入的其他第三方库重复(比如引入Hibernate时也要引入apache-commons系列),到时又会产生跟#a一样的问题。 Maven可以自动化地解决这些问题。   1. 你只需要宣称依赖Spring   2. Spring所需要的类库会被Maven自动下载下来,不需要你手动下   3. 如果这时存在第三方库的重复问题,Maven会自动为你做好依赖的调解

《Maven实战》笔记 2.2 - dependency scope及其传递性

四个主要的scope:   1.compile: 编译和运行时都需要    2.provided: 编译时需要,运行时不用。比如web应用对servlet-api的依赖    3.runtime:  运行时需要,编译时不用。比如mysql的jdbc driver    4.test: 顾名思义 scope的传递:   1. 若A->B是compile,B->C是compile,则A->C也是complile   2. 若A->B是provided,B->C是provided,则A->C也是provided   3. 若A->B是provided,B->C是compile,则A->C是provided

《Maven实战》笔记 2.1 - Coordinate的概念

Coordinate翻译成“坐标”,正如空间的一个点可以用(x,y,z)来唯一地标识一样,Maven里的工程也可以通过(groupId, artifactId, version, packaging, classifier)来唯一地标识 其中,“groupId, artifactId, version”称作基本坐标,一般用这几个就够了

《Maven实战》笔记 1 - 一些杂碎

Maven的三大功能   1.构建: 类似于Ant,但比Ant更强调Convention Over Configuration,有利于在组织内形成标准   2.依赖管理:这一点应该是Maven最重要的特性   3.项目信息管理:好像第三方框架才用这种东西? Eclipse插件   1.可以装一个m2eclipse   2.m2eclipse自带了一个Maven,应该配置一下,让它使用你安装的正牌Maven;这是为了让整台机器只使用一个Maven,避免两个Maven都作用于同一个工程,造成难以预料的错误。 杂   1.pom.xml里的<name>元素没有多大实际作用,你可以填一下可读性较好的项目名称,如"web module of xxx platform"   2.java类的包名应该包含本工程的groupId和artifactId

选择Maven的最初动机是什么?

Maven能干很多事情,但你当时选择它或者去了解它,是因为什么目的? 今天问自己这个问题,居然一时间答不上来,能想到的只是一些“依赖管理”、“构建管理”之类的泛泛的说法。 后来回忆了一些,想起来了。当时真应该坚持使用Maven。 当时的想法是:   1. 组织内有好几个应用   2. 应用之间需要共享一些业务逻辑组件,即jar库   3. jar库需要频繁经常构建和版本升级,这些事情手动做很麻烦,所以当时考虑引入Maven;当时脑子里还没建立起版本号的概念,以为这是第三方框架才用的东西,如果当时仔细研究了Maven,还可以顺便建立起版本的概念,为未来的服务化铺平道路。

DDD可以帮助你“快速定位代码“

今天有个牛人提到了这一点,我觉得很有意义。 DDD(领域驱动设计)提倡让Entity来负担业务逻辑,而不是都往Service里塞; 这样的一个好处是,某Entity相关的逻辑会集中在这个Entity类内部,也就是说。 当你要查看某块功能的代码时,你基本上都能在这个Entity类里找到。 这其实也是封装性的体现,即把某Entity自身的功能封装在Entity内部,对外只提供比较宏观的接口,Service之流不准直接干涉Entity的细节。 如果不走这条路,那你就要去Service里找; 而跟一个Entity相关的Service可能会有很多很多个,到时找起来就麻烦了。

发布了一个用于在页面上查看日志的小工具:玻璃墙(Glasswall)

开发和测试时, 你想不想在浏览器的页面上直接看到本次http请求所产生的log4j日志? 开源项目“ 玻璃墙”(Glasswall)就是这样一种工具。它让你在页面上直接看到日志输出,帮你在遇到问题时迅速地发现问题,而不用辛苦地去服务器上找日志然后grep。如图: Glasswall的功能很简单,但它有个 在易用性方面有个优势:“非侵入”。使用Glasswall,   1. 你用不着做任何代码、配置文件的改动,也不用把任何jar文件丢到web应用里或应用服务器里。   2. 你只需要在启动应用服务器的命令行里加上"-javaagent"参数   3. 或者连这个参数都可以不加;你可以在web应用启动后,另外敲一个命令:“./glasswall.sh <pid> ”(windows下是glasswall.bat)。 Glasswall的应用场合是所有基于Servlet的web application,目前支持的日志框架除了log4j,还有java.util.logging。 使用者的jdk版本须在java 5以上; 如果想使用零侵入的“./glasswall.sh <pid> ” ,则须java 6以上的SUN JDK。 另外,操作系统不限。 更多细节详见 http://code.google.com/p/glasswall/的首页介绍,也可到作者的微博留言: http://weibo.com/u/2474145202 有兴趣的同学可以下载下来试试。 另外,虽然我自认为做了很全面的测试,但可能仍有缺陷。 欢迎大家在使用时检视代码,提交补丁,或者加入项目。 声明:     1. 这个主意不是本人原创。类似的东西已经存在,本人只是写了一个非侵入式的版本     2. 这个项目的构思和设计都深受开源项目BTrace的影响,有兴趣的同学可以研究下Btrace