Spring IOC解析
问题:Spring怎么加载配置文件,怎么注册bean,怎么获取bean
1.XmlBeanFactory
- new Resource(ClassPathResource 实现类获取bean配置文件和当前类加载器)传给XmlBeanFactory构造方法
ClassPathResource resource = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
UserDto userDto = factory.getBean("userDto", UserDto.class);
<1>初始化XmlBeanDefinitionReader
<2>调用XmlBeanDefinitionReader.loadBeanDefinitions方法
<1>:创建Set<EncodedResource>集合添加到resourcesCurrentlyBeingLoaded
<2>:InputStream inputStream = encodedResource.getResource().getInputStream();获取xml输入流
<3>:InputSource inputSource = new InputSource(inputStream);转换为资源输入流
<4>:调用doLoadBeanDefinitions获取配置文件Doucment ->调用doLoadDocument(获取配置文件的xsd约束文件)
->DefauktDocumentLoader.loadDocument,DocumentBuilder builder.parse(inputSource)解析
<5>:解析完成后调用XmlBeanDefinitionReader.registerBeanDefinitions
->初始化BeanDefinitionDocumentReader
->获取容器之前的数量(DefaultListableBeanFactory.beanDefinitionMap<String, BeanDefinition>.size())
->doRegisterBeanDefinitions
->preProcessXml(root);解析之前
->DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(root, this.delegate);
->parseDefaultElement(对比是否是
import:importBeanDefinitionResource,
alias:processAliasRegistration,
bean:processBeanDefinition,
->BeanDefinitionParserDelegate.parseBeanDefinitionElement 负责解析元素
->获取标签id和name属性
->checkNameUniqueness将获取的id和name值保存在usedNames Set集合里面
->parseBeanDefinitionElement 将bean名称保存到Stack<Entry>
->parseBeanDefinitionAttributes 处理默认值以及填写的属性值
beans:doRegisterBeanDefinitions)
->DefaultListableBeanFactory.beanDefinitionMap.put(beanName,beanDefinition)
->DefaultListableBeanFactory.beanDefinitionNames.add(beanName)
->DefaultListableBeanFactory.manualSingletonNames.remove(beanName)
->BeanComonentDefintion.findInnerBeanDefinitionsAndBeanReferences获取property设置的值存放在beanDefinition(所有配置文件的元数据都保存在这里,通过反射获取这里配置组装Bean)
->postProcessXml(root);解析之后
<6>:获取Bean
BeanDefintionValueResover负责将property值赋值给Bean
-
Ioc容器初始化过程,分为三个过程(1.BeanDefinition的Resouce定位,2.加载解析,3注册)
- 通过ResourceLoader读取以Resource定义的BeanDefinition
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
//触发容器初始化,以及解析BeanDefinition
refresh();
}
}
//AbstractRefreshableApplicationContext,该类是AbstractApplicationContext基类
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
//解析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);
}
}
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.loadBeanDefinitions解析载入BeanDefinition(这里解析的是XML其他形式可以由具体的BeanDefinitionReader基类解析)
具体的解析完成是在BeanDefinitionParserDelegate中完成 -
DefaultListableBeanFactory 负责将解析好的BeanDefinition注册到ioc容器中,该容器是一个HashMap
beanDefinitionMap.put(beanName,beanDefinition) -
BeanFactroy根据组装好的BeanDefinition进行注入