Spring启动初始化过程

 

1.spring启动过程

1)定时器,监控启动时间

2)获取spring监听器,启动监听器

此处启动的监听器主要是做环境处理的监听器,与后面环境准备中和环境运行中的监听器不同。主要过程是相同的,都是通过发布事件找到事件对应的监听器,之后启动事件监听处理(有一点尚不确定,在发布事件时,spring默认的监听器都是直接调用执行的,定义了一个Executor线程池,但是没设置值,看到里面有设置的方法,应该是需要自定义设置去异步执行监听的监听器)。

3)对启动传入的参数args进行封装,判断环境是哪种模式SERVLET、REACTIVE还是默认模式,然后将其和监听器listeners一起绑定到环境中

4)配置需要忽略的Bean,配置启动时的Banner

5)创建容器

6)实例化SpringBootExceptionResporter,用于打印启动时的日志

7)准备容器

主要做容器环境的准备工作,如是否允许BeanDefine覆盖,是否是懒加载

8)刷新容器

a.prepareRefresh主要完成配置类的解析,验证启动必须参数等

b.prepareBeanFactory准备容器需要用的BeanFactory

c.invokeBeanFactoryPostProcessors实例化BeanFactoryPostProcessor

d.registerBeanPostProcessors实例化所有的BeanPostProcessor

e.initMessageSource国际化,如果无默认的,则使用父类的

f.onRefresh特殊的Bean和子类的初始化,模板方法,不同的容器做不同的处理,如tomcat,jetty等

g.registerListeners注册事件监听器

h.finishBeanFactoryInitialization实例化所有非懒加载的bean,这里包含所有bean的创建过程

j.finishRefresh发布相应的事件

9)刷新容器后的处理

10)定时器停止监听

11)判断是会否要输出启动日志

12)启动监听器开始监听启动事件

13)运行监听器开始监听容器运行事件

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);
			prepareContext(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, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				initMessageSource();

				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				onRefresh();

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

2.读取配置文件过程

该过程是在spring启动过程的第3)步prepareEnvironment(listeners,  applicationArguments)——>listeners.environmentPrepared(environment)准备环境时做的事情(ConfigFileApplicationListener实现了SmartApplicationListener和EnvironmenetPostProcesor,SmartAplicationListener实现了ApplicationListener<ApplicationEvent>,所以准备环境的时候做事件发布和监听器监听会去调用ConfigFileApplicationListener方法)

查找的顺序是file:./config/——>file:./config/*/——>file:./——>classpath:/config/——>classpath:/,其中每个目录下查找文件类型的顺序是properties——>xml——>yml——>yaml

1)初始化环境,包括资源加载器,属性加载器

2)初始化profiles文件,根据配置文件中配置的spring.profiles.active是什么来决定是否重新加载application文件,根据spring.profiles.include来决定要加载哪些个文件

3)遍历profiles文件去加载配置文件,按照上面列出的顺序查找加载。

3.Bean生命周期

1)BeanFactoryPostProcessor构造器,实例化BeanFactoryPostProcessor

2)BeanFactoryPostProcessor的postProcessorBeanFactory方法

3)BeanPostProcessor构造器,实例化BeanPostProcessor

4)InstantiationAwareBeanPostProcessor构造器,实例化InstantiationAwareBeanPostProcessor

5)执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法

6)执行Bean的构造器

7)执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法

8)执行InstantiationAwareBeanPostProcessor的postProcessProperties方法

9)执行InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法

10)调用BeanNameAware的setBeanName方法

11)调用BeanFactoryAware的setBeanFactory方法

12)执行BeanPostProcessor中的postProcessBeforeInitialization方法

13)调用InitializingBean的afterPropertiesSet方法

14)调用InitMethod指定的方法

15)执行BeanPostProcessor的postProcessAfterInitialization方法

16)容器初始化成功

使用完成后开始销毁

17)调用DisposableBean的destroy方法

18)执行destroyMethod指定的方法

4.循环依赖问题解决

构造器中循环依赖会导致程序启动失败,报出异常信息:The dependencies of some of the beans in the application context form a cycle

 

 

 

 

 

参考:

【Spring中Bean的加载与SpringBoot的初始化流程】https://blog.csdn.net/q610376681/article/details/108740943

Spring Bean的生命周期(非常详细)https://www.baidu.com/link?url=TefZDBiF55mIw5Cd76TZGgCP1saXnyjeuASEajpHL3sNkr09AyuKug9esrqua2vV_YE7Oz3yeGimHfBuvxczGa&wd=&eqid=92d9a1600000e0a300000004600833ff

深究Spring中Bean的生命周期https://www.cnblogs.com/javazhiyin/p/10905294.html

曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存https://www.cnblogs.com/grey-wolf/p/13034371.html

 

 

 

 

 

 

 

 

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页