现象:同一个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. ingress-nginx配置https文件访问

    1.先将证书文件上传至服务器特定目录.比如:/root/ssl 假设证书名称为:server.crt和server.key 2.现在主节点后台创建私密文件. kubectl create secret ...

  2. bzoj2582 [Usaco2012Jan]Bovine Alliance

    [Usaco2012Jan]Bovine Alliance Time Limit: 2 Sec Memory Limit: 128 MB Description Bessie and her bovi ...

  3. ThinkPHP5.1x 中间件实现原理

    ThinkPHP5.1x的中间件,其核心还是闭包函数的应用,来实现“责任链”模式: 模拟代码: <?php //模拟的控制器 class Controller { public function ...

  4. 虚拟机设置静态IP地址

    前言 NAT连接方式只能配置一次,配置好子网掩码和网关IP后,虚拟机NAT连接的ip段都是同一个ip段 1.菜单栏选择 编辑 -> 虚拟网络编辑器,打开虚拟网络编辑器对话框,选择Vmnet8 N ...

  5. java中数据库和VO的一一对应关系

    如图所示,数据库中数据如果有下划线,则JavaVO中删除,除第一个单词外,其他单词首字母大写

  6. Tomcat6 只允许指定域名访问,禁用IP地址访问,防止恶意解析

    运维网监控突然同事反应,在百度上搜索其他域名,竟然打开了和我们P2P一模一样的网站,我第一个反应是源代码被盗用了.后来发现,是域名被恶意解析了,解决方法 1.禁止IP地址访问项目 2.只允许指定的域名 ...

  7. SpringBoot2.0总结

    与SpringCloud关系 与SpringMVC关系 与JFinal区别 常用注解: @RestController  @EnableAutoConfiguration   @ComponentSc ...

  8. Mysql 列变行其中一种做法。

    需求是: 上班打卡记录   和  下班打卡记录  是分别是两条数据,现在是要合并为一条数据,并且封装成一个实体. 有可能是 只有上班记录,,或者是只有下班的记录.如何关联全查,一边为null或者另一边 ...

  9. Vue的安装和使用详解(一)

    Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与 ...

  10. python笔试做错的题目

    a = [1,2,3] b = a print(id(a),id(b),a == b) print(a,b) b = b + [1,2,3] print(a,b) print(id(a),id(b), ...