Xml格式的应用启动
Xml和注解是我们进行使用Spring进行开发时用到的两种主要配置方式。本文简单介绍Xml格式的应用的启动流程。
从启动应用的代码开始入手:
public class Launcher {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/spring.xml");
CountDownLatch latch = new CountDownLatch(1);
try {
latch.await();
} catch (InterruptedException ignored) {
}
}
}
这里,只是创建了一个ClassPathXmlApplicationContext的实例,并传入了一个字符串“classpath:spring/spring.xml”,来看它的构造器:
//上面使用的构造器
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
//最终使用的构造器
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
因为parent为null,所以这里先忽略super(parent);主要做了两件事:setConfigLocations(configLocations)和refresh();
setConfigLocations(configLocations)是在其父类AbstractRefreshableConfigApplicationContext中:
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}else {
this.configLocations = null;
}
}
//resolvePath方法:如果给的路径中含有占位符${...},则使用环境变量来替换掉
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
其实this.configLocations最终就是我们传入的那个字符串,即:
this.configLocations=["classpath:spring/spring.xml"]
到这里,setConfigLocations(configLocations)就结束了,该方法就是将我们传入的一个表示路径的字符串设置给ClassPathXmlApplicationContext。
再来看refesh(),该方法是接口ConfigurableApplicationContext中定义的方法,是应用真正启动的方法,所以这个方法非常重要。
具体到ClassPathXmlApplicationContext,这个refesh()的实现是在其父类AbstractApplicationContext中:
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) {
// 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();
}
}
}