阅读spring 源码环境搭建
- 看了一些讲解spring的书,但是感觉还是不够深,所有想自己看看spring的源码,看源码的时候可以写一些代码跑起来,本地调试一下应该会更好理解
- 有一些社区是做了官方文档的中文翻译,质量很高,大概是比一些出版的书籍要更加权威,docs4dev社区-spring-5.1.3中文文档
- 本次选择的spring版本是5.1.3,主要是中文文档也是最高这个版本,方便对的上,源码下载地址
环境要求
gradle
- spring是使用gradle-4.10.2版本构建的,idea会自动安装并引用,如果有问题再手动
- 版本要求可见源码文件:gradle/wrapper/gradle-wrapper.properties
- 下载后先配置环境变量
- 然后在文件 init.d 目录下新增一个文件 init.gradle 这个是下载包的仓库配置
- 配置内容可以复制下面的内容:
allprojects{ repositories { def ALIYUN_REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public' def ALIYUN_JCENTER_URL = 'https://maven.aliyun.com/nexus/content/repositories/jcenter' def GRADLE_LOCAL_RELEASE_URL = 'https://repo.gradle.org/gradle/libs-releases-local' def ALIYUN_SPRING_RELEASE_URL = 'https://maven.aliyun.com/repository/spring-plugin' all { ArtifactRepository repo -> if(repo instanceof MavenArtifactRepository){ def url = repo.url.toString() if (url.startsWith('https://repo1.maven.org/maven2')) { project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL." remove repo } if (url.startsWith('https://jcenter.bintray.com/')) { project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_JCENTER_URL." remove repos } if (url.startsWith('https://repo.spring.io/plugins-release')) { project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_SPRING_RELEASE_URL." remove repo } } } maven { url ALIYUN_REPOSITORY_URL } maven { url ALIYUN_JCENTER_URL } maven { url ALIYUN_SPRING_RELEASE_URL } maven { url GRADLE_LOCAL_RELEASE_URL } } }
JDK
- spring5.1.3 使用了一些语法低版本JDK不支持(9以下都不行),所以JDK直接选择java17,当你使用JDK17的时候,编译时报如下错误的时候,可以选择将JDK切换回8,因为我当时是mac上直接使用java17成功了,windows上使用java8成功,也许java11刚好合适:
java.util.Map java.lang.ProcessEnvironment.theCaseInsensitiveEnvironment accessible: module java.base does not “opens java.lang” to unnamed module @d041cf
- 下载后配置好环境变量
开发工具 IDEA 配置
- 我使用的是2022版本,将spring项目导入,先什么也不做,等它自动加载完,idea提示安装什么东西就允许即可,加载完毕后再进行下面的设置
- 文件->设置->构建 执行 部署->编译器->java编译器>选择编译版本 17
- 文件->设置->构建 执行 部署->构建工具->Gradle 配置好前面下载的gradle程序地址,同时gradle jvm 选择17
- 文件->项目结构->平台设置->SDK 添加自己下载的jdk 17
- 文件->项目设置->项目 设置java 17
- 文件->项目设置->模块 将所有模块设置成 java 17
- 文件->设置->插件->Marketplace 中搜索 Translation 安装这个插件后重启,然后再进入 文件->设置->工具->翻译 在右侧面板最下面,其它->翻译文档勾住,设置上方的翻译引擎,如果没有VPN,可以使用国内的翻译引擎,注册一个开发者id配置上去即可(国内的应该会收费,不推荐),然后看源码的时候,将鼠标放到类(可按Ctrl+Q快捷键)或者方法上就会触发翻译
- 文件->设置->外观与行为->系统设置->HTTP 代理 如果使用的翻译是谷歌翻译,需要在这里设置VPN代理(使用的VPN软件大多数都有开放端口支持http,socket代理等功能)否则谷歌翻译可能会访问不到网络,有些vpn软件也许不需要再idea进行设置因为它有可能就是全局代理,只需要保证网络较好即可。
- 如果是英文版的idea找好对应位置就行
在spring源码工程中创建自己的学习项目包
- 选择项目根包,右击->新建->新模块 选择gradle构建模块包,包名可以叫做 spring-study
- 找到根目录下的 build.gradle 文件,打开后 搜索 -Werror ,然后把它删除掉,这个地方会影响编译,我不删除这个的时候,自己创建的包使用spring注解的时候,无法编译通过,会一直报错误 因为配置了 -Werror
- 打开spring-study 包下的 build.gradle 文件, 在 dependencies 层级下添加如下配置,如果不满足依赖,比如想试试web,则可以多加上implementation(project(“:spring-web”))其它子模块也是一样的添加方式
implementation(project(":spring-core")) implementation(project(":spring-beans")) implementation(project(":spring-context")) compileOnly 'org.projectlombok:lombok:1.18.24' annotationProcessor 'org.projectlombok:lombok:1.18.24' testCompileOnly 'org.projectlombok:lombok:1.18.24' testAnnotationProcessor 'org.projectlombok:lombok:1.18.24' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
开始编写代码启动spring
- 因为我只想启动轻量级spring,不想启动web服务,所以选择AnnotationConfigApplicationContext 来启动
- 启动时的扫包路径以及一些注解,就跟平时使用spring的时候一样,创建一些servic类,带上注解@Service即可
- 这样看spring源码的环境就搭建好了,使用spring框架的时候,都是调用的本地的代码,也方便调试
- main函数如下:
@Configuration @ComponentScan({"org.springframework.main1"}) public class Main1 { public static void main(String[] args) { ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main1.class); UserService us = applicationContext.getBean(UserService.class); System.out.println(us.getUserInfo().toString()); } }
- UserService 类如下:
@Component public class UserService { public UserDo getUserInfo(){ UserDo ud = new UserDo(); ud.setName("谭峻"); ud.setAge(28); return ud; } }
- UserDo 类如下:
@Setter @Getter @ToString public class UserDo { private String name; private int age; }