现象:同一个springmvc工程使用eclipse和idea用Tomcat启动都没问题,但是如果走单元测试使用到了@ContextConfiguration这个spring的上下文注解idea出问题了,eclipse没问题;由于最近才使用idea;只能先百度一下根据现象,发现天下文章一大抄。。。还得自己慢慢追!

第一阶段:根据提示基本断定这个map的id被加载了两次,但是全文搜索了一下确实只有一个id,排除传统的手残;eclipse没问题也能证明这点,这里就猜测很大可能是idea哪里需要设置一下,但是网上没找到

第二阶段:看日志追源码,出错定位在parse map阶段,如图:

初步判断在idea执行test的时候,加载了2遍spring的相关mapper.xml,继续追,根据异常定位到 PathMatchingResourcePatternResolver 这个类,他主要进行资源的匹配,主要入口方法

他基本做了两个件事情,1)把所有的不重复的资源用set收集起来,2)针对收集的资源进行一次xml的筛选(set),再接下去就是解析parse不在这个类(根据这里提供的xml进行逐一(xml里面的相关id)解析并记录,如果出现重复的则报异常题目异常)

protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
String rootDirPath = determineRootDir(locationPattern);
String subPattern = locationPattern.substring(rootDirPath.length());
     //getResources()这个方法收集所有的资源
Resource[] rootDirResources = getResources(rootDirPath);
Set<Resource> result = new LinkedHashSet<Resource>(16);
for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource);
URL rootDirURL = rootDirResource.getURL();
if (equinoxResolveMethod != null) {
if (rootDirURL.getProtocol().startsWith("bundle")) {
rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
rootDirResource = new UrlResource(rootDirURL);
}
}
if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
}
else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
}
else {
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
}
}
if (logger.isDebugEnabled()) {
logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return result.toArray(new Resource[result.size()]);
Resource[] rootDirResources = getResources(rootDirPath);发现在执行完这个方法的时候里面出现了2次相同的jar包,表现形式不一样而已,例如:
URL [jar:file:/E:/Program%20Files/JetBrains/IntelliJ%20IDEA%202018.3/lib/idea_rt.jar!/]
URL [jar:file:E:\Program Files\JetBrains\IntelliJ IDEA 2018.3\lib\idea_rt.jar!/]

看到这里傻眼了,为什么位置相同的包会都能加进去,这里就想:要么是我那里没注意到idea配置,要么就是spring4.3.8的bug;回过头来想,这两条居然都言中了

第三阶段:定位、分析,进入getResources看了一下,第一次通过classLoader(AppClasssLoader顶级的)得到的url集合((URLClassLoader) classLoader).getURLs()进行条件筛选,第二次通过判断是否是系统的calssloader进行再次的add结果,如下:
protected void addAllClassLoaderJarRoots(ClassLoader classLoader, Set<Resource> result) {
if (classLoader instanceof URLClassLoader) {
try {
for (URL url : ((URLClassLoader) classLoader).getURLs()) {
try {
UrlResource jarResource = new UrlResource(
                   //url自动在文件根目录前加/,例如:file:/E:/Program%20Files/JetBrains/IntelliJ%20IDEA%202018.3/lib/idea_rt.jar
ResourceUtils.JAR_URL_PREFIX + url.toString() + ResourceUtils.JAR_URL_SEPARATOR);
if (jarResource.exists()) {
result.add(jarResource);
}
}
catch (MalformedURLException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot search for matching files underneath [" + url +
"] because it cannot be converted to a valid 'jar:' URL: " + ex.getMessage());
}
}
}
}
catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot introspect jar files since ClassLoader [" + classLoader +
"] does not support 'getURLs()': " + ex);
}
}
}
     //如果是系统的loader继续添加
