spring应该是java中最常用的开源框架,引入spring可以降到应用开发的复杂性。平常大家更关注于spring的应用,本文就和各位一起来分析一下spring的源码。
spring发展到今天,已然是个十分庞大的框架,往往不知从何处下手,本文就从spring的加载过程入手。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
applicationContext.getBean("name");
上面这段简单的代码就是spring的启动方式之一,通过对于ClassPathXmlApplicationContext的实例化就可以完成spring的加载过程。先给出ClassPathXmlApplicationContext的继承关系图,诸如spring的框架,结构都较复杂,列一下继承的关系,对于我们的理解很有帮助,图如下:
ClassPathXmlApplicationContext的构造函数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
构造函数的功能:加载指定的xml文件并且刷新上下文内容。
从以上贴的代码来看很简单,就是做了三件事:
1.super(parent)
设置父级的ApplicationContext,这里设置了null
2.setConfigLocations(configLocations)
设置spring配置文件的路径,并且对于路径中的占位置进行转换
3.refresh()
refresh()是spring加载的核心内容,通过xml、properties、database对于context加载和刷新,完成对于所有单例类的初始化工作。
refresh()方法
上文已经提到refresh()方法是整个spring的加载的核心,这也是我们本次需要提到的重点内容,先展示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) {
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;
}
}
}
首先spring的refresh()方法的一些特点:
1.方法从开始到结束都使用了对于this.startupShutdownMonitor的加锁处理
1).避免了多线程同时刷新spring配置
2).close()和refresh()都对startupShutdownMonitor进行加锁,close()的作用和refresh()是相反的:关闭context,销毁所有的bean。避免了2者的同时执行,产生冲突。
2.refresh()方法中没有具体的对于业务逻辑处理的代码,而是分成了若干个子方法,方便项目维护和代码拓展。
本文先讲到这里,下一篇开始,对于refresh()中的各个子方法进行详细的梳理