spring源码搭建记录
1.1 构建工具
Spring源码工程使用的项目构建工具不是Maven,而是Google的Gradle。首先需了解该工具并安装。
1.1.1 Gradle简介
Gradle是一款Google推出的 基于JVM、 通用灵活的 项目构建工具, 支持Maven,JCenter多种第三方仓库;支持传递性依赖管理、废弃了繁杂的xml文件,转而使用 简洁的 、 支持多种语言 (例如:java、groovy等)的 build脚本文件 。
1.1.2 与常见的项目构建工具对比
- Ant: 2000 年Apache推出的纯Java编写构建工具,通过xml[build.xml]文件管理。
- 优点 :使用灵活,速度快(快于gradle和maven)。
- 缺点:Ant没有强加任何编码约定的项目目录结构,开发人员需编写繁杂XML文件构建指令,对开发人员是一个挑战。
- Maven: 2004年Apache组织推出的再次使用xml文件[pom.xml]管理项目的构建工具。
- 优点:遵循一套约定大于配置的项目目录结构,使用统一的GAV坐标进行依赖管理, 侧重于包管理 。
- 缺点:项目构建过程僵化,配置文件编写不够灵活、不方便自定义组件,构建速度慢于gradle。
- Gradle: 2012年Google推出的基于Groovy语言的全新项目构建工具,集合了Ant和Maven各自的优势。
- 优点:集Ant脚本的灵活性+Maven约定大于配置的项目目录优势,支持多种远程仓库和插件 ,侧重于大项目构建 。
- 缺点:学习成本高、资料少、脚本灵活、版本兼容性差等。
1.1.3 gradle下载
- 下载地址:https://gradle.org/
1.1.4 Gradle安装
- 新建系统变量GRADLE_HOME,值为gradle解压目录
- 新建系统变量GRADLE_USER_HOME,值为仓库目录
- Path变量增加%GRADLE_HOME%/bin路径
- 验证安装结果,cmd内输入gradle -v
1.2 jdk与源码版本
- Spring Framework 6.0.x: JDK 17-21 (expected)
- Spring Framework 5.3.x: JDK 8-19 (expected)
- Spring Framework 5.2.x: JDK 8-15
- Spring Framework 5.1.x: JDK 8-12
- Spring Framework 5.0.x: JDK 8-10
- Spring Framework 4.3.x: JDK 6-8
1.3 源码下载与导入
1.3.1 源码下载地址
github链接: https://github.com/spring-projects/spring-framework
若github速度慢,可以使用gitee导入github项目。
gitee导入github项目: https://gitee.com/projects/import/url
1.3.2 源码下载
git clone https://github.com/spring-projects/spring-framework
切换到5.2.x分支
git branch 5.2.x
目录如下
1.3.3 导入前修改配置
1. spring-framework\gradle\wrapper\gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
此处需要将gradle的下载地址切换为阿里的镜像提高速度,由于gradle各个版本的语法和配置不一样,不能修改gradle版本。
阿里镜像地址:https://mirrors.aliyun.com/macports/distfiles/gradle/
获取镜像地址后,将文件内容改为:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https://mirrors.aliyun.com/macports/distfiles/gradle/gradle-5.6.4-bin.zip
# 或distributionUrl=file\:///e:/software/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2. spring-framework\gradlew.bat
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
调整下列内容可以在spring源码中添加中文注释,否则编译会报错
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" "-Dfile.encoding=UTF-8"
3.spring-framework\build.gradle
最上方添加以下内容:
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/spring' }
maven { url "https://repo.spring.io/plugins-release-local" }
maven { url "https://repo.spring.io/plugins-release" }
}
}
buildscript是gradle脚本执行需要的依赖。
然后找到configure(allprojects)配置的repositories ,改为以下内容:
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/spring' }
mavenCentral()
maven { url "https://repo.spring.io/libs-spring-framework-build" }
}
allprojects里是项目本身需要的依赖。表示项目里面每个build.gradle 里面的库都会依赖用这些仓库。
1.3.4 idea导入
1.3.5 新建测试模块spring-source-debug
调整spring-source-debug/build.gradle内容
plugins {
id 'java'
}
group = 'cn.fxy'
version = '5.2.26.BUILD-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
# 新增以下内容
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional(project(":spring-aop"))
optional(project(":spring-context"))
}
test {
useJUnitPlatform()
}
测试代码:
Person.java
public class Person {
String name;
String sex;
int age;
}
AnnoConfig.java
@Configuration
@Import(MyImportRegistar.class)
public class AnnoConfig {
@Bean
public Person person(){
Person person = new Person();
person.setName("张三");
return person;
}
}
/**
* BeanDefinitionRegistry:bean定义注册中心,bean图纸中心
*/
class MyImportRegistar implements ImportBeanDefinitionRegistrar{
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition definition = new RootBeanDefinition();
definition.setBeanClass(Person.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("name","李四");
definition.setPropertyValues(propertyValues);
registry.registerBeanDefinition("personLs",definition);
}
}
AnnoApplicationDebug.java
public class AnnoApplicationDebug {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AnnoConfig.class);
String[] names = context.getBeanDefinitionNames();
for (String name : names) {
System.out.println("bean:"+name);
}
Map<String, Person> pBeanMap = context.getBeansOfType(Person.class);
pBeanMap.entrySet().forEach(entry -> {
Person person = entry.getValue();
System.out.println("person-name:"+person.getName());
});
}
}
执行结果:
1.3.6 新增测试模块springmvc-source-debug
调整springmvc-source-debug/build.gradle内容
plugins {
id 'java'
// 新增插件会自动创建artifacts输出
id 'war'
}
group = 'cn.fxy'
version = '5.2.26.BUILD-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
//新增以下配置
compile(project(":spring-webmvc"))
compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.0'
}
test {
useJUnitPlatform()
}
刷新工程后查看配置
配置tomcat
测试代码
SpringMvcConfig .java 配置包扫描
@Configuration
@ComponentScan(value = "cn.fxy.spring.web.controller", includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})
public class SpringMvcConfig {
}
HelloController.java
@RestController
public class HelloController {
@GetMapping("hello")
public String hello() {
return "hello,SpringMvc";
}
}
MyWebApplicationInitializer.java
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// 创建IOC容器
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
//context.register(SpringConfig.class);//注册Spring配置类
context.register(SpringMvcConfig.class);//注册SpringMvc配置类
// 创建DispatcherServlet,并且将IOC容器保存到DispatcherServlet中
DispatcherServlet servlet = new DispatcherServlet(context);
// 利用Servlet规范添加自己创建的servlet
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
//该函数用于设置在Web应用程序启动时是否加载指定的Servlet。参数loadOnStartup是一个整数,如果其值大于等于0,则表示在应用程序启动时加载该Servlet,并且其值越小,加载的优先级越高;如果其值为-1,则表示在第一次请求该Servlet时才加载。
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");// 指定映射
}
}
启动tomcat,访问url
1.3.7 mvc测试报错问题处理
问题一 java: 找不到符号: 变量 CoroutinesUtils
java: 找不到符号
符号: 变量 CoroutinesUtils
位置: 类 org.springframework.core.ReactiveAdapterRegistry.CoroutinesRegistrar
解决办法:
1.双击执行compileKotlin
执行完成后会生成文件spring-core\kotlin-coroutines\build\libs\kotlin-coroutines-5.2.26.BUILD-SNAPSHOT.jar,将其添加到Spring-core的依赖中。