DefaultBeanDefinitionDocumentReader.java
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)) { //加载默认的阶段配置信息【程序入口】 this.parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
parseDefaultElement(ele, delegate)该方法会根据当前节点类型作三件事情java
一、导入importnode
例如:app
<import resource="applicationContext-mybean.xml"></import>
二、alias别名post
<bean name="myBean,wahaha,gagBean" class="com.wolf.bean.Mybean1"> <property name="name"> <value>郑先生</value> </property> <property name="pwd"> <value>666666888888</value> </property> </bean> <!--给myBean起别名--> <alias name="myBean" alias="gagBean,gagaBean,gagagaBean"></alias>
三、bean定义ui
<bean name="myBean2" class="com.wolf.bean.Mybean1"> <property name="name"> <value>郑先生2</value> </property> <property name="pwd"> <value>2222222</value> </property> </bean>
四、beans集合this
对于beans集合系统会从新走doRegisterBeanDefinitions处理流程,跟程序来源同样。spa
parseDefaultElement(ele, delegate)代码实现以下code
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if(delegate.nodeNameEquals(ele, "import")) {//导入 this.importBeanDefinitionResource(ele); } else if(delegate.nodeNameEquals(ele, "alias")) {//别名 this.processAliasRegistration(ele); } else if(delegate.nodeNameEquals(ele, "bean")) {//bean this.processBeanDefinition(ele, delegate); } else if(delegate.nodeNameEquals(ele, "beans")) {//bean集合 this.doRegisterBeanDefinitions(ele); } }
1、importxml
protected void importBeanDefinitionResource(Element ele) { String location = ele.getAttribute("resource"); if(!StringUtils.hasText(location)) { this.getReaderContext().error("Resource location must not be empty", ele); } else { location = this.getReaderContext().getEnvironment().resolveRequiredPlaceholders(location); LinkedHashSet actualResources = new LinkedHashSet(4); boolean absoluteLocation = false; try { absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); } catch (URISyntaxException var11) { ; } int actResArray; if(absoluteLocation) { try { actResArray = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources); } catch (BeanDefinitionStoreException var10) { this.getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, var10); } } else { try { Resource relativeResource = this.getReaderContext().getResource().createRelative(location); //判断当前资源文件是否存在 if(relativeResource.exists()) { //执行XmlBeanDefinitionReader的loadBeanDefinitions,跟加载资源的流程一致 //因此import资源处理操做是很是简单的 actResArray = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = this.getReaderContext().getResource().getURL().toString(); actResArray = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources); } } catch (IOException var8) { this.getReaderContext().error("Failed to resolve current resource location", ele, var8); } catch (BeanDefinitionStoreException var9) { this.getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, var9); } } Resource[] actResArray1 = (Resource[])actualResources.toArray(new Resource[actualResources.size()]); //这里作了一个事件通知 this.getReaderContext().fireImportProcessed(location, actResArray1, this.extractSource(ele)); } }
2、alias别名解析对象
protected void processAliasRegistration(Element ele) { //经过当前节点的别名信息配置 //name 表示BeanName String name = ele.getAttribute("name"); //别名信息 String alias = ele.getAttribute("alias"); boolean valid = true; if(!StringUtils.hasText(name)) { this.getReaderContext().error("Name must not be empty", ele); valid = false; } if(!StringUtils.hasText(alias)) { this.getReaderContext().error("Alias must not be empty", ele); valid = false; } if(valid) { try { //XmlReaderContext-->BeanDefinitionRegistry-->GenericApplicationContext(接口BeanDefinitionRegistry)的registerAlias方法[DefaultListableBeanFactory beanFactory] //其实就是往DefaultListableBeanFactory beanFactory中设置别名信息(SimpleAliasRegistry为具体别名注册实现) //private final Map<String, String> aliasMap = new ConcurrentHashMap(16); 别名属性记录器 this.getReaderContext().getRegistry().registerAlias(name, alias); } catch (Exception var6) { this.getReaderContext().error("Failed to register alias \'" + alias + "\' for bean with name \'" + name + "\'", ele, var6); } this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele)); } }
根据类图结构能够看到
DefaultListableBeanFactory为SimpleAliasRegistry的子类
而后在父类实现了别名的注册,子类直接使用便可。
--分部代码实现 DefaultBeanDefinitionDocumentReader.java类中持有XmlReaderContext readerContext对象 其中this.getReaderContext()其实就是去获取XmlReaderContext protected final XmlReaderContext getReaderContext() { return this.readerContext; } 当拿到XmlReaderContext对象后,经过XmlReaderContext提供的getRegistry()获取注册器 XmlReaderContext.java类中持有XmlBeanDefinitionReader reader xmlBean读取器,在xmlBean读取器中获取注册器 public final BeanDefinitionRegistry getRegistry() { return this.reader.getRegistry(); } AbstractBeanDefinitionReader.java类中持有 private final BeanDefinitionRegistry registry//BeanDefinitionRegistry为一个接口 public final BeanDefinitionRegistry getRegistry() { return this.registry; } GenericApplicationContext.java持有DefaultListableBeanFactory beanFactory public void registerAlias(String beanName, String alias) { this.beanFactory.registerAlias(beanName, alias); } SimpleAliasRegistry.java private final Map<String, String> aliasMap = new ConcurrentHashMap(16); public void registerAlias(String name, String alias) { if(alias.equals(name)) { this.aliasMap.remove(alias); } else { String registeredName = (String)this.aliasMap.get(alias); if(registeredName != null) { if(registeredName.equals(name)) { return; } if(!this.allowAliasOverriding()) { throw new IllegalStateException("Cannot register alias \'" + alias + "\' for name \'" + name + "\': It is already registered for name \'" + registeredName + "\'."); } } this.checkForAliasCircle(name, alias); this.aliasMap.put(alias, name); } }
总结:其实别名的注册思路很简单。就是在beanFactory容器中去查找当前beanName是否存在别名,若是存在则直接return;若是别名与beanName的名称相同时也return;
这里还加入了一个逻辑就是判断别名是否可以被替换在目前的代码实现直接返回了true,也就是说默认状况能够直接替换别名的。
protected boolean allowAliasOverriding() { return true; }
this.checkForAliasCircle(name, alias)
这里作了一个验证,就是验证当前注册的别名是否被其余的beanName注册过,若是注册过会抛出
throw new IllegalStateException("Cannot register alias \'" + alias + "\' for name \'" + name + "\': Circular reference - \'" + name + "\' is a direct or indirect alias for \'" + alias + "\' already")异常
3、beans处理
beans处理逻辑也比较简单
直接调用了this.doRegisterBeanDefinitions(ele)逻辑,而后咱们跟踪代码,发现跟处理rootElement逻辑相同。
protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = this.createDelegate(this.getReaderContext(), root, parent); if(this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute("profile"); if(StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, ",; "); if(!this.getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if(this.logger.isInfoEnabled()) { this.logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + this.getReaderContext().getResource()); } return; } } } this.preProcessXml(root); this.parseBeanDefinitions(root, this.delegate); this.postProcessXml(root); this.delegate = parent; }
4、bean标签处理
TIPS:针对bean标签的处理逻辑相对比较复杂,这里要深刻分析。
【接】基于XmlBeanFactory加载bean分析:parseDefaultElement(二)