Spring源码: StartupStep、ApplicationStartup 接口

本文最后更新于:2023-06-03 13:37 星期六

Spring源码: StartupStep、ApplicationStartup 接口解析

UML

红色线为内部类关系,带有一方,是另一方的内部类。

StartupStep-ApplicationStartup-Contain-InnerClass

依赖关系

  • public interface StartupStep

    • default interface Tags extends Iterable

    • default interface Tag

  • default class FlightRecorderStartupStep implements StartupStep

  • 内含有:class FlightRecorderStartupEvent extends Event 类的变量 event

    • default static class FlightRecorderTag implements Tag
    • default static class FlightRecorderTags implements Tags
      • private class TagsIterator implements Iterator
  • public interface ApplicationStartup

    • default class DefaultApplicationStartup implements ApplicationStartup
      • default static class DefaultStartupStep implements StartupStep
        • default static class DefaultTags implements StartupStep.Tags
    • public class FlightRecorderApplicationStartup implements ApplicationStartup

两接口、三个实现类,

StartupStep

​ FlightRecorderStartupStep

ApplicationStartup

DefaultApplicationStartup

​ FlightRecorderApplicationStartup

StartupStep接口

步骤记录有关ApplicationStartup期间发生的特定阶段或操作的指标。

StartupStep 的生命周期如下:

  1. 该步骤是通过调用the application startup启动创建和启动的,并被分配了一个唯一的id 。

  2. 然后我们可以在处理过程中使用StartupStep.Tags附加信息

  3. 然后我们需要标记步骤的**end()**

实现可以跟踪“执行时间”或其他步骤指标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public interface StartupStep {

/**
* Return the name of the startup step.
* <p>A step name describes the current action or phase. This technical
* name should be "." namespaced and can be reused to describe other instances of
* similar steps during application startup.
*/
String getName();

/**
* Return the unique id for this step within the application startup.
*/
long getId();

/**
* Return, if available, the id of the parent step.
* <p>The parent step is the step that was started the most recently
* when the current step was created.
*/
@Nullable
Long getParentId();

/**
* Add a {@link Tag} to the step.
* @param key tag key
* @param value tag value
*/
StartupStep tag(String key, String value);

/**
* Add a {@link Tag} to the step.
* @param key tag key
* @param value {@link Supplier} for the tag value
*/
StartupStep tag(String key, Supplier<String> value);

/**
* Return the {@link Tag} collection for this step.
*/
Tags getTags();

/**
* Record the state of the step and possibly other metrics like execution time.
* <p>Once ended, changes on the step state are not allowed.
*/
void end();


# 对 Tag 的迭代。
/**
* Immutable collection of {@link Tag}.
*/
interface Tags extends Iterable<Tag> {
}


# 将 FlightRecorderTag 类的get方法使用接口暴露出来。方便面向接口迭代。
/**
* Simple key/value association for storing step metadata.
*/
interface Tag {

/**
* Return the {@code Tag} name.
*/
String getKey();

/**
* Return the {@code Tag} value.
*/
String getValue();
}

}

将记录通过 FlightRecorderStartupEvent 扩展为事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Enabled(true)
@StackTrace(true)
@Registered(true)
public abstract class Event extends jdk.internal.event.Event {
protected Event() {}

@Override
public final void begin() { }

@Override
public final void end() {}

@Override
public final void commit() {}

@Override
public final boolean isEnabled() { return false; }

@Override
public final boolean shouldCommit() { return false; }

@Override
public final void set(int index, Object value) { }
}


@Category("Spring Application")
@Label("Startup Step")
@Description("Spring Application Startup")
class FlightRecorderStartupEvent extends Event {

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;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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;
}


// 封装 Tag 信息
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);
// 每个数组存放是 FlightRecorderTag 对象。
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");
}
}
}

// 实体类,key-value,数据存储。
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;
}
}
}

ApplicationStartup

使用steps检测应用程序启动阶段。
核心容器及其基础结构组件可以使用ApplicationStartup来标记应用程序启动期间的步骤,并收集有关执行上下文或其处理时间的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public interface ApplicationStartup {

ApplicationStartup DEFAULT = new DefaultApplicationStartup();

StartupStep start(String name);
}


# 实现类,default 作用域 ,仅能通过,ApplicationStartup.DEFAULT 获取。

class DefaultApplicationStartup implements ApplicationStartup {
# DefaultStartupStep 自身内部类
private static final DefaultStartupStep DEFAULT_STARTUP_STEP = new DefaultStartupStep();

@Override
public DefaultStartupStep start(String name) {
return DEFAULT_STARTUP_STEP;
}

static class DefaultStartupStep implements StartupStep {

private final DefaultTags TAGS = new DefaultTags();

@Override
public String getName() {
return "default";
}

@Override
public long getId() {
return 0L;
}

@Override
public Long getParentId() {
return null;
}

@Override
public Tags getTags() {
return this.TAGS;
}

@Override
public StartupStep tag(String key, String value) {
return this;
}

@Override
public StartupStep tag(String key, Supplier<String> value) {
return this;
}

@Override
public void end() {

}

static class DefaultTags implements StartupStep.Tags {
@Override
public Iterator<StartupStep.Tag> iterator() {
return Collections.emptyIterator();
}
}
}

}

// ----------------------------------------------------------------

public class FlightRecorderApplicationStartup implements ApplicationStartup {

private final AtomicLong currentSequenceId = new AtomicLong();

private final Deque<Long> currentSteps;


public FlightRecorderApplicationStartup() {
this.currentSteps = new ConcurrentLinkedDeque<>();
this.currentSteps.offerFirst(this.currentSequenceId.get());
}


@Override
public StartupStep start(String name) {
long sequenceId = this.currentSequenceId.incrementAndGet();
this.currentSteps.offerFirst(sequenceId);
// FlightRecorderStartupStep
return new FlightRecorderStartupStep
(sequenceId, name, this.currentSteps.getFirst(),
committedStep -> this.currentSteps.removeFirstOccurrence(sequenceId));
}

}


使用

ApplicationStartup 对 StartupStep 进一步封装,使用时通过ApplicationStartup 获取 StartupStep 的实例。

1
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
1
2
3
4
5
6
7
public AnnotationConfigApplicationContext() {
//getApplicationStartup()获取的值:ApplicationStartup.DEFAULT
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}

Event 机制

待补充。


Spring源码: StartupStep、ApplicationStartup 接口
https://blog.dekun.wang/blog/2fd1f403.html
作者
Wang Dekun
发布于
2023-06-03 13:37 星期六
更新于
2023-06-03 23:05 星期六
许可协议