通过ClassPathXmlApplicationContext源码解读Spring启动过程
@(Spring)[Spring][源码]
注:本次分析基于spring-context-5.1.0.RC1.jar
- 通过ClassPathXmlApplicationContext源码解读Spring启动过程
- 类关系
- 入口函数
- 解读refresh方法
- prepareRefresh()
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
- prepareBeanFactory(beanFactory)
- postProcessBeanFactory(beanFactory)
- invokeBeanFactoryPostProcessors(beanFactory)
- registerBeanPostProcessors(beanFactory)
- initMessageSource()
- initApplicationEventMulticaster()
- onRefresh()
- registerListeners()
- finishBeanFactoryInitialization(beanFactory)
- finishRefresh()
- destroyBeans()
- cancelRefresh(ex)
- resetCommonCaches()
类关系
入口函数
通过ClassPathXmlApplicationContext
类构造方法启动父类AbstractApplicationContext
的函数refresh方法
/**
* Create a new ClassPathXmlApplicationContext, loading the definitions
* from the given XML file and automatically refreshing the context.
* @param configLocation resource location
* @throws BeansException if context creation failed
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
@Override
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();
}
}
}
解读refresh方法
refresh方法第一行是对startupShutdownMonitor进行了加锁处理,使得refresh方法线程同步,然后执行下面一系列的方法,这里先初步了解一下每个方法的作用,后面再对每一个方法进行详细解析
prepareRefresh()
主要有两段逻辑, 涉及重要的类Environment\AbstractEnvironment
1.1 initPropertySources方法是一个protected的空方法,留给子类实现的
1.2 getEnvironment().validateRequiredProperties()创建了spring的环境参数组件,并验证必备参数
通过
System.getProperties()
获取JVM相关参数,System.getenv()
程序运行的系统、硬件及环境变量相关参数
获取后的参数放入AbstractEnvironment类的成员变量propertySources中
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
解析项目配置的 application.xml、xxx.xml 定义的import、bean、resource、profile等等,得到一个bean工厂对象
prepareBeanFactory(beanFactory)
对bean工厂做一些初始化处理
postProcessBeanFactory(beanFactory)
spring提供的扩展点,可以通过继承ClassPathXmlApplicationContext来重写该方法