spring启动流程首先从SpringApplication.run(StartWorkApplication.class, args);这一行代码进入。run方法进入首先会创建SpringApplication的对象,调用构造方法。如下:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
//创建类型为ApplicationContextInitializer的对象
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//创建类型为ApplicationListener的对象
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
上面的getSpringFactoriesInstances方法最终会调用loadSpringFactories。
这个方法会读取每一个jar下面的META-INF/spring.factories文件,得到所有的配置类,并返回一个map。接下来获取指定类型的bean创建对象加载到内存。
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = cache.get(classLoader);
if (result != null) {
return result;
}
result = new HashMap<>();
try {
//从META-INF/spring.factories读取配置类
Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION);
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
String[] factoryImplementationNames =
StringUtils.commaDelimitedListToStringArray((String) entry.getValue());
for (String factoryImplementationName : factoryImplementationNames) {
result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>())
.add(factoryImplementationName.trim());
}
}
}
// Replace all lists with unmodifiable lists containing unique elements
result.replaceAll((factoryType, implementations) -> implementations.stream().distinct()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)));
cache.put(classLoader, result);
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
return result;
}
创建完SpringApplication对象后就会调用他的run方法。其中主要的方法是prepareContext和refreshContext。如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
(一)prepareContext方法
prepareContext方法主要做一些预处理的工作,环境信息配置以及预处理一些后置处理器和springApplication启动类。调用链如下:
prepareContext*>>BeanDefinitionLoader#load>>AnnotatedBeanDefinitionReader#register>>GenericApplicationContext#registerBeanDefinition>>*DefaultListableBeanFactory#registerBeanDefinition。可以看到最终调用DefaultListableBeanFactory的registerBeanDefinition方法。这个方法会将项目启动类springApplication的beanDefinition缓存到beanDefinitionMap。
(二)refreshContext方法
refreshContext调用AbstractApplicationContext#refresh方法。里面的主要逻辑如下:
// Allows post-processing of the bean factory in context subclasses.
//beanFactory扩展点
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//1)执行BeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//2)注册BeanPostProcessors
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化消息 。。。暂时忽略
initMessageSource();
// Initialize event multicaster for this context.
//3)初始化multicaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
//4)注册listener
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//5)预先创建非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//6)执行LifecycleProcessor的onRefresh方法以及发布ContextRefreshedEvent事件
finishRefresh();
1)invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors主要是执行BeanFactory的后置处理器。先执行实现了BeanDefinitionRegistryPostProcessor接口的Processor,再执行实现BeanFactoryPostProcessor接口的Processor,实现PriorityOrdered接口的Processor优先于实现Ordered执行。其中ConfigurationClassPostProcessor这个后置处理器实现了BeanDefinitionRegistryPostProcessor和PriorityOrdered接口,会被第一个执行。 ConfigurationClassPostProcessor会处理@ComponentScan,@Import等注解。关于这个类具体的解析逻辑在这篇文章[springboot BeanFactoryPostProcesser之ConfigurationClassPostProcessor]。(https://blog.csdn.net/weixin_38965431/article/details/123595745)
2)registerBeanPostProcessors
registerBeanPostProcessors作用是注册Bean的后置处理器。主要逻辑如下:先注册实现了PriorityOrdered接口的PostProcessor,再注册实现了Ordered接口的BeanPostProcessor,最后再注册剩余的BeanPostProcessor。他的注册逻辑是通过AbstractBeanFactory#doGetBean获取到BeanPostProcessor实例然后缓存到beanPostProcessors集合中。doGetBean创建bean对象的逻辑放到后续篇章。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取BeanPostProcessor类型的beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//根据优先级不同对这些BeanPostProcessor做不同的划分
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//创建bean实例,注入到IOC容器
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
//排序 按照PriorityOrdered值从小到大的顺序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//优先注册实现了PriorityOrdered接口的BeanPostProcessor
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
//再注册实现了Ordered接口的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
}
3)initApplicationEventMulticaster
initApplicationEventMulticaster方法主要是注册了一个事件监听广播器SimpleApplicationEventMulticaster。
4)registerListeners
registerListeners的作用是注册事件监听器
5)finishBeanFactoryInitialization
finishBeanFactoryInitialization的作用是提前创建非懒加载的单例Bean。他调用了DefaultListableBeanFactory#preInstantiateSingletons这个方法,内部通过doGetBean创建Bean注入Ioc容器。具体实现如下:
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//加载所有非懒加载的单例bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//非抽象的非懒加载的单例bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//处理factorybean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
//处理非factorybean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
//如果bean实现了SmartInitializingSingleton,调用afterSingletonsInstantiated进行初始化
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
6)finishRefresh
finishRefresh主要作用是执行LifecycleProcessor的onRefresh方法以及发布ContextRefreshedEvent事件。发布事件监听器的逻辑也放在后续篇章。
总结:spring启动流程其实主要是refreshContext方法里面的1,2,5步。第一步主要是执行BeanFactoryPostProcessors其中就包括解析各种注解类然后生成BeanDefination描述性信息缓存到BeanDefinationMap。第二步是优先创建各种BeanPostProcessor后置处理器,注册到spring容器,然后在后续创建bean时候会执行这些后置处理器。第五步主要是创建非懒加载的单例bean,根据BeanDefinationMap里面的信息,通过doGetBean创建。