ioc启动
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// 手动启用一个ioc容器
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("src/main/resources/spring-bean.xml");
}
}
FileSystemXmlApplicationContext的源码如下:
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext {
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 设置xml配置信息的所在位置
setConfigLocations(configLocations);
if (refresh) {
// ioc容器启动的方法
refresh();
}
}
}
可以看出refresh()的完成就是标志着ioc容器的启动完成,起详细源码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 刷新前的处理,比如标注环境启动时间,标注环境启动标识active = true, 标注环境关闭标识close = false 等
// active标识和close标识用atomic修饰,保持原子性
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 获取一个新的,干净的容器
// 先调用refreshBeanFactory()方法
// 删除旧的容器,然后创建一个新的容器并且初始化等,最后返回这个新的容器
// 在refreshBeanFactory方法中,载入BeanDefinition信息
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 配置容器的标准环境属性,比如context的classLoader或者poseProcessor这些
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 配置容器的后置处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用BeanFactory的后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册Bean的后处理器,在bean创建过程中调用
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化信息源
initMessageSource();
// Initialize event multicaster for this context.
// 初始化上下文中的时间机制
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 初始化一些特殊的bean
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.
// 发布容器结束事件
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();
}
}
}
BeanDefinition载入
BeanDefinition的载入是在ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()处完成的,在obtainFreshBeanFactory()方法里,会先refreshBeanFactory(),源码如下:
protected final void refreshBeanFactory() throws BeansException {
// 如果有beanFactory 指的是否持有defaultListableBeanFactory
if (hasBeanFactory()) {
// 销毁容器里面的所有singleton bean
// 源码其实容器里面把bean以及bean的信息等都放入hashMap或者ConCurrentHashMap里面,然后把这些map clear一下
destroyBeans();
// 关闭容器
// 将容器持有的DefaultListableBeanFactory设置成null
closeBeanFactory();
}
try {
// new 一个新的defaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定制容器 设置容器的一些属性
customizeBeanFactory(beanFactory);
// 设置definitionReader、resourceLoader、entityResolver等,方面后序对于BeanDefinition的处理
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
先判断是否已经存在容器,如果已经存在,则先销毁容器里面的单例bean,然后再关闭容器。后序从新创建一个DefaultListableBeanFactory,然后设置好一些相应的属性之后,则会开始loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
先定义一个XmlBeanDefinitionReader,用来读BeanDefinition是以xml形式来保存的元数据,类型的如果bean是用注解的形式的话,则也有相应的AnnotatedBeanDefinitionReader,给容器设置好相应的阅读器之后
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// resource就是配置的信息源,有可能是一个bean.xml,也有可能是一个注解的config类
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
在一系列对resource包装之后,执行:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
// 以下省略
}
此处才是真正的开始加载beanDefinition,会先把信息处理成标准的document,然后调用可以阅读document的BeanDefinitionDocumentReader继续解析信息源,最后就是将信息源解析成spring统一的一个beanDefinition数据结构,然后放入一个BeanDefinitionHolder,最后在push到容器内维护好的一个hashMap里面。其实就是整个beanDefinition的载入就是将不同信息源的解析成ioc标准的数据结构,然后放入到容器的map里面