Spring 下载编译
进入spring-framework官网 点击如图所示github按钮,spring-framework的源码托管在了github上面,直接去github搜索也是可以的

- M1…M2(Milestone):里程碑版本,在版发布之前会出几个里程碑的版本。使用snapshot版本开发了一个时间,觉得最近写代码杠杠的,那么就整几个里程碑版本记录下吧
- RC1…RC2(Release Candidates):发布候选,内部开发到一定阶段了,各个模块集成后,经过细心的测试整个开发团队觉得软件已经稳定没有问题了,可以对外发行了。
- release:正式版本。发布候选差不多之后,那么说明整个框架到了一定的阶段了,可投入市场大面积使用了,那么发布出去,让广大用户来吃吃香吧。
这里我选择5.2.19 release版本

然后使用git clone(需要自己下载git工具) 下来

git clone https://github.com/spring-projects/spring-framework.git

cd 到源码文件夹下面


添加阿里云镜像仓库
找到源码文件夹下面的build.gradle文件(相当于maven的pom),编辑修改镜像仓库配置,加快下载项目依赖的速度
在279行的位置(版本不同可能不一样,也可以使用编辑器搜索功能搜索repositories)
maven {url 'https://maven.aliyun.com/nexus/content/groups/public/'}
maven {url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}

同时,我们在github上面可以看到,官网写的有教程来教我们怎么编译spring源码
Build from Source

点击上方红框进入,我们选择使用IDEA来查看spring源代码
有如下图三个步骤:
(注意:第三步本博客并没有执行,没有出现错误情况,并且这个bug的issue最近一次更新也是在9年之前,估计在新版本中早已经修复了,如果有问题,就unload这个spring-aspects子项目,然后重新build spring framework)

这里写着我们需要预编译spring-oxm,使用gradle脚本文件
gradlew脚本文件会自动帮你下载gradle(放弃,下载太慢了,还是手动下载把)
按照gradlew给我下的这个版本下载(避免出问题),版本信息在gradle/wrapper/gradle-wrapper.properties配置文件中
gradle下载地址

gradle-5.6.4-bin.zip 文件下载到电脑本地以后,更改spring-framework源码中的gradle/wrapper/gradle-wrapper.properties配置文件
file:///为本地文件传输协议(你的gradle文件放在哪里,你就写那个路径)
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
# distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
distributionUrl=file\:///D\:/maintenance/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
然后使用如下命令预编译(使用git终端)spring-oxm
./gradlew :spring-oxm:compileTestJava


你可能会遇到如下错误
ERROR: JAVA_HOME is set to an invalid directory
你可能需要更改一下你的系统环境变量JAVA_HOME,不能带分号,也不能带bin目录

然后系统的path变量里面你可以追加设置这个,让电脑依然可以找到java

IDEA 构建
使用IDEA打开spring framework项目,就会自动构建

图中的爆红
POM relocation to an other version number is not fully supported in Gradle : xml-apis:xml-apis:2.0.2 relocated to xml-apis:xml-apis:1.0.b2.
Please update your dependency to directly use the correct version 'xml-apis:xml-apis:1.0.b2'.
Resolution will only pick dependencies of the relocated element. Artifacts and other metadata will be ignored.
解决方案:
修改引入方式,修改bulid.gradle,搜索configurations.all,添加如下内容:(不过我没管这个爆红,暂时使用没有发现问题)
可见stack overflow这篇Exclude transitive dependency in Gradle [duplicate]
configurations.all {
resolutionStrategy {
force 'xml-apis:xml-apis:1.0.b2'
}
}
测试
新建一个gradle的module

给自己的模块加依赖,里面的很多注解和应用上下ApplicationContext文我们后面都要用到
compile(project(":spring-context"))

