Spring5源码编译记录

172 阅读4分钟

身为一个合格java程序员,居然没有去编译过Spring 源码!!!

前言:

从事java开发工作三载有余, 咋子说三年工作中java框架就是Spring 全家桶这一套。要是说对这个框架已经非常熟悉、了然于胸。 其实也没有最主要是对这个框架的使用和了解些基本的原理,可以熟练使用它来完成日常的业务开发,然后在这个过程中就会发现Spring 软件框架的设计的精妙😀。 通过对Spring 源码的学习让自己加深对 编程思想、设计模式的认知。so... 便想重新从源码的角度去学习Spring,一方面可以巩固之前学习的设计模式及其应用用,另一方面提高一下自己阅读源码的能力。最后希望自己可以坚持阅读下去 💪 💪 💪。

环境

  • git-version: git下载
  • java-versioin: 1.8
  • Idea: IntelliJ IDEA 2020.1 (Ultimate Edition)
  • Gradle-version:gradle-5.6.2
  • spring 5.x

拉取Spring源码

github 拉取代码

  • 首先在 github 上面搜索 spring

    image.png

    选择点击 spring-projects 这个仓库,进入以下界面

    image.png

    在这个界面中拉取代码即可。

  • Spring 源码获取方式有两种

    1. 直接拉取代码到本地后切换分支

    • 复制git 仓库地址

    image.png

    git clone git@github.com:spring-projects/spring-framework.git [-b branch(指定分支名称)]

    • 在电脑建好对应的文件夹,使用git 命令行拉取代码(建议使用ssh协议方式拉取)

    image.png

    • 下载完成(因为在github中可能需要亿点点时间)后,使用git bash 进入对应的目录

    image.png

    使用git命令在本地创建开发分支 git checkout -b new_brancha_name tag_name 如:

    git checkout -b 5.2.0 v5.2.0

    以上步骤完成之后进入目录如图所示:

    image.png

    2. 使用fork 到自己的仓库中方式

      > fork是“分叉”、“复制”的意思;fork可以复制出一个仓库的新拷贝,包含了原有库中的所有提交记录,fork后这个代码库是完全独立的,可以在自己的库中做任何修改,也可以向原来的库提交合并请求。
    
    • spring-frameworkfork到自己github的Repositories

    步骤一:

    image.png

    步骤二:

    image.png

    步骤三:

    image.png

    • 完成以上步骤,按照【1】 中的将代码clone 到本地,并选择需要编译、阅读源码的分支。

编译前准备工作

按照上面的步骤来,会得到下面的一个目录机构,之后就可以对spring 源码进行编译了。

image.png

进入目录后我们发现Spring使用的Gradle来构建的(3.x 使用的还是maven 具体是那个版本换到gradle不清楚,相较于前者编译是速度杠杠滴)。这里先不着急把项目导入idea,需要先安装Gradle,安装完成后改些配置。

这里为啥要先改配置的主要原因是

1、 学习过Gradle的老师都知道使用Gradle 构建的java项目都有一个gradle/wapper文件夹 (wrapper包装器),gradle-wrapper.properties文件中有配置项目需要的gradle下载地址。 如 distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip,warapper包装器的作用:用于解决实际开发中可能会遇到的不同的项目需要不同版本的 Gradle问题。也是Gradle 官方推荐的做法。如果不想在本地安装Gradle 可以直接使用项目GradleWrapper中自带的版本。

2、需要改动Gradle中对应的maven镜像源由国外的改成阿里的中央仓库,主要原因是为了快速的下载jar包,让编译快亿点。

  • 在项目目录找到 /e/openSourceProject/spring-framework/gradle/wrapper 中的 gradle-wrapper.properties 文件里面有对应该SpringTag使用的gradle版本。下载对应的版本(如果不使用对应的gradle版本编译的时候会报一些奇奇怪怪的错,别问为啥😭😭😭)gradle下载地址

    image.png

  • gradle下载放到本地的目录,修改gradle-wrapper.properties文件distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip 改成 distributionUrl=file\:///D:/JetBrains/gradle-5.6.2-bin/gradle-7.2-bin.zip

  • 分别配置 build.gradlesettings.gradle 国内镜像源

    • build.gradle

      repositories {
      	maven { url "https://maven.aliyun.com/repository/public" }
      	maven { url "https://maven.aliyun.com/repository/gradle-plugin"}
      	mavenCentral()
      	maven { url "https://repo.spring.io/libs-spring-framework-build" }
      }
      
    • settings.gradle

      pluginManagement {
          repositories {
                  maven { url "https://maven.aliyun.com/repository/public" }
                  maven { url "https://maven.aliyun.com/repository/gradle-plugin"}
                  mavenCentral()
                  gradlePluginPortal()
                  maven { url "https://repo.spring.io/release" }
          }
      }
      

完成以上准备动作接下来开始编译,cmd 打开本地spring项目目录: 执行Gradle命令:./gradlew :spring-oxm:compileTestJava 开始编译,如图所示: image.png 等待几分钟☕☕☕☕...最后你会看到如下信息

image.png

到这里为止Spring源码就编译成功了😄。

导入Idea

源码编译成功,需要阅读源代码和Debug就得导入到Idea中,打开Idea-> File->New->Project From existing Source->选择spring项目目录->选中build.gradle-> Open file as Project 等待几分钟。Idea在Builde过程中没有报错就可以进行下面的测试了。

测试

在Spring项目下新建子模块 File-> Project Structure->Modules-> + -> New Module 如图

image.png

目录结构如下如所示:

image.png

在build.gradle中加入对应的依赖

plugins {
    id 'java'
}

group 'org.springframework'
version '5.2.0.RELEASE'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    implementation(project(":spring-context"))
    implementation(project(":spring-beans"))
    implementation(project(":spring-core"))
}

配置类:

package com.chou.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author Axel
 * @version 1.0
 * @className AppConfig
 * @description TODO
 * @date 2022/8/7 11:21
 */

@Configuration
@ComponentScan(value = "com.chou.spring")
public class AppConfig {
   // 扫描com.chou.spring 下面所有的bean
}

业务类:

package com.chou.spring.service;

import org.springframework.stereotype.Service;

/**
 * @author Axel
 * @version 1.0
 * @className HolleService
 * @description TODO
 * @date 2022/8/7 11:28
 */

@Service
public class HelloService {
   public void hello(){
      System.out.println("hello spring source code !");
   }
}

测试类:

package com.chou.spring;

import com.chou.spring.config.AppConfig;
import com.chou.spring.service.HelloService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author Axel
 * @version 1.0
 * @className ChouSpringTest
 * @description TODO
 * @date 2022/8/7 11:29
 */

public class ChouSpringTest {

   public static void main(String[] args) {
      AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
      HelloService helloService = applicationContext.getBean(HelloService.class);
      helloService.hello();
   }
}

运行 ChouSpringTest 结果如下:

image.png

到此为止Spring源码编译就结束了🤡🤡🤡