最近由于不清楚maven(2.2.x)增量编译的机制,导致应用出现了一个当时觉得非常诡异的一个问题。先描述一下问题。

    背景是应用A有一个公用的base包,版本为1.6.6-SNAPSHOT,应用B依赖于这个公用的base包。我在base包中修改了一个字符串变量的值,该变量是一个缓存的key(如下面代码的Constants类,中的CACHE_KEY)。然后使用mvn deploy 命令把base包上传到中心库中。出现的问题是应用B打包部署,应用上线后,使用后台功能删除"cache.key.new"对应的缓存值,提示删除成功。但是前台展示的还是老的值(前台展示取的数据是从缓存取出的,简化代码后,参考下面的CategoryManager的showCategory()方法,根据key在缓存中取出值,然后前台展示)。
 
  public Interface Constants{
public interface Cache{
String CACHE_KEY = “cache.key.new”;//旧值为"cache.key"
}
}
public Class CategoryManager{
private static Map<int, String> keyMaps = new HashMap<String, String>();
static {
keyMaps.put(1, Constants. Cache. CACHE_KEY);//把缓存的key存到map中
.........
} public Object showCategory(){
return cacheManager.get(keyMaps.get(1));//在缓存中获取数据
}
}
 
    一开始怀疑是包没有成功deploy到中心库中,然后在中心库中把1.6.6-SNAPSHOT的源码包拉了下来,发现里面的代码是新的。
    我的印象中deploy是maven生命周期的最后一步,执行deploy命令是会执行compile编译操作的,当时怀疑自己记错了,以为base包deploy的时候没有走到compile,就把包发到中心库中了,后续把base包的1.6.6-SNAPSHOT的编译后的文件拉下来,并且反编译Constants类,发现CACHE_KEY的确是新的值"cache.key.new",证明这块是被重新编译过了。(后续翻阅了下资料”http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html maven生命周期“发现自己记的的确没错)
    最后把CategoryManager.class反编译过来一看,发现里面的部分代码是这样的:
 
    public Class CategoryManager{
private static Map<int, String> keyMaps = new HashMap<String, String>();
static {
keyMaps.put(1, "cache.key");//问题出在这里,这个"cache.key"没有替换成新的值"cache.key.new"
.........
}
........
}
    发现问题了,这里的"cache.key"并没有替换成新值。也就是说CategoryManager类并没有重新编译。这里的原因是maven的增量编译机制。
    后续找了些资料表明,默认情况下maven是增量编译的,maven在编译的时候会先去比较源文件(.java)文件的修改时间和对应类文件(.class)的修改时间,如果源文件的修改时间比类文件的修改时间要晚的话,重新编译原文件否则不做处理(另外,如果删除了一个java文件,对应的class文件在增量编译时是不会被移除的)。
    在这里CategoryManager的源文件并没有发生过改变,所以不会重新编译。并且这个地方恰好是静态代码块,这段代码  keyMaps.put(1, Constants. Cache. CACHE_KEY); 编译时直接被替换成 keyMaps.put(1, "cache.key"); ,如果是在非静态代码块里面使用的话,这块地方是不会出问题的。所以之前一直使用mvn deploy都没有出现过问题。
    那要怎么避免这个问题呢,使用mvn clean deploy。clean会做一些清理的工作,包括移除上一次构建的文件。这样就能很好的解决这个问题了。
 
参考:

