Spring 源码解析 - 环境搭建

736 阅读3分钟

学习源码个人建议还是当一份源码下来,自己编译运行一下,也方便做笔记等。虽然过程中会有一点磕绊,但整体来说,Spring的源码环境搭建还是比较容易的。

准备环境

  • 源码

    • github.com/spring-proj…
    • master等其他版本可能为spring内部开发人员使用的,会包含一些他们内部仓库才有的东西,所以最好切到某个relase的tag下。
    • 我们这里选择当前最新的relase版本
  • gradle

    • 目前最新的spring使用了gradle作为系统构建器
    • 虽然源码说内置了一个gradle环境,不需要我们在自己环境中配置gradle,但是我在编译时候出现了一些问题,所以建议还是自己环境配一个。
    • spring对gradle的版本也有要求,但是官网没有说,我最终使用的gradle版本是gradle-5.6.4。(在编译过程中,spring也会自动下载需要的版本)
  • jdk

    • 官方上说jdk8就行,但是如果直接使用Oracle的jdk8是有问题的,会有部分类缺失。

    • 网上查阅有人使用Orcale的jdk11解决了,但是我们配置了依然不好使,最后使用的是官方给的链接的open-jdk

      To build you will need Git and JDK 8 update 262 or later.

    • 我使用的jdk版本为

开始编译

为了防止意外,最好紧跟spring文档的步骤来:官方指导

一些调整

因为我单独下了一个open-jdk,但是我系统当前环境默认的jdk版本还是jdk8,所以我们需要修改下编译脚本,让它使用我们指定的jdk的版本。

主要就是修改gradlew脚本下面这段:(如果你是windows系统就修改gradlew.bat)

我的修改如下:

# 这里指定你配置的jdk位置
JAVA_TMP_HOME=/Users/***/workspace/env/jdk/open-jdk-11.0.10
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_TMP_HOME" ] ; then
    if [ -x "$JAVA_TMP_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_TMP_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_TMP_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_TMP_HOME

官网步骤

  • ./gradlew build
    • 下载需要的gradle版本以及相关 依赖,并且会执行所有的测试case。这个步骤会花费比较长时间。
    • 一般情况下,就能编译通过了,如下:
  • 导入idea
    • 参考官方文档
    • 注意设置下Project对应的JDK版本,以及Gradle版本。
    • 具体步骤
      • 预编译:./gradlew :spring-oxm:compileTestJava
      • 导入gradle项目,等待idea 下载依赖以及index过程
      • 排除spring-aspects 模块
    • 最终导入完成如图:

测试

我们添加一个新的gradle模块:spring-samples

  1. 添加相关的依赖,修改build.gradle添加如下:

    dependencies {
        compile(project(":spring-context"))
        testCompile group: 'junit', name: 'junit', version: '4.12'
    }
    
    jar.enabled(true)
    
  2. 添加一个启动类MainApplication以及一个HelloWorld的bean实体,如图

  1. 里面内容如下:

    1. MainApplication
    @Configuration
    // 扫描路径
    @ComponentScan("org.springframework.samples")
    public class MainApplication {
    	public static void main(String[] args) {
        // 基于注解的容器
    		AnnotationConfigApplicationContext applicationContext =
    				new AnnotationConfigApplicationContext(MainApplication.class);
    		String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    		Stream.of(beanDefinitionNames).forEach(System.out::println);
    		// 获取helloworld bean
    		HelloService helloServiceImpl = applicationContext.getBean("helloServiceImpl", HelloService.class);
    		helloServiceImpl.sayHello();
    	}
    }
    
    1. HelloWorld Bean
    public interface HelloService {
    	String sayHello();
    }
    @Service
    public class HelloServiceImpl implements HelloService {
    	@Override
    	public String sayHello() {
    		System.out.println("Hello World !");
    		return "HelloWorld!";
    	}
    }
    
  2. 运行main方法,环境搭建完毕。