编写一个简单的applicationContext获取容器用的bean,用来测试Spring源码构建编译过程是否成功
实体类User
public class User {
private String id;
private String userName;
private String age;
private String work;
private String salary;
private StringBuilder stringBuilder = new StringBuilder();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getWork() {
return work;
}
public void setWork(String work) {
this.work = work;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
@Override
public String toString() {
stringBuilder.append("User :{");
stringBuilder.append("id='" + id);
stringBuilder.append("'\\''");
stringBuilder.append(", userName='" + userName);
stringBuilder.append("'\\''");
stringBuilder.append(", age='" + age);
stringBuilder.append("'\\''");
stringBuilder.append(", work='" + work);
stringBuilder.append("'\\''");
stringBuilder.append(", salary='" + salary);
stringBuilder.append("'\\''");
stringBuilder.append("'}'");
return stringBuilder.toString();
}
}
User配置类,从这里获取User 的bean
package com.xt.spring.config;
import com.xt.spring.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfig {
@Bean
public User user() {
User user = new User();
user.setId("1");
user.setUserName("xt");
user.setAge("24");
return user;
}
}
应用程序启动类
@ComponentScan注解也是在spring-context子项目中,指定扫描包com.xt.spring下的component,在程序中通过AnnotationConfigApplicationContext来获取由Spring自动创建的Bean。对于main函数中使用spring的场景,有两个常见的高级容器。一个是ClassPathXmlApplicationContext,基于classpath下的xml配置文件;另一种是AnnotationConfigApplicationContext,基于java配置文件。
如下是他的类图

package com.xt.spring;
import com.xt.spring.config.UserConfig;
import com.xt.spring.entity.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import java.util.Arrays;
@ComponentScan("com.xt.spring.**")
public class UserApplication {
public static void main(String[] args) {
System.out.println("启动...........");
long startTime = System.currentTimeMillis();
System.out.println("开始时间:" + startTime + "毫秒");
ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);
User user = context.getBean(User.class);
System.out.println("信息:" + user.toString());
System.out.println(context.getBeanDefinitionCount());
Arrays.stream(context.getBeanDefinitionNames()).forEach(System.out::println);
long endTime = System.currentTimeMillis();
System.out.println("结束时间:" + endTime + "毫秒");
System.out.println("耗时:" + (endTime - startTime) + "毫秒");
}
}
如下所示,已经获取并创建了自定义的bean了(可能你会有中文乱码问题,见下面部分内容)

有关IDEA控制台乱码问题
修改 IntelliJ IDEA 全局编码、项目编码、属性文件编码
上方导航栏“File→Settings…”进入配置页面,在“Editor”中下滑找到“File Encodings”,分别将 Global Encoding、Project Encoding、Default encoding for properties files 都设置为 UTF-8。在重启之后运行程序检查控制台信息,如果不管用请执行下面的步骤。

IntelliJ IDEA 中自定义虚拟机选项
上方导航栏“Help→Etit Custom VM Options…”进入自定义虚拟机选项页面。

在 idea64.exe.vmoptions 文件尾加上-Dfile.encoding=UTF-8。在重启之后运行程序检查控制台信息,一般到了这步问题就解决了,当然如果不管用请执行下面的超级步骤。

直接修改 IntelliJ IDEA 配置文件的编码信息
我们打开 IntelliJ IDEA 在本地的安装目录,找到下面两个文件,使用记事本打开,在最后一行添加-Dfile.encoding=UTF-8 即可。在重启之后运行程序检查控制台信息,问题解决!



spring源代码各个模块作用
主要模块:
spring-core:核心模块 依赖注入IOC和DI的最基本实现
spring-beans: Bean工厂与装配
spring-context:上下文,即IOC容器
spring-context-support:对IOC的扩展,以及IOC子容器
spring-context-indexer:类管理组件和Classpath扫描
spring-expression:表达式语句
切面编程:
spring-aop:面向切面编程,CGLIB,JDKProxy
spring-aspects:集成AspectJ,Aop应用框架
spring-instrument:动态Class Loading模块
数据访问与集成:
spring-jdbc:提供JDBC主要实现模块,用于简化JDBC操作
spring-tx: spring-jdbc事务管理
spring-orm:主要集成Hibernate,jpa,jdo等
spring-oxm:将java对象映射成xml数据或将xml映射为java对象
spring-jms:发送和接受消息
web组件:
spring-web:提供了最基础的web支持,主要建立在核心容器上
spring-webmvc:实现了spring mvc的web应用
spring-websocket:主要与前端页的全双工通讯协议
spring-webflux:一个新的非阻塞函数式Reactive Web框架
报文:
spring-messaging: 4.0加入的模块,主要集成基础报文传送应用
测试:
集成兼容:
spring-framework-bom:解决不同模块依赖版本不同问题
References:
(写博客主要是对自己学习的归纳整理,资料大部分来源于书籍、网络资料、官方文档和自己的实践,整理的不足和错误之处,请大家评论区批评指正。同时感谢广大博主和广大作者辛苦整理出来的资源和分享的知识。)