上篇回顧
上一篇SpringBootExceptionReporter異常上報(bào)中分析了springboot如何處理啟動(dòng)過(guò)程中的異常
目錄
1. 準(zhǔn)備容器prepareContext()
2. 統(tǒng)一ApplicationContext和Application使用的environment
3. ApplicationContext的后置處理
4. 執(zhí)行Initializers
????4.1 DelegatingApplicationContextInitializer
????4.2 SharedMetadataReaderFactoryContextInitializer
????4.3 ContextIdApplicationContextInitializer
????4.4 ConfigurationWarningsApplicationContextInitializer
????4.5 ServerPortInfoApplicationContextInitializer
????4.6 ConditionEvaluationReportLoggingListener
5. 發(fā)布ApplicationContextInitializedEvent事件
6. 打印啟動(dòng)和profile日志
7. 手工注冊(cè)單例Bean
8. 初始化BeanDefinitionLoader, 加載Application
9. 發(fā)布contextLoaded事件
????9.1 ConfigFileApplicationListener
????9.2 LoggingApplicationListener
????9.3 BackgroundPreinitializer
????9.4 DelegatingApplicationListener
1. 準(zhǔn)備環(huán)境prepareContext()
準(zhǔn)備應(yīng)用上下文環(huán)境AnnotationConfigServletWebServerApplicationContext, 執(zhí)行了以下8個(gè)步驟
- 統(tǒng)一ApplicationContext和Application使用的environment
- 后置處理ApplicationContext
- 執(zhí)行Initializers
- 發(fā)布contextPrepared事件
- 打印啟動(dòng)和profile日志
- 注冊(cè)單例bean
- 加載啟動(dòng)類(lèi)
- 發(fā)布contextLoaded事件
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//本文的重點(diǎn)
//準(zhǔn)備應(yīng)用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//...
}
/**
* 準(zhǔn)備應(yīng)用上下文
* @param context AnnotationConfigServletWebServerApplicationContext實(shí)例
* @param environment SpringApplication中的StandardServletEnvironment實(shí)例
* @param applicationArguments SpringApplication中的DefaultApplicationArguments實(shí)例
* @param printedBanner 默認(rèn)使用SpringApplicationBanner實(shí)例
*/
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//設(shè)置context(上下文)環(huán)境
//統(tǒng)一ApplicationContext和Application,使用Application的environment
context.setEnvironment(environment);
//ApplicationContext的后置處理
postProcessApplicationContext(context);
//執(zhí)行Initializers
applyInitializers(context);
//發(fā)布contextPrepared事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
//配置了info日志
//打印啟動(dòng)和profile日志
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
//獲取到DefaultListableBeanFactory實(shí)例
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//注冊(cè)名為springApplicationArguments,值為applicationArguments的單例bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
//banner不為空,那么注冊(cè)名為springBootBanner,值為printedBanner的單例bean
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
//allowBeanDefinitionOverriding默認(rèn)為false
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 獲取sources列表,獲取到我們的YanggxApplication.class
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//初始化bean加載器,并加載bean到應(yīng)用上下文
load(context, sources.toArray(new Object[0]));
//發(fā)布contextLoaded事件
listeners.contextLoaded(context);
}
}
2. 統(tǒng)一ApplicationContext和Application使用的environment
配置ApplicationContext和Application的environment成員變量, 使用Application的environment, AnnotationConfigServletWebServerApplicationContext的bean定讀取器reader和bean掃描器scanner都使用Application的environment
public class AnnotationConfigServletWebServerApplicationContext
extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
//顯式調(diào)用父類(lèi)AbstractApplicationContext的setEnvironment方法
super.setEnvironment(environment);
//調(diào)用AnnotatedBeanDefinitionReader#setEnvironment()方法
this.reader.setEnvironment(environment);
//ClassPathBeanDefinitionScanner繼承了ClassPathScanningCandidateComponentProvider,所以調(diào)用了父類(lèi)setEnvironment方法
this.scanner.setEnvironment(environment);
}
}
顯式調(diào)用父類(lèi)AbstractApplicationContext的setEnvironment方法
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
//environment成員變量
@Nullable
private ConfigurableEnvironment environment;
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
this.environment = environment;
}
}
調(diào)用AnnotatedBeanDefinitionReader#setEnvironment()方法
public class AnnotatedBeanDefinitionReader {
public void setEnvironment(Environment environment) {
//初始化conditionEvaluator
this.conditionEvaluator = new ConditionEvaluator(this.registry, environment, null);
}
}
調(diào)用ClassPathBeanDefinitionScanner的setEnvironment方法
ClassPathBeanDefinitionScanner繼承了ClassPathScanningCandidateComponentProvider, 所以調(diào)用了父類(lèi)setEnvironment方法
ublic class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
@Nullable
private Environment environment;
public void setEnvironment(Environment environment) {
Assert.notNull(environment, "Environment must not be null");
this.environment = environment;
//conditionEvaluator置為null
this.conditionEvaluator = null;
}
}
3. ApplicationContext的后置處理
執(zhí)行了以下三步
- 設(shè)置ApplicationContext的beanNameGenerator
- 設(shè)置ApplicationContext的resourceLoader和classLoader
- 設(shè)置ApplicationContext的類(lèi)型轉(zhuǎn)換Service
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
//沒(méi)有設(shè)置beanNameGenerator,默認(rèn)為null
if (this.beanNameGenerator != null) {
//如果beanNameGenerator不為空
//那么注冊(cè)一個(gè)名為internalConfigurationBeanNameGenerator
//值為beanNameGenerator的單例bean
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
//沒(méi)有設(shè)置resourceLoader,默認(rèn)為null
if (this.resourceLoader != null) {
//如果resourceLoader不為空
if (context instanceof GenericApplicationContext) {
//context是GenericApplicationContext子類(lèi)
//那么設(shè)置上下文context的resourceLoader
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
//如果當(dāng)前上下文是DefaultResourceLoader的子類(lèi)
//那么設(shè)置上下文context的classLoader
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
//this.addConversionService默認(rèn)為true
if (this.addConversionService) {
//設(shè)置類(lèi)型轉(zhuǎn)換Service
context.getBeanFactory().setConversionService(
ApplicationConversionService.getSharedInstance());
}
}
4. 執(zhí)行Initializers
initializers在SpringApplication初始化期間獲取到, 一共獲取到6個(gè)初始化器:
- DelegatingApplicationContextInitializer
- SharedMetadataReaderFactoryContextInitializer
- ContextIdApplicationContextInitializer
- ConfigurationWarningsApplicationContextInitializer
- ServerPortInfoApplicationContextInitializer
- ConditionEvaluationReportLoggingListener
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
//斷言判斷initializer的類(lèi)型是否符合條件
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
//執(zhí)行各個(gè)initializer的初始化initialize方法
initializer.initialize(context);
}
}
4.1 DelegatingApplicationContextInitializer
獲取環(huán)境中屬性context.initializer.classesInitializer配置的ApplicationContextInitializer列表, 執(zhí)行其initialize()方法, 由于我們沒(méi)有配置屬性context.initializer.classesInitializer, 所以不會(huì)執(zhí)行任何操作
//代理初始化器
public class DelegatingApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
private static final String PROPERTY_NAME = "context.initializer.classes";
@Override
public void initialize(ConfigurableApplicationContext context) {
ConfigurableEnvironment environment = context.getEnvironment();
//獲取environment中配置的context.initializer.classes屬性
//其值為各個(gè)initializer,用逗號(hào)分隔開(kāi)
List<Class<?>> initializerClasses = getInitializerClasses(environment);
if (!initializerClasses.isEmpty()) {
//獲取到各個(gè)initializer,并執(zhí)行其initialize()方法
applyInitializerClasses(context, initializerClasses);
}
}
}
4.2 SharedMetadataReaderFactoryContextInitializer
添加了一個(gè)類(lèi)型為CachingMetadataReaderFactoryPostProcessor的BeanFactoryPostProcessor, CachingMetadataReaderFactoryPostProcessor會(huì)做兩件事情
- 注冊(cè)一個(gè)名稱(chēng)為internalCachingMetadataReaderFactory, 類(lèi)型為SharedMetadataReaderFactoryBean的bean, 用于讀取bean的元數(shù)據(jù)Metadata
- 獲取名稱(chēng)為internalConfigurationAnnotationProcessor, 類(lèi)型為ConfigurationClassPostProcessor的bean定義, 為其添加name為metadataReaderFactory, value為internalCachingMetadataReaderFactory的internalCachingMetadataReaderFactory
class SharedMetadataReaderFactoryContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
public static final String BEAN_NAME = "org.springframework.boot.autoconfigure."
+ "internalCachingMetadataReaderFactory";
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//spring上下文容器添加一個(gè)CachingMetadataReaderFactoryPostProcessor
applicationContext.addBeanFactoryPostProcessor(
new CachingMetadataReaderFactoryPostProcessor());
}
}
4.3 ContextIdApplicationContextInitializer
初始化容器ID, 獲取屬性spring.application.name配置的應(yīng)用名稱(chēng), 如果不存在的話(huà), 默認(rèn)使用application
//容器ID初始化器
public class ContextIdApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//獲取并設(shè)置容器ID
ContextId contextId = getContextId(applicationContext);
applicationContext.setId(contextId.getId());
//容器beanFactory中注冊(cè)一個(gè)名稱(chēng)為ContextId類(lèi)名
//值為contextId的bean
applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(),
contextId);
}
//獲取ContextID
private ContextId getContextId(ConfigurableApplicationContext applicationContext) {
//父容器獲取spring.application.name對(duì)應(yīng)的bean
ApplicationContext parent = applicationContext.getParent();
if (parent != null && parent.containsBean(ContextId.class.getName())) {
return parent.getBean(ContextId.class).createChildId();
}
//父容器獲取不到,則生成一個(gè)contextId
return new ContextId(getApplicationId(applicationContext.getEnvironment()));
}
//獲取應(yīng)用ID
private String getApplicationId(ConfigurableEnvironment environment) {
//獲取屬性:spring.application.name
String name = environment.getProperty("spring.application.name");
//如果為空,默認(rèn)名application
return StringUtils.hasText(name) ? name : "application";
}
//ContextId類(lèi)
class ContextId {
//原子Long類(lèi)
private final AtomicLong children = new AtomicLong(0);
private final String id;
ContextId(String id) {
this.id = id;
}
ContextId createChildId() {
//線(xiàn)程安全遞增
return new ContextId(this.id + "-" + this.children.incrementAndGet());
}
String getId() {
return this.id;
}
}
}
4.4 ConfigurationWarningsApplicationContextInitializer
配置告警初始化器, 用于檢測(cè)注解了包org, org.springframework包內(nèi)的類(lèi), 如果注解了,那么打印warn日志
public class ConfigurationWarningsApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext context) {
//添加一個(gè)beanFactory后置處理器
//ConfigurationWarningsPostProcessor的子類(lèi)
context.addBeanFactoryPostProcessor(
new ConfigurationWarningsPostProcessor(getChecks()));
}
//返回ComponentScanPackageCheck實(shí)例
protected Check[] getChecks() {
return new Check[] { new ComponentScanPackageCheck() };
}
/**
* 配置錯(cuò)誤后置處理器
*/
protected static final class ConfigurationWarningsPostProcessor
implements PriorityOrdered, BeanDefinitionRegistryPostProcessor {
private Check[] checks;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
//處理各個(gè)檢查之后的警告
for (Check check : this.checks) {
//沒(méi)有問(wèn)題的話(huà)message為null
String message = check.getWarning(registry);
if (StringUtils.hasLength(message)) {
//有錯(cuò)誤信息,打印告警信息
warn(message);
}
}
}
private void warn(String message) {
if (logger.isWarnEnabled()) {
//打印告警日志
logger.warn(String.format("%n%n** WARNING ** : %s%n%n", message));
}
}
}
//Component注解掃描Check類(lèi)
protected static class ComponentScanPackageCheck implements Check {
//有問(wèn)題的包
private static final Set<String> PROBLEM_PACKAGES;
static {
//將org和org.springframework包添加到PROBLEM_PACKAGES
//也就是不允許配置這兩個(gè)包內(nèi)的類(lèi)方法和屬性
Set<String> packages = new HashSet<>();
packages.add("org.springframework");
packages.add("org");
PROBLEM_PACKAGES = Collections.unmodifiableSet(packages);
}
@Override
public String getWarning(BeanDefinitionRegistry registry) {
//獲取被掃描的包
Set<String> scannedPackages = getComponentScanningPackages(registry);
//獲取有問(wèn)題的包
List<String> problematicPackages = getProblematicPackages(scannedPackages);
if (problematicPackages.isEmpty()) {
//沒(méi)有問(wèn)題返回null
return null;
}
//有問(wèn)題返回的錯(cuò)誤信息
return "Your ApplicationContext is unlikely to "
+ "start due to a @ComponentScan of "
+ StringUtils.collectionToDelimitedString(problematicPackages, ", ")
+ ".";
}
private boolean isProblematicPackage(String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return true;
}
//如果包名為org或者org.springframework
//那么返回true,否則返回false
return PROBLEM_PACKAGES.contains(scannedPackage);
}
private String getDisplayName(String scannedPackage) {
if (scannedPackage == null || scannedPackage.isEmpty()) {
return "the default package";
}
return "'" + scannedPackage + "'";
}
}
}
4.5 ServerPortInfoApplicationContextInitializer
服務(wù)端口初始化器, 分別實(shí)現(xiàn)了ApplicationContextInitializer和ApplicationListener接口, 在applicationContext中添加了事件監(jiān)聽(tīng)器this, 監(jiān)聽(tīng)了WebServerInitializedEvent事件, 配置服務(wù)的端口號(hào)
public class ServerPortInfoApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext>,
ApplicationListener<WebServerInitializedEvent> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//把this添加到Application的listener中
applicationContext.addApplicationListener(this);
}
//監(jiān)聽(tīng)處理WebServerInitializedEvent事件
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
//獲取environment中配置的server.ports
String propertyName = "local." + getName(event.getApplicationContext()) + ".port";
setPortProperty(event.getApplicationContext(), propertyName,
event.getWebServer().getPort());
}
}
4.6 ConditionEvaluationReportLoggingListener
條件評(píng)估日志監(jiān)聽(tīng)器, 主要作用是給applicationContext添加了一個(gè)ConditionEvaluationReportListener監(jiān)聽(tīng)器, ConditionEvaluationReportListener監(jiān)聽(tīng)了ContextRefreshedEvent和ApplicationFailedEvent事件, 打印相應(yīng)日志
public class ConditionEvaluationReportLoggingListener
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
//applicationContext中添加一個(gè)ConditionEvaluationReportListener
applicationContext
.addApplicationListener(new ConditionEvaluationReportListener());
if (applicationContext instanceof GenericApplicationContext) {
//注冊(cè)一個(gè)ConditionEvaluationReport bean
this.report = ConditionEvaluationReport
.get(this.applicationContext.getBeanFactory());
}
}
//監(jiān)聽(tīng)到ApplicationEvent
protected void onApplicationEvent(ApplicationEvent event) {
ConfigurableApplicationContext initializerApplicationContext = this.applicationContext;
if (event instanceof ContextRefreshedEvent) {
//ContextRefreshed事件
if (((ApplicationContextEvent) event)
.getApplicationContext() == initializerApplicationContext) {
logAutoConfigurationReport();
}
}
else if (event instanceof ApplicationFailedEvent
&& ((ApplicationFailedEvent) event)
.getApplicationContext() == initializerApplicationContext) {
//ApplicationFailedEvent事件
logAutoConfigurationReport(true);
}
}
}
//用于記錄Condition注解的評(píng)估情況
public final class ConditionEvaluationReport {
//bean名稱(chēng)為autoConfigurationReport
//類(lèi)型為ConditionEvaluationReport
private static final String BEAN_NAME = "autoConfigurationReport";
//從beanFactory中獲取ConditionEvaluationReport實(shí)例
public static ConditionEvaluationReport get(
ConfigurableListableBeanFactory beanFactory) {
synchronized (beanFactory) {
ConditionEvaluationReport report;
if (beanFactory.containsSingleton(BEAN_NAME)) {
//如果bean已經(jīng)被注冊(cè),立即返回
report = beanFactory.getBean(BEAN_NAME, ConditionEvaluationReport.class);
}
else {
//否則注冊(cè)bean
report = new ConditionEvaluationReport();
beanFactory.registerSingleton(BEAN_NAME, report);
}
locateParent(beanFactory.getParentBeanFactory(), report);
return report;
}
}
}
5. 發(fā)布ApplicationContextInitializedEvent事件
Application容器初始化完成事件, 對(duì)該事件感興趣的監(jiān)聽(tīng)器有
- BackgroundPreinitializer
- DelegatingApplicationListener
BackgroundPreinitializer
擴(kuò)展點(diǎn), 后臺(tái)進(jìn)程初始化器, 用于多線(xiàn)程執(zhí)行后臺(tái)耗時(shí)任務(wù), 在這里不處理ApplicationContextInitializedEvent事件
DelegatingApplicationListener
擴(kuò)展點(diǎn), 代理監(jiān)聽(tīng)器, 繼續(xù)分發(fā)事件, 不處理ApplicationContextInitializedEvent事件
6. 打印啟動(dòng)和profile日志
//logStartupInfo默認(rèn)為true
if (this.logStartupInfo) {
//打印項(xiàng)目啟動(dòng)信息
// Starting YanggxApplication on pcname with PID 12372 (E:\java\spring\target\classes started by username in E:\java\spring)
logStartupInfo(context.getParent() == null);
//打印profile
//No active profile set, falling back to default profiles: default
logStartupProfileInfo(context);
}
7. 注冊(cè)單例Bean
注冊(cè)了兩個(gè)單例Bean
- 命令行參數(shù)bean, 名稱(chēng)為springApplicationArguments, 值為applicationArgument
- banner bean, 名稱(chēng)為springBootBanner, 值為printedBanner
//注冊(cè)命令行參數(shù)bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
//banner bean
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
7.1 手工注冊(cè)單例Bean流程
調(diào)用DefaultListableBeanFactory#registerSingleton方法, 顯示調(diào)用父類(lèi)DefaultSingletonBeanRegistry#registerSingleton方法
DefaultListableBeanFactory 手工注冊(cè)單例Bean
手工注冊(cè)單例Bean, 不同于掃描bean定義, 然后注冊(cè)單例bean, 手工注冊(cè)的單例Bean, 沒(méi)有維護(hù)到beanDefinitionMap中, 而是將beanName維護(hù)到manualSingletonNames中
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
//注冊(cè)單例bean
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
//判斷bean的創(chuàng)建過(guò)程是否已經(jīng)開(kāi)始了
//調(diào)用抽象父類(lèi)AbstractBeanFactory#hasBeanCreationStarted()方法
//判斷AbstractBeanFactory成員變量alreadyCreated Set不為空
if (hasBeanCreationStarted()) {
//bean創(chuàng)建過(guò)程已經(jīng)開(kāi)始了
//鎖住成員變量beanDefinitionMap
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
//如果bean定義Map, beanDefinitionMap已經(jīng)包含了bean
//維護(hù)到手工單例bean名稱(chēng)manualSingletonNames中
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// bean還沒(méi)有注冊(cè)過(guò), 仍處于啟動(dòng)注冊(cè)階段
if (!this.beanDefinitionMap.containsKey(beanName)) {
//如果beanDefinitionMap不包含beanName
//那么添加到manualSingletonNames
this.manualSingletonNames.add(beanName);
}
}
//清空allBeanNamesByType和singletonBeanNamesByType
clearByTypeCache();
}
}
DefaultSingletonBeanRegistry手工注冊(cè)單例Bean
將beanName添加到registeredSingletons中, beanName和對(duì)應(yīng)的對(duì)象保存singletonObjects中, 并刪除beanName對(duì)應(yīng)的beanFactory, earlySingleton
//默認(rèn)單例bean注冊(cè)器
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//緩存單例bean, key為bean名稱(chēng),value為bean實(shí)例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//緩存beanFactory, key為bean名稱(chēng), value為beanFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//早期單例緩存, key為bean名稱(chēng), value為bean實(shí)例
//為了解決循環(huán)依賴(lài)而引入的
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//單例bean名稱(chēng)set
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
//正在創(chuàng)建的單例bean名稱(chēng)set
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//手工注冊(cè)單例bean
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
//判斷名稱(chēng)和值不可以為空
Assert.notNull(beanName, "Bean name must not be null");
Assert.notNull(singletonObject, "Singleton object must not be null");
synchronized (this.singletonObjects) {
//判斷bean是否為空
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
//不為空拋異常
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
//添加一個(gè)單例bean
addSingleton(beanName, singletonObject);
}
}
//添加一個(gè)單例bean
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//保存到singletonObjects的map中
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
//添加beanName
this.registeredSingletons.add(beanName);
}
}
}
8. 初始化BeanDefinitionLoader, 加載Application
首先生成一個(gè)BeanDefinitionLoader, 用于加載SpringApplication的成員變量sources, 當(dāng)前sources列表中只有YanggxApplication.class一個(gè)對(duì)象
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//實(shí)例化BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
//this.beanNameGenerator為null
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
//this.resourceLoader為null
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
//this.environment為null
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//調(diào)用load()方法,加載各個(gè)sources
loader.load();
}
8.1 BeanDefinitionLoader
加載SpringApplication維護(hù)的sources列表資源, 可以加載類(lèi), XML, groovy等資源, 由于我們傳入的sources中只有一個(gè)YanggxApplication.class, 所以調(diào)用的是load(Class<?> source)方法, 最后調(diào)用的是AnnotatedBeanDefinitionReader#register()方法, 注冊(cè)了一個(gè)Bean定義
class BeanDefinitionLoader {
//啟動(dòng)類(lèi)列表
private final Object[] sources;
//注解Bean定義讀取器
private final AnnotatedBeanDefinitionReader annotatedReader;
//XML Bean定義讀取器
private final XmlBeanDefinitionReader xmlReader;
//groovy Bean定義讀取器
private BeanDefinitionReader groovyReader;
//Bean定義掃描器
private final ClassPathBeanDefinitionScanner scanner;
//資源加載器
private ResourceLoader resourceLoader;
/**
* 構(gòu)造函數(shù)
*/
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
//傳入的sources, 目前只有YanggxApplication.class
this.sources = sources;
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
//使用了groovy
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
this.scanner = new ClassPathBeanDefinitionScanner(registry);
//排除sources掃描
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
/**
* 加載sources
*/
public int load() {
int count = 0;
for (Object source : this.sources) {
count += load(source);
}
return count;
}
//加載Object資源
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
if (source instanceof Class<?>) {
//加載類(lèi)資源
return load((Class<?>) source);
}
if (source instanceof Resource) {
//加載Resource資源
return load((Resource) source);
}
if (source instanceof Package) {
//加載Package資源
return load((Package) source);
}
if (source instanceof CharSequence) {
//加載字符串資源
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
//加載類(lèi)資源
private int load(Class<?> source) {
if (isGroovyPresent()
&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// 使用了groovy,加載groovy資源
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
//如果是@Component注解
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
return 0;
}
//加載groovy資源
private int load(GroovyBeanDefinitionSource source) {
int before = this.xmlReader.getRegistry().getBeanDefinitionCount();
((GroovyBeanDefinitionReader) this.groovyReader).beans(source.getBeans());
int after = this.xmlReader.getRegistry().getBeanDefinitionCount();
return after - before;
}
//加載resource資源
private int load(Resource source) {
if (source.getFilename().endsWith(".groovy")) {
//使用了groovy
if (this.groovyReader == null) {
throw new BeanDefinitionStoreException(
"Cannot load Groovy beans without Groovy on classpath");
}
return this.groovyReader.loadBeanDefinitions(source);
}
//加載xml資源
return this.xmlReader.loadBeanDefinitions(source);
}
//加載package資源
private int load(Package source) {
//scanner掃描
return this.scanner.scan(source.getName());
}
//load xml資源
private int load(CharSequence source) {
String resolvedSource = this.xmlReader.getEnvironment()
.resolvePlaceholders(source.toString());
try {
//先嘗試加載類(lèi)資源
return load(ClassUtils.forName(resolvedSource, null));
}
catch (IllegalArgumentException | ClassNotFoundException ex) {
}
// 不成功的話(huà),加載resource資源
Resource[] resources = findResources(resolvedSource);
int loadCount = 0;
boolean atLeastOneResourceExists = false;
for (Resource resource : resources) {
if (isLoadCandidate(resource)) {
atLeastOneResourceExists = true;
loadCount += load(resource);
}
}
if (atLeastOneResourceExists) {
return loadCount;
}
// 不成功的話(huà),加載package資源
Package packageResource = findPackage(resolvedSource);
if (packageResource != null) {
return load(packageResource);
}
//還不成功的話(huà),就拋異常
throw new IllegalArgumentException("Invalid source '" + resolvedSource + "'");
}
}
AnnotatedBeanDefinitionReader注冊(cè)Bean定義
public class AnnotatedBeanDefinitionReader {
//Class列表注冊(cè)Bean定義
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
//單個(gè)Bean注冊(cè)
registerBean(annotatedClass);
}
}
//單個(gè)Class注冊(cè)bean
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
//注冊(cè)Bean定義
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//生成注解BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//判斷是否符合@Conditional注解的條件
//不滿(mǎn)足的話(huà), 就不注冊(cè)Bean
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//設(shè)置instanceSupplier, //AbstractAutowireCapableBeanFactory#createBeanInstance中調(diào)用了instanceSupplier.get()生成bean實(shí)例
abd.setInstanceSupplier(instanceSupplier);
//Scope元空間
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//生成Bean名稱(chēng)
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//處理Lazy, Primary, DependsOn, Role, Description注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
//beanDefinition定制器
customizer.customize(abd);
}
//bean定義容器
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//Scope代理模式處理
//ScopedProxyMode.DEFAULT和NO不需要代理處理
//INTERFACES使用JDK動(dòng)態(tài)代理
//TARGET_CLASS使用CGLIB動(dòng)態(tài)代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注冊(cè)Bean定義
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
9. 發(fā)布contextLoaded事件
調(diào)用listeners.contextLoaded(context), 發(fā)布了一個(gè)ApplicationPreparedEvent事件, 對(duì)ApplicationPreparedEvent事件感興趣的監(jiān)聽(tīng)器有:
- ConfigFileApplicationListener
- LoggingApplicationListener
- BackgroundPreinitializer
- DelegatingApplicationListener
9.1 ConfigFileApplicationListener
配置文件監(jiān)聽(tīng)器
public class ConfigFileApplicationListener
implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
//事件處理
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
//處理ApplicationPreparedEvent
onApplicationPreparedEvent(event);
}
}
//處理ApplicationPreparedEvent
private void onApplicationPreparedEvent(ApplicationEvent event) {
this.logger.switchTo(ConfigFileApplicationListener.class);
addPostProcessors(((ApplicationPreparedEvent) event).getApplicationContext());
}
//applicationContext中添加一個(gè)PropertySourceOrderingPostProcessor
protected void addPostProcessors(ConfigurableApplicationContext context) {
//用于重排序PropertySourceOrderingPostProcessor
context.addBeanFactoryPostProcessor(
new PropertySourceOrderingPostProcessor(context));
}
}
9.2 LoggingApplicationListener
日志監(jiān)聽(tīng)器
public class LoggingApplicationListener implements GenericApplicationListener {
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
ConfigurableListableBeanFactory beanFactory = event.getApplicationContext()
.getBeanFactory();
//注冊(cè)日志單例bean
if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
}
}
}
9.3 BackgroundPreinitializer
后臺(tái)預(yù)初始化器, 當(dāng)前不做任務(wù)處理, 方便以后擴(kuò)展
9.4 DelegatingApplicationListener
代理監(jiān)聽(tīng)器, 不做任何處理, 方便以后擴(kuò)展
總結(jié)
這一步的主要作用是為下面刷新applicationContext做準(zhǔn)備
- 統(tǒng)一了ApplicationContext和Application的environment
- 設(shè)置ApplicationContext的beanNameGenerator,resouceLoader和classLoader, 并設(shè)置beanFactory的類(lèi)型轉(zhuǎn)換Service
- 執(zhí)行Initializer
- 發(fā)布ApplicationContextInitializedEvent
- 打印啟動(dòng)日志和profile日志
- 手工注冊(cè)命令行和banner兩個(gè)單例Bean
- 初始化BeanDefinitionLoader, 加載啟動(dòng)類(lèi)sources
- 發(fā)布contextLoaded事件
下一篇
我們將會(huì)在下一篇refreshContext()刷新應(yīng)用上下文, 研究springboot如何掃描加載bean, 如何建立webserver容器