1. 获取spring-framework源码
1.1 clone方式
git clone https://github.com/spring-projects/spring-framework.git
cd spring-framework
git checkout 5.2.x # 切换到你需要的分支
1.2 download方式
访问spring的github地址(https://github.com/spring-projects/spring-framework),然后切换到你需要的分支,进行源码包下载。
如下图:
2. Spring 源码结构
获取到spring源码后,导入到IDEA中,代码结构如下图:
3. build
接下来进行代码构建,在IDEA右侧你会看到一个Gradle工具栏,点开会看到如下所示内容,找到下图红框所示命令,点击进行构建,构建过程中如果某个模块构建失败,可以先单独构建该模块,成功后,再整体构建。
看到下图状态,则代表构建成功。
4. 添加自定义调试模块
4.1 新增模块
按下面截图所示步骤可以快速创建一个基本的gradle模块。
4.2 修改build.gradle文件
模块创建好之后只有一个build.gradle文件,可以在里面添加需要调试的模块,如下:
plugins {
id 'java'
}
group 'org.springframework'
version '5.2.20.BUILD-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
// ========= 添加调试模块 start ===========
compile(project(":spring-beans"))
compile(project(":spring-core"))
compile(project(":spring-context"))
compile(project(":spring-webmvc"))
compile(project(":spring-jdbc"))
compile(project(":spring-orm"))
compile(project(":spring-tx"))
compile(project(":spring-web"))
// ========= 添加调试模块 end ===========
testCompile group: 'junit', name: 'junit', version: '4.12'
}
4.3 添加代码
然后添加代码,构建成如下图结构:
MyAppContext代码如下:
package com.hamajiao.spring.debug;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyAppContext {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
applicationContext.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
4.4 debug调试
完成以上步骤其实就已经可以愉快的操练起来了,按下面方式进行debug,先一睹spring的风采吧!
5. 常见错误
5.1 Checkstyle错误
错误内容如下:
Execution failed for task ':spring-debug:checkstyleMain'.
> Checkstyle rule violations were found. See the report at: file:///Users/gaoxiang/git/spring-framework/spring-debug/build/reports/checkstyle/main.html
Checkstyle files with violations: 1
Checkstyle violations by severity: [error:2]
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
> Task :spring-debug:checkstyleMain FAILED
[ant:checkstyle] [ERROR] /Users/gaoxiang/git/spring-framework/spring-debug/src/main/java/com/hamajiao/spring/debug/MyAppContext.java:1: header.missing [SpringHeader]
[ant:checkstyle] [ERROR] /Users/gaoxiang/git/spring-framework/spring-debug/src/main/java/com/hamajiao/spring/debug/MyAppContext.java:5:1: 工具类应隐藏 public 构造器。 [HideUtilityClassConstructor]
Execution failed for task ':spring-debug:checkstyleMain'.
> Checkstyle rule violations were found. See the report at: file:///Users/gaoxiang/git/spring-framework/spring-debug/build/reports/checkstyle/main.html
Checkstyle files with violations: 1
Checkstyle violations by severity: [error:2]
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
出现以上错误是因为spring使用了ant风格的代码检查,所有的检查规则都在src/checkstyle/checkstyle.xml里面做了配置,如果不想被这些检查烦扰到,可以全部注释掉:
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="com.puppycrawl.tools.checkstyle.Checker">
<!-- Suppressions -->
<!-- <module name="SuppressionFilter">-->
<!-- <property name="file" value="${config_loc}/checkstyle-suppressions.xml"/>-->
<!-- </module>-->
<!-- Root Checks -->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringHeaderCheck">-->
<!-- <property name="fileExtensions" value="java" />-->
<!-- <property name="headerType" value="apache2"/>-->
<!-- <property name="headerCopyrightPattern" value="20\d\d-20\d\d"/>-->
<!-- <property name="packageInfoHeaderType" value="none"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck">-->
<!-- <property name="lineSeparator" value="lf"/>-->
<!-- </module>-->
<!-- TreeWalker Checks -->
<!-- <module name="com.puppycrawl.tools.checkstyle.TreeWalker">-->
<!-- <!– Annotations –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck">-->
<!-- <property name="elementStyle" value="compact" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.annotation.MissingOverrideCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.annotation.PackageAnnotationCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationLocationCheck">-->
<!-- <property name="allowSamelineSingleParameterlessAnnotation"-->
<!-- value="false" />-->
<!-- </module>-->
<!-- <!– Block Checks –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.blocks.EmptyBlockCheck">-->
<!-- <property name="option" value="text" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.blocks.LeftCurlyCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck">-->
<!-- <property name="option" value="alone" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.blocks.NeedBracesCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.blocks.AvoidNestedBlocksCheck" />-->
<!-- <!– Class Design –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.design.FinalClassCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.design.InterfaceIsTypeCheck" />-->
<!--<!– <module name="com.puppycrawl.tools.checkstyle.checks.design.HideUtilityClassConstructorCheck" />–>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.design.MutableExceptionCheck">-->
<!-- <property name="format" value="^.*Exception$" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.design.InnerTypeLastCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.design.OneTopLevelClassCheck" />-->
<!-- <!– Type Names –>-->
<!-- <module name="TypeName">-->
<!-- <property name="format" value="^[A-Z][a-zA-Z0-9_]*(?<!Test)$" />-->
<!-- <property name="tokens" value="CLASS_DEF" />-->
<!-- <message key="name.invalidPattern"-->
<!-- value="Class name ''{0}'' must not end with ''Test'' (checked pattern ''{1}'')." />-->
<!-- </module>-->
<!-- <!– Coding –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.CovariantEqualsCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.EmptyStatementCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.EqualsHashCodeCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanExpressionCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.SimplifyBooleanReturnCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.StringLiteralEqualityCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedForDepthCheck">-->
<!-- <property name="max" value="3" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck">-->
<!-- <property name="max" value="5" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.NestedTryDepthCheck">-->
<!-- <property name="max" value="3" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck" />-->
<!-- <module name="io.spring.javaformat.checkstyle.filter.RequiresOuterThisFilter" />-->
<!-- <module name="io.spring.javaformat.checkstyle.filter.IdentCheckFilter">-->
<!-- <property name="names" value="logger" />-->
<!-- <module-->
<!-- name="com.puppycrawl.tools.checkstyle.checks.coding.RequireThisCheck">-->
<!-- <property name="checkMethods" value="false" />-->
<!-- <property name="validateOnlyOverlapping" value="false" />-->
<!-- </module>-->
<!-- </module>-->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringNoThisCheck">-->
<!-- <property name="names" value="logger" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.coding.OneStatementPerLineCheck" />-->
<!-- <!– Imports –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.RedundantImportCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.UnusedImportsCheck">-->
<!-- <property name="processJavadoc" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck">-->
<!-- <property name="groups" value="java,javax,*,org.springframework" />-->
<!-- <property name="ordered" value="true" />-->
<!-- <property name="separated" value="true" />-->
<!-- <property name="option" value="bottom" />-->
<!-- <property name="sortStaticImportsAlphabetically" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedImports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses"-->
<!-- value="^reactor\.core\.support\.Assert,^org\.slf4j\.LoggerFactory" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedJUnit3Imports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses" value="^junit\.framework\..+" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedJUnit4Imports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses"-->
<!-- value="^org\.junit\.(Test|BeforeClass|AfterClass|Before|After|Ignore|FixMethodOrder|Rule|ClassRule|Assert|Assume)$,^org\.junit\.(Assert|Assume)\..+,^org\.junit\.(experimental|internal|matchers|rules|runner|runners|validator)\..+" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedJUnitJupiterImports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses" value="^org\.junit\.jupiter\..+" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedTestNGImports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses" value="^org\.testng\..+," />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">-->
<!-- <property name="id" value="bannedHamcrestImports"/>-->
<!-- <property name="regexp" value="true" />-->
<!-- <property name="illegalClasses" value="^org\.hamcrest\..+" />-->
<!-- </module>-->
<!-- <!– Javadoc Comments –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTypeCheck">-->
<!-- <property name="scope" value="package"/>-->
<!-- <property name="authorFormat" value=".+\s.+"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck">-->
<!-- <property name="allowMissingParamTags" value="true"/>-->
<!-- <property name="allowMissingThrowsTags" value="true"/>-->
<!-- <property name="allowMissingReturnTag" value="true"/>-->
<!-- <property name="allowMissingJavadoc" value="true"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocVariableCheck">-->
<!-- <property name="scope" value="public"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocStyleCheck">-->
<!-- <property name="checkEmptyJavadoc" value="true"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.NonEmptyAtclauseDescriptionCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagContinuationIndentationCheck">-->
<!-- <property name="offset" value="0"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.AtclauseOrderCheck">-->
<!-- <property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF"/>-->
<!-- <property name="tagOrder" value="@author, @since, @param, @see, @version, @serial, @deprecated"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.javadoc.AtclauseOrderCheck">-->
<!-- <property name="target" value="METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>-->
<!-- <property name="tagOrder" value="@param, @return, @throws, @since, @deprecated, @see"/>-->
<!-- </module>-->
<!-- <!– Miscellaneous –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.indentation.CommentsIndentationCheck">-->
<!-- <property name="tokens" value="BLOCK_COMMENT_BEGIN"/>-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.UpperEllCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.ArrayTypeStyleCheck" />-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.OuterTypeFilenameCheck" />-->
<!-- <!– Regexp –>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="format" value="^\t* +\t*\S" />-->
<!-- <property name="message"-->
<!-- value="Line has leading space characters; indentation should be performed with tabs only." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpCheck">-->
<!-- <property name="format" value="[ \t]+$" />-->
<!-- <property name="illegalPattern" value="true" />-->
<!-- <property name="message" value="Trailing whitespace" />-->
<!-- </module>-->
<!-- <module-->
<!-- name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="maximum" value="0" />-->
<!-- <property name="format"-->
<!-- value="assertThatExceptionOfType\((NullPointerException|IllegalArgumentException|IOException|IllegalStateException)\.class\)" />-->
<!-- <property name="message"-->
<!-- value="Please use specialized AssertJ assertThat*Exception method." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="id" value="bddMockito"/>-->
<!-- <property name="maximum" value="0"/>-->
<!-- <property name="format" value="org\.mockito\.Mockito\.(when|doThrow|doAnswer)" />-->
<!-- <property name="message" value="Please use BDDMockito." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="id" value="expectedExceptionAnnotation"/>-->
<!-- <property name="maximum" value="0"/>-->
<!-- <property name="format" value="\@Test\(expected" />-->
<!-- <property name="message" value="Please use AssertJ assertions." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="id" value="junit4Assertions"/>-->
<!-- <property name="maximum" value="0"/>-->
<!-- <property name="format" value="org\.junit\.Assert\.assert" />-->
<!-- <property name="message" value="Please use AssertJ assertions." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="id" value="junitJupiterAssertions"/>-->
<!-- <property name="maximum" value="0"/>-->
<!-- <property name="format" value="org\.junit\.jupiter\.api\.Assertions\.assert" />-->
<!-- <property name="message" value="Please use AssertJ assertions." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">-->
<!-- <property name="id" value="testNGAssertions"/>-->
<!-- <property name="maximum" value="0"/>-->
<!-- <!– should cover org.testng.Assert and org.testng.AssertJUnit –>-->
<!-- <property name="format" value="org\.testng\.Assert(JUnit)?\.assert" />-->
<!-- <property name="message" value="Please use AssertJ assertions." />-->
<!-- <property name="ignoreComments" value="true" />-->
<!-- </module>-->
<!-- <!– Spring Conventions –>-->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringLambdaCheck">-->
<!-- <property name="singleArgumentParentheses" value="false" />-->
<!-- </module>-->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringCatchCheck" />-->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringJavadocCheck" />-->
<!-- <module name="io.spring.javaformat.checkstyle.check.SpringJUnit5Check" />-->
<!-- </module>-->
</module>
当然如果不想这么粗暴全部注释,可以只注释掉错误对应的检查规则,比如我上面出现的错误,我这里可以注释掉以下两个规则:
<!-- Root Checks -->
<!-- 检查SpringHeader 每个类开头部分必须是版权声明-->
<module name="io.spring.javaformat.checkstyle.check.SpringHeaderCheck">
<property name="fileExtensions" value="java" />
<property name="headerType" value="apache2"/>
<property name="headerCopyrightPattern" value="20\d\d-20\d\d"/>
<property name="packageInfoHeaderType" value="none"/>
</module>
<!-- 检查HideUtilityClassConstructor 工具类应私有化构造器 并声明为final 避免被创建对象-->
<module name="com.puppycrawl.tools.checkstyle.checks.design.HideUtilityClassConstructorCheck" />
另外你也可以按照规则一一进行修改来满足规则要求,比如将MyAppContext改成如下内容:
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hamajiao.spring.debug;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class MyAppContext {
private MyAppContext() {
}
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
总之以上三种方法都可以解决这类错误。当然了,这类错误不解决也不会影响你debug,但是作为患有强迫症晚期的我来说,看到任何错误都是无法忍受的!
5.2 某个模块build失败
某个模块build失败的时候,可以先单独构建该模块,成功后,再整体构建。
5.3 连接问题
有些时候网络不稳定会导致依赖下载失败,一般多试几次都可以下载成功的。