Spring源码阅读环境搭建(以及执行单元测试后的错误解决)

前期运行环境与工具准备

  • JDK版本:1.8.0_162 (版本1.8就行,我的是1.8最新版,高于1.8的没试过)
  • 下载地址:https://www.oracle.com/technetwork/cn/java/javase/downloads/jdk8-downloads-2133151-zhs.html
  • GRADLE版本:4.10.3(也可用idea自带的gradle导入就行,如果自己安装需要配置相关环境)
  • 注意:这里会有一个问题,就是如果我们创建的项目和Gradle版本冲突了怎么办,也就是说Spring需要的版本和我们下载的版本不一致时怎么办?

  • 解决:我们先不配置Gradle,在本地打开 Spring 目录,在当前目录打开 cmd,输入命令:

  • gradlew :spring-oxm:compileTestJava

  • 出现BUILD SUCCESS字样时说明构建成功,如下图所示
  • bulid
  • 在 Spring-frameword-5.1x/.gradle 目录中可以看到 4.10.3,那么下载4.10.3版本即可。
  • 另外,如果电脑本身就有Gradle那么直接进行下一个板块的步骤,导入IDEA,在IDEA中编译 compileTestJava 即可,可以以看到相应的 Gradle 版本
  • 当然下载好之后要重新配置 Gradle 的环境变量,我就是因为电脑本身就有 Gradle,弄了很多次都不行,最后重新下载对应版本的 Gradle 版本。
  • 配置教程:https://www.cnblogs.com/linkstar/p/7899191.html
  • 这里得再加一步,为了编译过程更快,我们为安装好的Gradle配置国内镜像
  • 进入 Gradle 安装目录,在 init.d 目录下新建一个 init.gradle 文件,并添加以下内容:
  • allprojects{
        repositories {
            def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/'
            all { ArtifactRepository repo ->
                def url = repo.url.toString()
                if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) {
                    project.logger.lifecycle 'Repository ${repo.url} replaced by $REPOSITORY_URL .'
                    remove repo
                }
            }
            maven {
                url REPOSITORY_URL
            }
        }
    }
  • Spring 源码版本:v5.1.X.RELEASE (目前最新版为:5.2.1.RELEASE,下载最好用VPN,不然很慢)
  • 下载地址:https://github.com/spring-projects/spring-framework
  • IntelliJ IDEA版本:IntelliJ IDEA 2018.2.5(2017也可以,我的是2018)
  • 下载地址:https://www.jetbrains.com/idea/download/
  • 系统:WINDOWS 10

下载源码

  • 我这里选择的是5.1.x版本的Spring,然后点击Clone or download,如果会Git可以使用Git命令的方式,不会的话选择下载ZIP压缩包,下载好之后需要解压
  • 解压好之后,我们为 Spring 添加阿里云镜像
  • 在编译过程中,Spring会去自动下载一些依赖的包,默认使用的是官方的镜像,下载比较慢,所以我们提前添加好国内镜像,将下面这行代码粘贴到build.gradle文件中的repositories节点下即可 
  • //添加阿里云镜像
    maven { url "http://maven.aliyun.com/nexus/content/groups/public" }

导入IDEA

  • 点击File->New->Project form Existing Sources...打开项目
  • 选择刚刚解压的spring项目工程
  • 选择 Gradle
  • 选择自己配置的Gradle环境
  • 调整内存:-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
  • 点击Finish
  • 注意:在点击finish前,最好是能够开启VPN,构建过程会要下载大量的依赖包跟插件,这里下载要很长时间我当时没有及时,做好去吃个饭,回来就差不多了,吃得快的可以再吃一顿,反正很慢。

  • 下载过程:

  • 项目导入到IDEA成功,如下图所示:

开始准备编译

  • 修改docs.gradle文件
    • 打开docs.gradle文件准备修改
  • 注释掉dokka和asciidoctor两个配置项
    • 因为在构建过程中执行这两个任务时会导致构建失败,这两个任务主要是用来生成文档使用,对主流程并没有任何影响,可以直接忽略,当然如果大家本地没有这个问题,也可以不注释。
  • 替换docs.gradle文件中的task schemaZip配
    • gradle的构建脚本,只针对Linux系统做了适配,需要把task schemaZip替换成下面代码,因为原有代码的路径符号" / "是针对Linux的,windows使用会有问题,在windows环境需要替换成" \\ "否则会出现异常。
    • 参考如下代码,注释部分是原有的代码:
    • //这部分被替换了,所以需要被替换掉
      //task schemaZip(type: Zip) {
      //	group = "Distribution"
      //	baseName = "spring-framework"
      //	classifier = "schema"
      //	description = "Builds -${classifier} archive containing all " +
      //			"XSDs for deployment at https://springframework.org/schema."
      //	duplicatesStrategy 'exclude'
      //	moduleProjects.each { subproject ->
      //		def Properties schemas = new Properties();
      //
      //		subproject.sourceSets.main.resources.find {
      //			(it.path.endsWith("META-INF/spring.schemas") || it.path.endsWith("META-INF\\spring.schemas"))
      //		}?.withInputStream { schemas.load(it) }
      //
      //		for (def key : schemas.keySet()) {
      //			def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
      //			assert shortName != key
      //			File xsdFile = subproject.sourceSets.main.resources.find {
      //				(it.path.endsWith(schemas.get(key)) || it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')))
      //			}
      //			assert xsdFile != null
      //			into (shortName) {
      //				from xsdFile.path
      //			}
      //		}
      //	}
      //}
      
      //替换成如下代码即可
      task schemaZip(type: Zip) { 
          group = "Distribution" 
          baseName = "spring-framework" 
          classifier = "schema" 
          description = "Builds -${classifier} archive containing all " + 
                  "XSDs for deployment at http://springframework.org/schema." 
          duplicatesStrategy 'exclude' 
          moduleProjects.each { subproject -> 
              def Properties schemas = new Properties(); 
              subproject.sourceSets.main.resources.find { 
                  it.path.endsWith("META-INF\\spring.schemas") 
              }?.withInputStream { schemas.load(it) } 
      
              for (def key : schemas.keySet()) { 
                  def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
                  assert shortName != key 
                  File xsdFile = subproject.sourceSets.main.resources.find { 
                      it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')) 
                  } 
                  assert xsdFile != null 
                  into (shortName) { 
                      from xsdFile.path 
                  } 
              } 
          } 
      }
      
  • 到现在编译前的准备工作才算完成

