IOC容器案例:XmlBeanFactorynode
XmlBeanFactory容器初始化过程:数据结构
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("com/zhiwei/ioc/applicationContext.xml"));
步骤1:XmlBeanFactory 使用 ClassPathResource 映射Spring XML配置文件app
new ClassPathResource("com/zhiwei/ioc/applicationContext.xml")
步骤2:初始化空白的IOC容器,而后使用XmlBeanDefinitionReader解析Spring XML配置文件,并注入到IOC容器ide
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { //传递父BeanFactory初始化父类 super(parentBeanFactory); //BeanDefinition解析 this.reader.loadBeanDefinitions(resource); }
步骤3: 查看XmlBeanDefinitionReader.loadBeanDefinitions() 方法post
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(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()); } 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(); } } }
方法解读: resourcesCurrentlyBeingLoaded:经过ThreadLocal绑定EncodedResource,XmlBeanDefinitionReader就持有配置资源映射,方便后续DOM XML解析,将配置资源封装为 inputSource对象,而后传递给doLoadBeanDefinitions方法ui
步骤4:查看XmlBeanDefinitionReader.doLoadBeanDefinitions方法 源码:this
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); }
解析: doLoadDocument方法底层经过DOM解析的方法解析Spring XML配置文件,并返回Document对象,接着调用registerBeanDefinitions进行Bean实际注册工做spa
步骤5:查看XmlBeanDefinitionReader.registerBeanDefinitions方法实现debug
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
解析: getRegistry():可用于获取IOC容器,缘由XmlBeanFactory实例化: private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); 将XML的Bean定义阅读器与IOC容器绑定在一块儿 registerBeanDefinitions内部调用registerBeanDefinitions注册Bean,注意createReaderContext方法会建立XmlReaderContext,该对象会与XmlBeanDefinitionReader 绑定,从而实现与IOC容器的间接绑定,这一点对于后续的Bean实际IOC容器注册很是重要code
步骤6:查看BeanDefinitionDocumentReader.registerBeanDefinitions方法
注意:BeanDefinitionDocumentReader主要做用就是将Spring XMl配置文件元素映射为IOC容器中的BeanDefinition数据结构,实现真正意义上的解析、注册Bean的功能
@Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); doRegisterBeanDefinitions(root); }
解析:将readerContext做为BeanDefinitionDocumentReader的内置组件,而后获取XML文件的Root节点,接着调用doRegisterBeanDefinitions方法处理
步骤7: BeanDefinitionDocumentReader.doRegisterBeanDefinitions方法代码
protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }
解析:实际解析XMl文件的时BeanDefinitionParserDelegate对象,查看createDelegate方法:
protected BeanDefinitionParserDelegate createDelegate( XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext); delegate.initDefaults(root, parentDelegate); return delegate; }
该方法执行时不单单返回BeanDefinitionParserDelegate 对象,还会在建立后进行Beans标签的属性信息的初始化工做,该方法核心代码:
preProcessXml(root); //自定义标签前置处理 parseBeanDefinitions(root, this.delegate); //Spring原始标签处理 postProcessXml(root); //自定义标签后置处理
步骤8:查看BeanDefinitionDocumentReader.parseBeanDefinitions方法代码
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
解析:该方法遍历XML文件映射的DOM树的节点,delegate.isDefaultNamespace(root)主要用于XML文件命名空间校验,delegate.isDefaultNamespace(ele)用于区别配置文件中的元素是否时Spring自带的,如果Spring自身元素则parseDefaultElement方法处理,不然parseCustomElement处理(例如自定义标签)
步骤9:查看BeanDefinitionDocumentReader.parseDefaultElement方法代码
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
解析:该方法做为一个中转接口,根据标签元素的不一样选择相应的方法处理,这里主要探索Bean标签的处理方法processBeanDefinition(ele, delegate);
步骤10:查看BeanDefinitionDocumentReader.processBeanDefinition方法代码:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
解析:
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
主要时根据Root元素节点遍历,而后将数据封装到 BeanDefinitionHolder 这个数据结构,真正IOC容器的Bean注册在 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 方法
步骤11:查看BeanDefinitionReaderUtils.registerBeanDefinition方法代码
public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String alias : aliases) { registry.registerAlias(beanName, alias); } } }
解析:这里Bean注册分为Bean注册和Bean别名注册,主要看registry.registerBeanDefinition方法
步骤12:查看BeanDefinitionRegistry.registerBeanDefinition(这里使用DefaultListableBeanFactory基础IOC容器)
@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition oldBeanDefinition; oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (this.logger.isWarnEnabled()) { this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } else { if (this.logger.isDebugEnabled()) { this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
解析: 首先校验生成的BeanDefinition类型,接着校验新建立的Bean是否在IOC容器中注册过,若是注册过则按照Bean的相应配置策略进行处理,例如重写,接着根据hasBeanCreationStarted方法判断IOC容器是否启动过,若是未启动则beanDefinitionMap Map记录BeanName与BeanDefinition对象的关系,beanDefinitionNames记录注册的Bean名称,这里Map的key为BeanName这就时IOC容器中BeanName惟一的缘由,若是IOC容器实现启动则beanDefinitionMap直接存放,manualSingletonNames须要已有的BeanName进行校验,最终等于beanDefinitionNames数据,至此整个XMl解析与IOC容器的初始化工做所有完成。