if (classLoader == ClassLoader.getSystemClassLoader()) {
// "java.class.path" manifest evaluation...
addClassPathManifestEntries(result);
}
。。。
protected void addClassPathManifestEntries(Set<Resource> result) {
try {
String javaClassPathProperty = System.getProperty("java.class.path");
for (String path : StringUtils.delimitedListToStringArray(
javaClassPathProperty, System.getProperty("path.separator"))) {
try {
File file = new File(path);
UrlResource jarResource = new UrlResource(ResourceUtils.JAR_URL_PREFIX +
ResourceUtils.FILE_URL_PREFIX + file.getAbsolutePath() +
ResourceUtils.JAR_URL_SEPARATOR);
if (jarResource.exists()) {
         //继续添加,这里会判断hashCode,因为set底层是一个hashMap,UrlResource有一个cleanedurl,通过它获取hashcode
         //能添加进去说明确实hashcode不一致,即他们的cleanedurl(就是一个文件路路径,类似jar:file:/E:/Program%20Files/JetBrains/IntelliJ%20IDEA%202018.3/lib/idea_rt.jar)不一样
result.add(jarResource);
}
}

上面这两个方法都是先new一个UrlResource,然后放到result中去,但是有个细节这里决定了两个对象的hashcode不一样:url.toString()就想我注释里写得一样它会在路径开始加一个'/',最后导致出现以下的结果:

jar:file:/E:/Program Files/JetBrains/IntelliJ IDEA 2018.3/lib/idea_rt.jar

jar:file:E:\Program Files\JetBrains\IntelliJ IDEA 2018.3\lib\idea_rt.jar

第四阶段:破局,好了,idea的原因找到了,为什么idea用tomcat启动没问题,eclipse怎么启动都没问题,先从简单入手,idea直接用tomcat启动发现他们的类加载器是tomcat自带的parallelxxX不属于系统类加载器,所以不执行addClassPathManifestEntries这个方法,

那eclipse又为什么test也能执行呢?继续追,发现eclipse在执行方法addClassPathManifestEntries中 String javaClassPathProperty = System.getProperty("java.class.path");代码的时候javaClassPathProperty这里面父类的路径居然是eclipse的路径(xxx/classs)而不是我的maven仓库的jar包路径(xxx/xx.jar),不是jar自然就不放到result中去了,到这里有点懵,但是知道有个方向,那就是去找eclipse和idea的管理项目的不同,eclipse父子项目是不需要打jar包的,但是我的idea是开了2个窗口,父项目必须打jar包才能运行,可不可以idea也不用打jar包,果然有解决方案(父子都在同一个窗口中),我就不写了随便找个说明(https://blog.csdn.net/nianbingsihan/article/details/82772801)这里注意一下,父项目如果是多个pom文件要全部引入,如果只引入最顶层的pom的话,其它的子项目是灰色表示没起作用,还是会走jar包,验证一下,把maven仓库中的jar包删除,果然不报错,运行test程序,终于见到了久违的通过!

idae父子项目Test执行报Result Maps collection already contains value for xxx的更多相关文章

  1. ssm 关于mybatis启动报Result Maps collection already contains value for ...的问题总结

    Result Maps collection already contains value for com.zhaike.mapping.ChapterMapper.BaseResultMap Err ...

  2. java.lang.IllegalArgumentException: Result Maps collection already contains value for xxx

    本人项目产生此问题的原因是: 本地备份了一份xxxmapper.xml的副本“xxxmapper - 副本.xml”,应该是系统会自动加载“mappe”目录下的所有xml文件. 参考:https:// ...

  3. MyBatis 中 Result Maps collection already contains value for xxx 错误原因

    出现此类错误的原因是同一个DAO操作多个Mapper导致的,将Mapper配置文件的  ResultMap的ID修改成不相同即可解决

  4. mybatis(错误一) 项目启动时报“Result Maps collection already contains value forxxx”的解决方案

    Result Maps collection already contains value for xyx.dsw.dao.mapper.admin.quotationwish.TempTestTab ...

  5. mybatis 异常Result Maps collection does not contain value for java.lang.String

    Result Maps collection does not contain value for java.lang.String 以上是我报的错. 只要报Result Maps collectio ...

  6. mybatisGenerator 代码自动生成报错 Result Maps collection already contains value for BaseResultMap--转

    转自:http://blog.csdn.net/tan3739/article/details/7555665 Exception in thread "main" Java.la ...

  7. mybatisGenerator 代码自动生成报错 Result Maps collection already contains value for BaseResultMap【转】

    由于mybatis简单易学,比起Hibername来,更容易上手,代码也能自动生成.这几天研究了下代码自动生成的,参考: http://0609xiaohua.iteye.com/blog/14535 ...

  8. 使用mybatis报错【Result Maps collection already contains value for ...BaseResultMap】的解决方法

    Result Maps collection already contains value for ...BaseResultMap ...... 这个问题,相信大家在使用mybatis的重新生成 d ...

  9. mybatis启动报错Result Maps collection already contains value forxxx

    ssm搭建过程中启动tomcat,报错: Cause: java.lang.IllegalArgumentException: Result Maps collection already conta ...

随机推荐

  1. vue,数组循环中src路径下图片总是不展示

    每次数组中带图片的src,图片总是不展示,搞得都怀疑是不是姿势不对.经过各方查看,还真不对 原因是因为图片路径在assets,所以需要require一下.其实就是require('path') 如a[ ...

  2. c# 编程--结构体

    结构体:由多种简单类型,组合成一种复杂的类型.使用这种复杂的类型来解决生活中的实际例子. 一.结构体定义:struct 结构体的名子{    public 类型名 变量名;    .....}    ...

  3. 【知识强化】第四章 网络层 4.4 IPv4

    这节课我们来学习一个非常重要的概念,就是IPv4地址,其实也是我们常用的IP地址. 首先我们来了解一下,为什么会有IP地址的出现以及它是做什么用的.假如说在很多年前我遇到一个女生非常的漂亮,等了十年之 ...

  4. Linux xargs 命令

    xargs xargs 是给命令传递参数的一个过滤器,也是组合多个命令的一个工具. xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据. xargs 也可 ...

  5. CF963E Circles of Waiting

    Circles of Waiting 求一个整点四连通随机游⾛,离原点距离超过R期望步数.R≤50. 带状矩阵法 本质上就是网格图的随机游走. \[ E_x=\sum_y P_{x,y}E_y+1 \ ...

  6. oracle时间问题 与case then

    思路一 --select * from nls_session_parameters where parameter='NLS_DATE_LANGUAGE'; -- 修改会话的默认日期格式 ALTER ...

  7. bzoj 3251

    http://www.lydsy.com/JudgeOnline/problem.php?id=3251 这道题在北京八十中的时候有人讲过.. 不过由于自己continue 写掉了一个所以调了很久. ...

  8. nucleus学习

    task的TCB结构: typedef struct TC_TCB_STRUCT { /* Standard thread information first. This information is ...

  9. throw throws 区别

    throw是语句抛出一个异常.语法:throw (异常对象);         throw e; throws是方法可能抛出异常的声明.(用在声明方法时,表示该方法可能要抛出异常)语法:[(修饰符)] ...

  10. Some Simple Mistakes I had

    This week, I had some mistakes. It is really hard to say: #1 py business what's happening l = abs(px ...