maven增量编译的更多相关文章

  1. Spark 1.0 开发环境构建:maven/sbt/idea

    因为我原来对maven和sbt都不熟悉,因此使用两种方法都编译了一下.下面记录一下编译时候遇到的问题.然后介绍一下如果使用IntelliJ IDEA 13.1构建开发环境. 首先准备java环境和sc ...

  2. IntelliJ IDEA使用心得之Maven项目篇(转)

    IntelliJ IDEA使用心得之Maven项目篇   今天和大家分享下,在IDEA中打开Maven项目的方法. 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Mave ...

  3. IntelliJ IDEA使用心得之Maven项目篇

    今天和大家分享下,在IDEA中打开Maven项目的方法. 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Maven命令生成项目的IDEA配置文件. 在项目的根目录(即po ...

  4. idea中使用maven

    转:https://www.cnblogs.com/kagome2014/p/8431064.html 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Maven命令生成项 ...

  5. Mac配置环境变量(Java,Android,Gradle,Nodejs,MongoDB,Maven,Hosts)

    JAVA_HOME 配置环境变量 # 使用vim打开.bash_profile文件.加入java环境变量 $ vim .bash_profile export JAVA_HOME=$(/usr/lib ...

  6. 深入了解gradle和maven的区别

    目录 简介 gradle和maven的比较 可扩展性 性能比较 依赖的区别 从maven迁移到gradle 自动转换 转换依赖 转换repositories仓库 控制依赖的版本 多模块项目 profi ...

  7. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

  8. 理解Maven中的SNAPSHOT版本和正式版本

    Maven中建立的依赖管理方式基本已成为Java语言依赖管理的事实标准,Maven的替代者Gradle也基本沿用了Maven的依赖管理机制.在Maven依赖管理中,唯一标识一个依赖项是由该依赖项的三个 ...

  9. 【微框架】Maven +SpringBoot 集成 阿里大鱼 短信接口详解与Demo

    Maven+springboot+阿里大于短信验证服务 纠结点:Maven库没有sdk,需要解决 Maven打包找不到相关类,需要解决 ps:最近好久没有写点东西了,项目太紧,今天来一篇 一.本文简介 ...

随机推荐

  1. android Button 切换背景,实现动态按钮和按钮颜色渐变

        android Button 切换背景,实现动态按钮和按钮颜色渐变 一.添加android 背景筛选器selector实现按钮背景改变     1.右键单击项目->new->Oth ...

  2. mysql导入数据库

     mysql -u root -p bbs < d:\bbs_2011-06-15 --default-character-set=gbk      mysqldump -uroot -p ta ...

  3. 嵌入式设备上的 Linux 系统开发

    转载:http://www.ibm.com/developerworks/cn/linux/embed/embdev/index.html   如果您刚接触嵌入式开发,那么大量可用的引导装载程序(bo ...

  4. 普通字符串与Hex编码字符串之间转换

    import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Hex; public clas ...

  5. C#中,为什么结构体也可以设置构造函数?

    结构体派生自ValueType,ValueType派生自Object,可访问Object的方法.结构体是一种缩小版的类.结构体不能继承.结构体总是有一个无参数的默认构造函数,不允许替换.结构体可指定字 ...

  6. Objective-C ,ios,iphone开发基础:几个常用类-NSNumber

    2013-08-21 在Objective-C,包括int double float 等等再内的基础数据类型都不是一个类,所以就不能给它们发送消息,也就是说不能调用方法,那怎么办呢 ?Objectiv ...

  7. 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析

    前面我们已经接触过几种数据结构了,有数组.链表.Hash表.红黑树(二叉查询树),今天再来看另外一种数据结构:栈.      什么是栈呢,我就不找它具体的定义了,直接举个例子,栈就相当于一个很窄的木桶 ...

  8. Nginx HTTP User_agent

    假设我这里有大量图像.CSS.javascript等静态文件,分别放在后端服务器  192.168.1.5 和 192.168.1.6上,那么我如何利用nginx的反向代理功能将不同的 http_us ...

  9. 小技巧之a标签自动解析URL

    我们可能都知道javascript中的window.location对象用来获取当前页面的地址URL,并把浏览器重定向到新的页面.它有protocol.hostname.host.port.searc ...

  10. 随机提取N条记录[多种数据库方法]

    随机提取10条记录的例子: Sql server: select top 10 * from 表 order by newid() Access: SELECT top 10 * FROM 表 ORD ...