BeanDefition加载注册过程
进入obtainFreshBeanFactory方法,这里面refreshBeanFactory方法会去创建beanFactory并加载bean
进入obtainFreshBeanFactory方法,这里面refreshBeanFactory方法会去创建beanFactory并加载bean
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
进入AbstractRefreshableApplicationContext类中的refreshBeanFactory方法
在这里首先会将已经创建的bean工程销毁,然后创建新的bean工厂,设置bean工厂的一些属性,这里我们看到bean工厂是可以被序列化的,在customizeBeanFactory里面自定义bean工厂环境,通过allowBeanDefinitionOverriding和allowCircularReferences这两个属性用户可以自己来决定是否需要bean的覆盖,是否需要循环依赖,目前还暂时还用不到这两个属性,下面往容器中注册这些bean的时候会用到,loadBeanDefinitions这个方法才会去真正加载bean
protected final void refreshBeanFactory() throws BeansException {
//如果之前已经创建了bean工厂,那么则销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建bean工厂
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置序列化id
beanFactory.setSerializationId(getId());
//相同名称的bean是否允许覆盖,是否允许循环依赖
customizeBeanFactory(beanFactory);
//这里到了最关键的部分,将BeanDefinition加载到bean工厂
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
进入AbstractXmlApplicationContext类的loadBeanDefinitions方法,在这里首先给bean工厂创建一个bean资源加载器并初始化相关环境,进入loadBeanDefinitions继续加载bean,这里也是最关键的地方
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
//给bean工厂创建一个资源加载器
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.
//初始化bean资源加载器
initBeanDefinitionReader(beanDefinitionReader);
//开始加载bean定义
loadBeanDefinitions(beanDefinitionReader);
}
它会将所有的xml进行循环加载,最终会进入XmlBeanDefinitionReader这个类里的loadBeanDefinitions方法.在这里会获得一个inputStream输入流进入doLoadBeanDefinitions方法开始读取bean,并将xml转换为Document对象
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
//从资源加载描述中获得一个输入流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//进入关键部分,开始加载bean定义
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
进入doLoadBeanDefinitions方法,这里主要是读取xml并转换为Document对象,关于xml的解析这个就不多介绍,直接进入到registerBeanDefinitions方法在这里开始往容器中注册bean,
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//加载解析xml文件并返回一个document对象
Document doc = doLoadDocument(inputSource, resource);
//开始注册bean定义
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
最终会进入DefaultBeanDefinitionDocumentReader类里的parseBeanDefinitions方法,在parseDefaultElement方法会解析在xml中常见的import,alias,bean等标签
关于bean的更多注册过程详细内容,可以关注本人公众号 "零壹工场" 详情说明