学习spring这个框架,我们总是有种感觉,会用但是不懂,“会用”是因为spring的框架利用约定大于配置的原则帮我们封装好了所有的启动配置类,这样我们使用起来的入门门槛就比较低了,只要照着官方的文档配置,一般都不会有问题,“不懂”是因为我们不知道他的底层到底是怎么实现的,有种雾里看花的感觉,一旦我们想拓展下spring的框架,就无从下手了, spring作为一个优秀的开源框架,我们很有必要去探究下他的底层实现,同时作为一名程序员,知其然也要知其所以然,要有求知欲望,这样才能站得高看的远,废话不多说,今天我们就来详细剖析下spring的启动过程(文中可能有错误的地方,希望各位看官能及时指出,非常感谢):
先看一个spring启动的例子:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
}
}
只要这一行启动代码,spring就为我们默认配置好了一切项目运行所必须的环境,是不是很简单,就从这里入手,看看spring到底做了什么!
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[]{source}, args);
}
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
//调用springApplication的构造函数
return (new SpringApplication(sources)).run(args);
}
public SpringApplication(Object... sources) {
//创建一个新的SpringApplication对象
initialize(sources);
}
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断是不是一个web的应用,判断的逻辑是加载 "javax.servlet.Servlet",
//"org.springframework.web.context.ConfigurableWebApplicationContext"这两个类,如果加载成功,则是web应用
// this.webEnvironment = true
this.webEnvironment = deduceWebEnvironment();
//初始化各种初始化器的实例,这些势力将会在创建好ApplicationContext后,prepare时进行调用,这里只是先对其进行实例化设值;
//这里总共有6个Initializers,是从spring.factories配置文件里面读取到的
//0 = {DelegatingApplicationContextInitializer@2208}
//1 = {ContextIdApplicationContextInitializer@2209}
//2 = {ConfigurationWarningsApplicationContextInitializer@2210}
//3 = {ServerPortInfoApplicationContextInitializer@2211}
//4 = {SharedMetadataReaderFactoryContextInitializer@2212}
//5 = {AutoConfigurationReportLoggingInitializer@2213}
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//设置10个listeners,实现原理同上,这里就不再赘述了,找到所有实现了ApplicationListener接口的实现类并实例化
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//从堆栈中找到启动类的信息并加载启动类,这里就是加载Application类,到这里,初始化的工作基本完成,下面开始执行Application //的run方法
this.mainApplicationClass = deduceMainApplicationClass();
}
public ConfigurableApplicationContext run(String... args) {
//new一个执行时间的监视器,记录spring启动的开始、结束时间;
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
//设置system的java.awt.headless的属性
this.configureHeadlessProperty();
//初始化一个SpringApplicationRunListeners对象,里面包含SpringApplicationRunListener数组,这里的数组只有一个监听器
//对象EventPublishingRunListener,他会发布一个ApplicationStartedEvent事件,我们可以监听这个事件做一些初始化的工作,
//其初始化SpringApplicationRunListener的实现原理同上面的ApplicationListener
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//因为是一个web应用,所以这里初始化一个StandardServletEnvironment环境对象,然后发布ApplicationEnvironmentPreparedEvent事件
//让监听者做文件解析的工作,详情看下面的1.1节
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//从名字就可以看出,这里就是打印banner的作用,具体的就是图案、springboot的版本号等信息
Banner printedBanner = this.printBanner(environment);
//创建ConfigurableApplicationContext,具体请看2.2
context = this.createApplicationContext();
//初始化FailureAnalyzersFailureAnalyzer 用于拦截我们感兴趣的异常,
//并将其包装到更具可读性的 FailureAnalysis ,
//如application-context相关的异常,默认的实现AbstractFailureAnalyzer
//继承于 FailureAnalyzer ,用于检查是否出现了特定的异常。如果需要
//访问到BeanFactoryEnvironment,
//可以实现BeanFactoryAware orEnvironmentAware接口。对于处理不了的异常,我们直接返回 null
//以便其他分析器可以处理。FailureAnalyzer 应该配置在 META-INF/spring.factories.才能生效,
//如:ProjectConstraintViolationFailureAnalyzer
//如果FailureAnalyzer实现了BeanFactoryAware接口,必须setBeanFactory设置BeanFactory
analyzers = new FailureAnalyzers(context);
//设置Context的属性信息,具体请看3.3
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新context,重点,具体请看4.4
this.refreshContext(context);
//完成刷新后的处理
this.afterRefresh(context, applicationArguments);
//发布一个ApplicationReadyEvent事件
listeners.finished(context, (Throwable)null);
//执行结束,记录执行时间
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
this.configureEnvironment(environment, applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
if (this.isWebEnvironment(environment) && !this.webEnvironment) {
environment = this.convertToStandardEnvironment(environment);
}
return environment;
}
1.1:new一个StandardServletEnvironment对象,并发布一个ApplicationEnvironmentPreparedEvent事件,还有做配置文件的解析的工作,监听ApplicationEnvironmentPreparedEvent事件并完成解析的工作可以参考我前面写的配置文件的解析的文章:https://blog.csdn.net/chengkui1990/article/details/79866499
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
//因为是web应用,所以这里是新建了一个StandardServletEnvironment对象
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置环境变量的source属性和prifile属性
configureEnvironment(environment, applicationArguments.getSourceArgs());
//发布一个ApplicationEnvironmentPreparedEvent事件,我们也可以自己监听该实践做一些解析工作
listeners.environmentPrepared(environment);
//如果environment是一个webEnvironment,那么就要转换成StandardEnvironment对象
if (isWebEnvironment(environment) && !this.webEnvironment) {
environment = convertToStandardEnvironment(environment);
}
return environment;
}
2.2:创建一个ConfigurableApplicationContext对象
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
//加载类org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
//返回一个ConfigurableApplicationContext对象,主要是通过反射:contextClass.newInstance
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
3.3:设置Context的属性信息
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置context的environment环境变量信息
context.setEnvironment(environment);
postProcessApplicationContext(context);
//主要是做一些context的初始化的工作,比如设置context的id,等等,总共有6个初始化器:
//这里的初始化器就是前面项目启动时加载的那6个Initializers,大家还有印象吗?
//具体请看3.3.1
applyInitializers(context);
//空的listener,什么事件都没有广播
listeners.contextPrepared(context);
if (this.logStartupInfo) {
//打印启动日志,包括机器名和PID
logStartupInfo(context.getParent() == null);
//打印当前的profile
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//注册一个单例的beanName=springApplicationArguments的ApplicationArguments对象
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
//注册一个单例的beanName=springBootBanner的Banner对象,注册过程请看3.3.2
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载bean进application context,这里是加载启动类Application
load(context, sources.toArray(new Object[sources.size()]));
//广播一个ApplicationPreparedEvent事件
listeners.contextLoaded(context);
}
3.3.1:初始化器初始化context的工作:
protected void applyInitializers(ConfigurableApplicationContext context) {
//循环迭代Initializers,逐个进行调用initialize方法,主要是填充context的属性
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
3.3.2:BeanFactory注册单例bean:
@Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { //首先是调用父类的registerSingleton方法,这里的父类是DefaultSingletonBeanRegistry对象 super.registerSingleton(beanName, singletonObject); if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { if (!this.beanDefinitionMap.containsKey(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1); updatedSingletons.addAll(this.manualSingletonNames); updatedSingletons.add(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase //bean不是在beanDefinitionMap里面 if (!this.beanDefinitionMap.containsKey(beanName)) { //因为是手动注册的bean,所以manualSingletonNames要加入该手动注册的bean this.manualSingletonNames.add(beanName); } } //清除缓存 clearByTypeCache(); }
DefaultSingletonBeanRegistry的registerSingleton方法:
@Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "'beanName' must not be null"); //先锁住singletonObjects对象,防止并发 synchronized (this.singletonObjects) { 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"); } //如果不存在,则新建单例对象 addSingleton(beanName, singletonObject); } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { //注册一个单例对象进入singletonObjects this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); //从但例工厂里面移除这个bean this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
4.4:刷新context:
private void refreshContext(ConfigurableApplicationContext context) {
//刷新context
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
4.4.1:刷新context
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//设置启动日期,close标志等于false,active标志等于true,初始化各种占位符信息
//验证各种必须的属性是否存在,为earlyApplicationEvents集合初始化一个LinkedHashSet
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//设置BeanFactory的SerialiableID
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//设置beanFactory的beanclassloader
//设置BeanExpressionResolver
//设置BeanPostProcessor=ApplicationContextAwareProcessor
//设置忽略依赖的集合和解析依赖的集合
//注册各种单例bean对象:environment、systemProperties、systemEnvironment
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//注册一个ServletContextAwareProcessor
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/**获取spring配置文件中定义的所有实现BeanFactoryPostProcessor接口的bean,然后根据优先级进行排序,之后对于每个 BeanFactoryPostProcessor,调用postProcessBeanFactory方法。
postProcessBeanFactory方法是在bean还没有初始化之前调用的,用户自己也实现该接口然后修改
bean的定义**/
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//rehoster所有的实现了BeanPostProcessor接口的bean,这样在后面的bean
//生成的时候拦截才能拦截并修改bean
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//初始化一个单例的MessageSource
initMessageSource();
// Initialize event multicaster for this context.
//初始化一个单例的ApplicationEventMulticaster对象
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//初始化特殊的bean,例如embeddedServletContainer
onRefresh();
// Check for listener beans and register them.
//注册所有监听器的bean,这里貌似也就是加入到一个集合中
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有的配置bean,这个很重要
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
完成刷新context,执行LifecycleProcessor
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();
}
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue(String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. //这一步很重要,这一步是初始化所有的单例的非懒加载的bean,实现还是很复杂的,具体的用户自己可以跟进去看看 beanFactory.preInstantiateSingletons(); }
//完成刷新做的事情 protected void finishRefresh() { // Initialize lifecycle processor for this context. //初始化所有的LifecycleProcessor,没有就新建一个默认的DefaultLifecycleProcessor,并注册成一个bean initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. //执行DefaultLifecycleProcessor的onRefresh方法 getLifecycleProcessor().onRefresh(); // Publish the final event. //广播一个ContextRefreshedEvent事件 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
写的有点乱了,未完待续吧!