根据import-into-idea.md文档步骤去构建

  • 打开spring工程的import-into-idea.md文件
    • import-into-idea.md里面详细的描述了编译步骤,根据import-into-idea.md文档里面介绍,我们需要对spring-core和spring-oxm做预编译
  • 预编译
    • 在IDEA中预编译很简单,按下图操作即可:
    • 注意:如果右侧没有Gradle那么可以在View中让它显示
    • 出现如下图所示,表示预编译成功
    • 上边的过程演示了 :spring-oxm 的预编译,:spring-core和它同理这里就不演示了,成功显示如下图即可
  • 终极编译
    • 对整个Spring项目构建,这个时候它会自动下载依赖包,如果有异常,会在控制台抛出并停止操作,编译整个工程,需要20分钟左右的时间。
    • 构建成功在控制台可以看到下图提示

执行单元测试

  • 即使整个项目没有Error或者红点,也不代表项目已经成功构建好了,我们还需要执行个单元测试试下,如果能顺利执行单元测试,那证明该项目已经构建成功,这里我用到的是DispatcherServletTests这个类,直接运行查看结果:
  • 我第一次执行的时候报错了,错误如下:
  • 网上找了很多解决办法还是没用
  • 比如这个:
  • 结果出来的错误更离谱,网上根本找不到相关示例,最后实在是找不到只能重新再来一次
  • 还有这个:
  • 这个还是不行,虽然报错没有更离谱,但是还是会有错误,只是错误没有改变罢了
  • 还有这个:
  • 这个还是不行,把这个类注释掉,那么还会有其他类报错,最后根本注释不完
  • 最后我也找了很久,终于让我找到了
  • 视频参考:https://www.bilibili.com/video/av76404922
  • 解决办法就是将找不到符号的那个类的子模块的build文件删除,再次重新build一遍即可,如果还是不行那么把该模块的text文件中的代码重新运行run一遍,之后再运行测试类即可。之后如果还是显示找不到符号,重复上述步骤即可。
  • 看完视频我的使用视频中的方式,之后还是会有其他的报错,但是报的错都是找不到符号,我还是使用同样的方法,进行重新rebuild,之后再将text中的类重新运行run一遍即可。
  • 很明显,上面单元测试类的所有单测执行成功。
  • 当我第二次安装的时候又遇到了不一样的坑
  • 在编译 spring-aspect 的 javadoc 时我等了半个多小时还是不动,之后又重新弄了很多次,还是不行。
  • 解决:注释掉 build.gradle 中的一些代码:
  • //	javadoc {
    //		description = "Generates project-level javadoc for use in -javadoc jar"
    //
    //		options.encoding = "UTF-8"
    //		options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
    //		options.author = true
    //		options.header = project.name
    //		options.use = true
    //		options.links(project.ext.javadocLinks)
    //		options.addStringOption("Xdoclint:none", "-quiet")
    //
    //		// Suppress warnings due to cross-module @see and @link references.
    //		// Note that global 'api' task does display all warnings.
    //		logging.captureStandardError LogLevel.INFO
    //		logging.captureStandardOutput LogLevel.INFO  // suppress "## warnings" message
    //	}
    
    	task sourcesJar(type: Jar, dependsOn: classes) {
    		duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    		classifier = "sources"
    		from sourceSets.main.allSource
    		// Don't include or exclude anything explicitly by default. See SPR-12085.
    	}
    
    //	task javadocJar(type: Jar) {
    //		classifier = "javadoc"
    //		from javadoc
    //	}
    
    	artifacts {
    		archives sourcesJar
    //		archives javadocJar
    	}
    }
  • 然后暂停当前运行,重新 build 即可。

可能遇到的坑点回顾

  • 构建成功没报错,但运行单元测试有异常 ,提示类找不到
    • 方案1:尝试点击右边菜单栏projects刷新项目,然后对Spring(Root)模块先clean再build一次
    • 方案2:针对找不到类的模块重新build一次
    • 方案3:点击Spring(root)模块下的Tasks->other->compileTestJava 执行一遍,针对test类编译一次即可
  • 构建失败,缺少依赖包
    • 方案1:对Spring(Root)模块先clean再build一次(建议打开VPN,有可能存在某些包下载不成功导致)
    • 方案2:尝试针对当前模块执行buildDependents
  • 构建失败,执行gradle task失败
    • 方案1:可能是当前运行环境版本不支持问题,如果不重要的问题,可以注释掉,保证构建正常
  • 构建失败,编码异常
    • 方案1:可以通过idea工具设置:Editor-File encodings 全部设置为UTF-8

有兴趣的同学可以关注我的个人公众号,期待我们共同进步!!!

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值