1、源码解析
obtainFreshBeanFactory()方法包含了 Spring的IOC容器 - DefaultListableBeanFactory对象的创建、解析配置文件中的bean信息加载至容器中。1 // 创建容器对象DefaultListableBeanFactory,加载xml配置文件的属性值到当前工厂中 2 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1.1、初始化容器 - refreshBeanFactory()
refreshBeanFactory()方法由AbstractApplicationContext的子类AbstractRefreshableApplicationContext具体实现,初始化容器-beanFactory。1 // 刷新内部工厂 2 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 3 // 初始化BeanFactory,并读取XML文件,将得到的BeanFactory记录在当前实体的属性中 4 refreshBeanFactory(); 5 // 返回当前实体的beanFactory属性 6 return getBeanFactory(); 7 }refreshBeanFactory()的整体流程:
1、创建容器beanFactory
创建DefaultListableBeanFactory对象的容器 - beanFactory(忽略BeanNameAware、BeanFactoryAware、BeanClassLoaderAware接口实现类);2、为beanFactory填充属性
customizeBeanFactory(beanFactory)是AbstractRefreshableApplicationContext中的方法, 为beanFactory设置属性。1 // 为beanFactory填充属性 2 protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) { 3 // 如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,是否允许覆盖同名称的不同定义的对象 4 if (this.allowBeanDefinitionOverriding != null) { 5 beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); 6 } 7 // 如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,是否允许bean之间存在循环依赖 8 if (this.allowCircularReferences != null) { 9 beanFactory.setAllowCircularReferences(this.allowCircularReferences); 10 } 11 }allowBeanDefinitionOverriding 与allowCircularReferences 是在createBeanFactory(beanFactory);中做的赋值操作。allowCircularReferences 是在创建DefaultListableBeanFactory对象做的初始化,默认值为true。
1 // 是否允许名称相同但beanDefinition不同的对象被覆盖 2 private boolean allowBeanDefinitionOverriding = true;
3、获取beanDefinition
解析配置文件中定义的标签信息: 默认标签解析;自定义标签解析。loadBeanDefinitions(beanFactory);加载bean定义信息。
1 // 通过XmlBeanDefinitionReader加载beanDefinition 2 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { 3 // Create a new XmlBeanDefinitionReader for the given BeanFactory. 4 // 创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中 5 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 6 7 // 为beanDefinitionReader设置环境对象 8 beanDefinitionReader.setEnvironment(this.getEnvironment()); 9 beanDefinitionReader.setResourceLoader(this); 10 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); 11 12 // 初始化beanDefinitionReader对象,并设置配置文件是否要进行验证 13 initBeanDefinitionReader(beanDefinitionReader); 14 // 加载BeanDefinitions 15 loadBeanDefinitions(beanDefinitionReader); 16 }上述代码是AbstractXmlApplicationContext中的方法,创建了bean定义信息读取器,为读取器填充属性,最终会调用XmlBeanDefinitionReader中的loadBeanDefinitions()方法,核心伪代码如下:
1 // 加载beanDefinition信息 2 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 3 4 // 通过属性来记录已经加载的资源 5 Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); 6 if (!currentResources.add(encodedResource)) { 7 throw new BeanDefinitionStoreException( 8 "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); 9 } 10 // 从encodedResource中获取已经封装的Resource对象, 再获取Resource对象的inputStream流信息 11 try (InputStream inputStream = encodedResource.getResource().getInputStream()) { 12 InputSource inputSource = new InputSource(inputStream); 13 if (encodedResource.getEncoding() != null) { 14 inputSource.setEncoding(encodedResource.getEncoding()); 15 } 16 // 加载beanDefinition核心逻辑,实际从指定的xml中加载beanDefinition 17 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); 18 } 19 catch (IOException ex) { 20 throw new BeanDefinitionStoreException( 21 "IOException parsing XML document from " + encodedResource.getResource(), ex); 22 } 23 finally { 24 // 移除已经加载的资源 25 currentResources.remove(encodedResource); 26 if (currentResources.isEmpty()) { 27 this.resourcesCurrentlyBeingLoaded.remove(); 28 } 29 } 30 }可以看到这一步还是加载beanDefinition的准备工作,获取Resource对象的输入流inputStream,封装输入流并进入加载beanDefinition的核心逻辑doLoadBeanDefinitions()。
1 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) 2 throws BeanDefinitionStoreException { 3 4 try { 5 // 获取xml文件的document对象,这个解析过程是由documentLoader完成的, 6 Document doc = doLoadDocument(inputSource, resource); 7 // 根据文档的节点信息封装成一个个的BeanDefinition对象 8 int count = registerBeanDefinitions(doc, resource); 9 if (logger.isDebugEnabled()) { 10 logger.debug("Loaded " + count + " bean definitions from " + resource); 11 } 12 return count; 13 } 14 ..... 15 catch (Throwable ex) { 16 throw new BeanDefinitionStoreException(resource.getDescription(), 17 "Unexpected exception parsing XML document from " + resource, ex); 18 } 19 }该步骤主要是注册bean定义信息的准备工作,获取配置文件的document对象,通过String[](配置文件集合) -string(配置文件)-Resource[]- resource,最终开始将resource读取成一个document文档。
1 // 创建document对象的读取器 2 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { 3 // 对xml的beanDefinition进行解析 4 // 创建BeanDefinitionDocumentReader对象 5 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 6 int countBefore = getRegistry().getBeanDefinitionCount(); 7 // 通过spring-beans的XSD或DTD实现beanDefinition具体的解析过程 8 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 9 return getRegistry().getBeanDefinitionCount() - countBefore; 10 }该步是注册bean定义信息的准备工作,获取document对象读取器。
1 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { 2 this.readerContext = readerContext; 3 // 注册定义在<bean/>标签的每一个beanDefinition 4 doRegisterBeanDefinitions(doc.getDocumentElement()); 5 }doRegisterBeanDefinitions()是将BeanDefinition对象注册进容器的核心逻辑,核心伪代码如下
1 public static final String PROFILE_ATTRIBUTE = "profile"; 2 public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; "; 3 4 // 注册beanDefinitionn的核心处理逻辑 5 protected void doRegisterBeanDefinitions(Element root) { 6 BeanDefinitionParserDelegate parent = this.delegate; 7 // 初始化解析beanDefinition的委托类 8 this.delegate = createDelegate(getReaderContext(), root, parent); 9 // ... 10 // 解析beanDefinition前的处理 11 preProcessXml(root); 12 // 解析beanDefinition信息 13 parseBeanDefinitions(root, this.delegate); 14 // 解析beanDefinition后的处理 15 postProcessXml(root); 16 17 this.delegate = parent; 18 }doRegisterBeanDefinitions()中的核心步骤 parseBeanDefinitions(root, this.delegate);,preProcessXml和postrocessXml有子类拓展实现,下面来看看DefaultBeanDefinitionDocumentReader中的解析方法parseBeanDefinitions()。
1 // 解析bean定义信息 2 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 3 // 是否为默认命名空间 4 if (delegate.isDefaultNamespace(root)) { 5 NodeList nl = root.getChildNodes(); 6 for (int i = 0; i < nl.getLength(); i++) { 7 Node node = nl.item(i); 8 if (node instanceof Element) { 9 Element ele = (Element) node; 10 // 解析默认命名空间元素,如<bean>标签 11 if (delegate.isDefaultNamespace(ele)) { 12 parseDefaultElement(ele, delegate); 13 } 14 // 解析自定义命名空间元素,如<aop>相关标签 15 else { 16 delegate.parseCustomElement(ele); 17 } 18 } 19 } 20 } 21 else { 22 delegate.parseCustomElement(root); 23 } 24 }parseBeanDefinitions()解析document对象文档树中的默认标签、自定义标签。关于beanDefinition的具体解析,我们放在下一章节介绍。