Skip to content

Commit cfac1ad

Browse files
committed
add spring refresh source code analysis introduction in readme file
1 parent c4ed057 commit cfac1ad

File tree

3 files changed

+284
-1
lines changed

3 files changed

+284
-1
lines changed
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
2+
3+
### 框架Refresh方法解析一
4+
5+
6+
7+
#### 1.Refresh方法简介
8+
9+
- Bean配置读取加载入口
10+
- Spring框架的启动流程
11+
12+
13+
14+
#### 2.Refresh方法的执行步骤
15+
16+
<img src="https://tva1.sinaimg.cn/large/008i3skNly1gvib55enehj61eg0u041602.jpg" alt="image-20211017144834689" align="left" width="800" />
17+
18+
```java
19+
@Override
20+
public void refresh() throws BeansException, IllegalStateException {
21+
synchronized (this.startupShutdownMonitor) {
22+
// Prepare this context for refreshing.
23+
// 准备此上下文
24+
prepareRefresh();
25+
26+
// Tell the subclass to refresh the internal bean factory.
27+
// 获取BeanFacotry
28+
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
29+
30+
// Prepare the bean factory for use in this context.
31+
// 准备此类上下文中使用的Bean工厂
32+
prepareBeanFactory(beanFactory);
33+
34+
try {
35+
// Allows post-processing of the bean factory in context subclasses.
36+
// 允许在上下文子类中对Bean工厂进行后处理
37+
postProcessBeanFactory(beanFactory);
38+
39+
// Invoke factory processors registered as beans in the context.
40+
// 调用在上下文中注册为Bean的工厂处理器
41+
invokeBeanFactoryPostProcessors(beanFactory);
42+
43+
// Register bean processors that intercept bean creation.
44+
// 注册拦截Bean创建的Bean处理器
45+
registerBeanPostProcessors(beanFactory);
46+
47+
// Initialize message source for this context.
48+
// 为此上下文初始化消息源
49+
initMessageSource();
50+
51+
// Initialize event multicaster for this context.
52+
// 为此上下文初始化事件广播器
53+
initApplicationEventMulticaster();
54+
55+
// Initialize other special beans in specific context subclasses.
56+
// 初始化特定上下文子类中的其他特殊Bean
57+
onRefresh();
58+
59+
// Check for listener beans and register them.
60+
// 检查监听器,并注册
61+
registerListeners();
62+
63+
// Instantiate all remaining (non-lazy-init) singletons.
64+
// 实例化所有剩余的(非延迟初始化)单例。
65+
finishBeanFactoryInitialization(beanFactory);
66+
67+
// Last step: publish corresponding event.
68+
// 最后一步:发布相应的事件
69+
finishRefresh();
70+
}
71+
72+
catch (BeansException ex) {
73+
if (logger.isWarnEnabled()) {
74+
logger.warn("Exception encountered during context initialization - " +
75+
"cancelling refresh attempt: " + ex);
76+
}
77+
78+
// Destroy already created singletons to avoid dangling resources.
79+
// 销毁已经创建的单例以避免浪费资源
80+
destroyBeans();
81+
82+
// Reset 'active' flag.
83+
// 重置active标志
84+
cancelRefresh(ex);
85+
86+
// Propagate exception to caller.
87+
throw ex;
88+
}
89+
90+
finally {
91+
// Reset common introspection caches in Spring's core, since we
92+
// might not ever need metadata for singleton beans anymore...
93+
// 重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据...
94+
resetCommonCaches();
95+
}
96+
}
97+
}
98+
```
99+
100+
101+
102+
#### 3.准备上下文:prepareRefersh#方法
103+
104+
- prepareRefersh#方法简介
105+
- 清除本地元数据缓存
106+
- 准备框架上下文
107+
- 设置框架启动时间
108+
- 设置框架 active 启动状态为true
109+
- 如果是Debug模式打印Debug日志
110+
- 初始化环境配置
111+
- 获取当前环境配置
112+
- 如果是Web环境,配置ServletContext 和 ServletConfig
113+
- 检查环境配置中的必备属性是否存在
114+
- 如果没有早期的事件监听器,就注册应用监听器:applicationListeners
115+
116+
-  prepareRefresh#方法
117+
118+
```java
119+
@Override
120+
protected void prepareRefresh() {
121+
// 清除元数据缓存
122+
this.scanner.clearCache();
123+
// 准备上下文
124+
super.prepareRefresh();
125+
}
126+
```
127+
128+
- clearCache#方法
129+
130+
```java
131+
/**
132+
* Clear the local metadata cache, if any, removing all cached class metadata.
133+
* 清除本地元数据缓存(如果有),删除所有缓存的类元数据。
134+
*/
135+
public void clearCache() {
136+
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
137+
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
138+
// for a shared cache since it'll be cleared by the ApplicationContext.
139+
// 清除外部提供的 MetadataReaderFactory 中的缓存;这是一个无操作用于共享缓存,因为它将被 ApplicationContext 清除。
140+
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
141+
}
142+
}
143+
```
144+
145+
- super.prepareRefresh方法
146+
147+
```java
148+
/**
149+
* Prepare this context for refreshing, setting its startup date and
150+
* active flag as well as performing any initialization of property sources.
151+
* 准备此上下文以进行刷新、设置其启动日期和* active 标志以及执行属性源的任何初始化
152+
*/
153+
protected void prepareRefresh() {
154+
// Switch to active.
155+
// 设置启动时间
156+
this.startupDate = System.currentTimeMillis();
157+
this.closed.set(false);
158+
// 设置 active 标志状态为 true
159+
this.active.set(true);
160+
161+
// 如果当前日志状态是Debug模式的话,会打印一段话
162+
if (logger.isDebugEnabled()) {
163+
if (logger.isTraceEnabled()) {
164+
logger.trace("Refreshing " + this);
165+
}
166+
else {
167+
logger.debug("Refreshing " + getDisplayName());
168+
}
169+
}
170+
171+
// Initialize any placeholder property sources in the context environment.
172+
// 初始化环境配置
173+
initPropertySources();
174+
175+
// Validate that all properties marked as required are resolvable:
176+
// see ConfigurablePropertyResolver#setRequiredProperties
177+
// 检查环境属性中必备的环境数据,如果没有就 throw MissingRequiredPropertiesException 异常
178+
getEnvironment().validateRequiredProperties();
179+
180+
// Store pre-refresh ApplicationListeners...
181+
// 将系统的事件监听器进行注册
182+
if (this.earlyApplicationListeners == null) {
183+
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
184+
}
185+
else {
186+
// Reset local application listeners to pre-refresh state.
187+
this.applicationListeners.clear();
188+
this.applicationListeners.addAll(this.earlyApplicationListeners);
189+
}
190+
191+
// Allow for the collection of early ApplicationEvents,
192+
// to be published once the multicaster is available...
193+
this.earlyApplicationEvents = new LinkedHashSet<>();
194+
}
195+
196+
```
197+
198+
- initPropertySources#方法
199+
200+
```java
201+
protected void initPropertySources() {
202+
// 获取环境配置上下文
203+
ConfigurableEnvironment env = this.getEnvironment();
204+
// 如果当前环境是Web环境,将servletContext 和 ServletConfig 加载到环境配置上下文中
205+
if (env instanceof ConfigurableWebEnvironment) {
206+
((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null);
207+
}
208+
}
209+
```
210+
211+
212+
213+
214+
215+
#### 获取新的Bean工厂:obtainFreshBeanFacotry#方法
216+
217+
- obtainFreshBeanFacotry#方法简介
218+
- 设置当前上下文刷新状态为true
219+
- 这是BeanFactory序列化ID(默认是application)
220+
- 返回BeanFacotry
221+
222+
- obtainFreshBeanFactory#方法
223+
224+
```java
225+
/**
226+
* Tell the subclass to refresh the internal bean factory.
227+
* 告诉子类刷新内部 bean 工厂
228+
* @return the fresh BeanFactory instance
229+
* @see #refreshBeanFactory()
230+
* @see #getBeanFactory()
231+
*/
232+
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
233+
// 设置上下文刷新状态和Beanfacotory的序列化ID
234+
refreshBeanFactory();
235+
// 获取BeanFactory(默认是DefaultListableBeanFacotry)
236+
return getBeanFactory();
237+
}
238+
239+
```
240+
241+
- refreshBeanFacoty#方法
242+
243+
```java
244+
/**
245+
* Do nothing: We hold a single internal BeanFactory and rely on callers
246+
* to register beans through our public methods (or the BeanFactory's).
247+
* @see #registerBeanDefinition
248+
*/
249+
@Override
250+
protected final void refreshBeanFactory() throws IllegalStateException {
251+
// 设置当前上下文刷新状态:true
252+
if (!this.refreshed.compareAndSet(false, true)) {
253+
throw new IllegalStateException(
254+
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
255+
}
256+
// 设置BeanFacotry序列化ID:默认是application
257+
this.beanFactory.setSerializationId(getId());
258+
}
259+
```
260+
261+
- getBeanFacotory#方法
262+
263+
```java
264+
/**
265+
* Return the single internal BeanFactory held by this context
266+
* (as ConfigurableListableBeanFactory).
267+
*/
268+
@Override
269+
public final ConfigurableListableBeanFactory getBeanFactory() {
270+
// 返回默认的 DefaultListableBeanFacotry
271+
return this.beanFactory;
272+
}
273+
```
274+
275+
276+

springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/initializer/FirstInitializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public void initialize(ConfigurableApplicationContext configurableApplicationCon
3030
ConfigurableEnvironment environment =
3131
configurableApplicationContext.getEnvironment();
3232

33+
// 设置必填属性
34+
environment.setRequiredProperties("app.enviroment");
35+
3336
// 设置自定义属性
3437
Map<String, Object> attributeMap = new HashMap<>();
3538
attributeMap.put("firstKey", "firstValue");

springboot-source-code-analysis/src/main/resources/application.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ context.initializer.classes=\
55
# 通过系统事件监听器,监听事件
66
context.listener.classes=\
77
com.example.springboot.source.code.analysis.listener.ThirdListener,\
8-
com.example.springboot.source.code.analysis.listener.FourthListener
8+
com.example.springboot.source.code.analysis.listener.FourthListener
9+
10+
11+
# 通过ConfigurableEnviroment.requiredProperty()方法设置的必填属性
12+
app.enviroment=ipman

0 commit comments

Comments
 (0)