文章目录
1. 确定最新源码版本,源码地址
最新版本 5.3.21
源码github地址
2. 源码编译
2.1 github 源码编译指南
克隆代码
git clone git@github.com:spring-projects/spring-framework.git
cd spring-framework
编译
./gradlew build
提示:以下操作与github源码编译步骤略有不同
2.2 源码下载(建议大家fork到自己仓库、在自己仓库进行克隆)
git clone git@github.com:spring-projects/spring-framework.git
2.3 指定tag v5.3.21 分支切换
cd spring-framework
git checkout -b v5.3.21 origin/v5.3.21
2.4 gradle文件远程仓库修改
2.4.1 修改build.gradle,添加gradle依赖下载远程仓库
repositories {
maven {
url 'https://maven.aliyun.com/repository/public/'
}
maven {
url 'https://maven.aliyun.com/repository/spring/'
}
mavenLocal()
mavenCentral()
gradlePluginPortal()
maven { url "https://repo.spring.io/release" }
}
2.4.2 修改setting.gradle,添加gradle插件下载远程仓库
pluginManagement {
repositories {
maven {
url 'https://maven.aliyun.com/repository/public/'
}
maven {
url 'https://maven.aliyun.com/repository/spring/'
}
mavenLocal()
mavenCentral()
gradlePluginPortal()
maven { url "https://repo.spring.io/release" }
}
}
2.5 项目构建
2.5.1 跳过测试进行编译(减少等待时间)
./gradlew build -x test
2.5.2 构建结果
添加了远程仓库地址后、构建速度明显快了很多
2.5.3 构建过程中,出现ge.spring.io身份验证错误
注释setting.gradle配置文件认证插件
plugins {
id "com.gradle.enterprise" version "3.9"
// id "io.spring.ge.conventions" version "0.0.9"
}
2.5.4 再次执行构建命令、构建成功
3. idea 打开项目
3.1 项目构建
3.1.1 idea gradle配置
3.1.2 等待idea加载、执行gradle插件任务、导入项目
3.1.3 项目导入成功
3.2 新建测试模块进行测试
3.2.1 新建module
file —> New —> Module
3.2.2 修改新建模块对应build.gradle,引入spring-context依赖
dependencies {
implementation(project(":spring-context"))
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
关于引入依赖模块的补充:
有些文章引入的依赖模块是这样的
dependencies {
implementation(project(":spring-context"))
implementation(project(":spring-beans"))
implementation(project(":spring-core"))
implementation(project(":spring-aop"))
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
打开spring-context模块的spring-context.gradle文件
根据依赖传递的特性、在spring-context模块中已经引入了其余三个模块的依赖、不需要重复引入
如果将依赖作用范围api替换成implementation,则需要在新建模块中进行额外三个依赖的引入、感兴趣的小伙伴可以进行测试
有关gradle依赖api、implementation的区别、官方文档解释
3.2.3 测试类进行测试
public class AppConfig {
public void test(){
System.out.println("hello World!");
}
}
public class IocTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig appConfig = applicationContext.getBean("appConfig", AppConfig.class);
appConfig.test();
}
}
3.2.4 程序执行异常(jdk.jfr不存在)
程序包jdk.jfr不存在 这个是jdk11添加的新特性, 用于监控应用的运行情况。我们使用的是jdk8版本、解决方案:
- 切换jdk版本到jdk11
- 注释掉相关类的代码(我使用的这种)
/*
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.metrics.jfr;
//import jdk.jfr.Category;
//import jdk.jfr.Description;
//import jdk.jfr.Event;
//import jdk.jfr.Label;
//import com.sun.org.glassfish.gmbal.Description;
/**
* {@link Event} extension for recording {@link FlightRecorderStartupStep}
* in Java Flight Recorder.
*
* <p>{@link org.springframework.core.metrics.StartupStep.Tags} are serialized
* as a single {@code String}, since Flight Recorder events do not support complex types.
*
* @author Brian Clozel
* @since 5.3
*/
//@Category("Spring Application")
//@Label("Startup Step")
//@Description("Spring Application Startup")
//class FlightRecorderStartupEvent extends Event {
class FlightRecorderStartupEvent {
public final long eventId;
public final long parentId;
// @Label("Name")
public final String name;
// @Label("Tags")
String tags = "";
public FlightRecorderStartupEvent(long eventId, String name, long parentId) {
this.name = name;
this.eventId = eventId;
this.parentId = parentId;
}
public void setTags(String tags) {
this.tags = tags;
}
}
/*
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.core.metrics.jfr;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.springframework.core.metrics.StartupStep;
import org.springframework.lang.NonNull;
/**
* {@link StartupStep} implementation for the Java Flight Recorder.
* <p>This variant delegates to a {@link FlightRecorderStartupEvent JFR event extension}
* to collect and record data in Java Flight Recorder.
*
* @author Brian Clozel
*/
class FlightRecorderStartupStep implements StartupStep {
private final FlightRecorderStartupEvent event;
private final FlightRecorderTags tags = new FlightRecorderTags();
private final Consumer<FlightRecorderStartupStep> recordingCallback;
public FlightRecorderStartupStep(long id, String name, long parentId,
Consumer<FlightRecorderStartupStep> recordingCallback) {
this.event = new FlightRecorderStartupEvent(id, name, parentId);
// this.event.begin();
this.recordingCallback = recordingCallback;
}
@Override
public String getName() {
return this.event.name;
}
@Override
public long getId() {
return this.event.eventId;
}
@Override
public Long getParentId() {
return this.event.parentId;
}
@Override
public StartupStep tag(String key, String value) {
this.tags.add(key, value);
return this;
}
@Override
public StartupStep tag(String key, Supplier<String> value) {
this.tags.add(key, value.get());
return this;
}
@Override
public Tags getTags() {
return this.tags;
}
@Override
public void end() {
// this.event.end();
// if (this.event.shouldCommit()) {
// StringBuilder builder = new StringBuilder();
// this.tags.forEach(tag ->
// builder.append(tag.getKey()).append('=').append(tag.getValue()).append(',')
// );
// this.event.setTags(builder.toString());
// }
// this.event.commit();
this.recordingCallback.accept(this);
}
protected FlightRecorderStartupEvent getEvent() {
return this.event;
}
static class FlightRecorderTags implements Tags {
private Tag[] tags = new Tag[0];
public void add(String key, String value) {
Tag[] newTags = new Tag[this.tags.length + 1];
System.arraycopy(this.tags, 0, newTags, 0, this.tags.length);
newTags[newTags.length - 1] = new FlightRecorderTag(key, value);
this.tags = newTags;
}
public void add(String key, Supplier<String> value) {
add(key, value.get());
}
@NonNull
@Override
public Iterator<Tag> iterator() {
return new TagsIterator();
}
private class TagsIterator implements Iterator<Tag> {
private int idx = 0;
@Override
public boolean hasNext() {
return this.idx < tags.length;
}
@Override
public Tag next() {
return tags[this.idx++];
}
@Override
public void remove() {
throw new UnsupportedOperationException("tags are append only");
}
}
}
static class FlightRecorderTag implements Tag {
private final String key;
private final String value;
public FlightRecorderTag(String key, String value) {
this.key = key;
this.value = value;
}
@Override
public String getKey() {
return this.key;
}
@Override
public String getValue() {
return this.value;
}
}
}
3.2.5 再次运行、spring-context模块下面InstrumentationSavingAgent类找不到
修改spring-context模块下spring-context.gradle文件
找到以下内容
optional(project(":spring-instrument"))
替换成
implementation(project(":spring-instrument"))
最后刷新gralde依赖
3.2.5 执行程序测试、可以正常执行
3.2.6 进行aop测试,如果引入@Aspect注解找不到,修改spring-aop模块下spring-aop.gradle文件
找到以下内容
optional("org.aspectj:aspectjweaver")
替换成
api("org.aspectj:aspectjweaver")
最后刷新gralde依赖