Springboot內建ApplicationContextInitializer--ContextIdApplicationContextInitializer
阿新 • • 發佈:2018-12-03
原始碼分析
本文程式碼基於 Springboot 2.1.0
package org.springframework.boot.context;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;
/**
* ApplicationContextInitializer that sets the Spring
* ApplicationContext ID. The "spring.application.name" property is used to create the ID.
* If the property is not set, "application" is used.
* 設定Spring應用上下文ID,也就是通過ApplicationContext#getId()去獲取的那個屬性,如果屬性
* "spring.application.name"有設定,則使用它作為應用上下文id,否則使用字串"application"。
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class ContextIdApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private int order = Ordered.LOWEST_PRECEDENCE - 10;
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// 構建針對當前應用上下文的ContextId物件:可能基於雙親應用上下文建立或者直接建立
ContextId contextId = getContextId(applicationContext);
// 設定當前應用上下文的id
applicationContext.setId(contextId.getId());
// 將上面生成的ContextId物件,作為一個單例bean註冊到當前應用上下文,
// 從下面的程式碼可以看到,這樣做的用途之一就是萬一當前應用上下文有子應用上下文,
// 該bean可以用於建立子應用上下文的ContextId物件
applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(),
contextId);
}
// 構建針對當前應用上下文的ContextId物件
private ContextId getContextId(ConfigurableApplicationContext applicationContext) {
ApplicationContext parent = applicationContext.getParent();
if (parent != null && parent.containsBean(ContextId.class.getName())) {
// 如果當前應用上下文有雙親上下文,並且雙親上下文已經存在自己的ContextId bean,
// 現在使用雙親上下文的ContextId bean生成當前應用上下文的ContextId物件
return parent.getBean(ContextId.class).createChildId();
}
// 如果當前應用上下文沒有雙親應用上下文或者雙親應用上下文沒有自己的ContextId bean,
// 則直接建立當前應用上下文的ContextId物件
return new ContextId(getApplicationId(applicationContext.getEnvironment()));
}
// 決定應用上下文id的名稱:或者使用環境屬性"spring.application.name"指定的值,或者使用
// 預設值"application"
private String getApplicationId(ConfigurableEnvironment environment) {
String name = environment.getProperty("spring.application.name");
return StringUtils.hasText(name) ? name : "application";
}
/**
* The ID of a context.
*/
class ContextId {
private final AtomicLong children = new AtomicLong(0);
private final String id;
ContextId(String id) {
this.id = id;
}
ContextId createChildId() {
return new ContextId(this.id + "-" + this.children.incrementAndGet());
}
String getId() {
return this.id;
}
}
}