您现在的位置是:主页 > news > 娄底哪里做网站/中国十大网站排名

娄底哪里做网站/中国十大网站排名

admin2025/6/19 18:11:54news

简介娄底哪里做网站,中国十大网站排名,wordpress 修改小部件,网站页面效果图怎么做写在前面 在这篇文章中分析了从xml文件解析为Document文档的过程,在这篇文章我们来继续分析从Document解析为BeanDefinition的过程。 1:作用 加载xml数据结构为spring中的BeanDefinition数据结构,为生成spring bean做准备。 2&#xff1a…

娄底哪里做网站,中国十大网站排名,wordpress 修改小部件,网站页面效果图怎么做写在前面 在这篇文章中分析了从xml文件解析为Document文档的过程,在这篇文章我们来继续分析从Document解析为BeanDefinition的过程。 1:作用 加载xml数据结构为spring中的BeanDefinition数据结构,为生成spring bean做准备。 2&#xff1a…

写在前面

在这篇文章中分析了从xml文件解析为Document文档的过程,在这篇文章我们来继续分析从Document解析为BeanDefinition的过程。

1:作用

加载xml数据结构为spring中的BeanDefinition数据结构,为生成spring bean做准备。

2:测试代码

为了方便调试再贴下测试代码:

@Test
public void testBeanDefinitionLoad() {// 定义资源ClassPathResource classPathResource = new ClassPathResource("testbeandefinition.xml");// 定义IOC容器DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();// 定义bean定义读取器XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);// 通过bean定义读取器从资源中读取bean定义int i = xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);System.out.println("bean定义的个数是:" + i);
}

xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="testBeanDefinitionBean"class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean><bean id="testBeanDefinitionBean1"class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean><!-- 这里引入自己的话会发生org.springframework.beans.factory.BeanDefinitionStoreException异常 --><!--<import resource="testbeandefinition.xml"/>-->
</beans>

执行测试代码,会执行到如下代码:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// 创建bean定义文档读取器BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();// 已经存在的BeanDefinition的个数int countBefore = getRegistry().getBeanDefinitionCount();// 使用documentReader通过document注册BeanDefinitiondocumentReader.registerBeanDefinitions(doc, createReaderContext(resource));// 当前的BeanDefinition的个数减去之前存在的个数,就是新增的个数return getRegistry().getBeanDefinitionCount() - countBefore;
}

3:createReaderContext

源码:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext
public XmlReaderContext createReaderContext(Resource resource) {return new XmlReaderContext(resource, this.problemReporter, this.eventListener,this.sourceExtractor, this, getNamespaceHandlerResolver());
}

先不深究。

4:createBeanDefinitionDocumentReader

源码:

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createBeanDefinitionDocumentReader
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {// 	private Class<? extends BeanDefinitionDocumentReader> documentReaderClass =// DefaultBeanDefinitionDocumentReader.class;return BeanUtils.instantiateClass(this.documentReaderClass);
}

DefaultBeanDefinitionDocumentReader是BeanDefinitionDocumentReader接口的实现类,完成从文档对象中注册BeanDefinition的功能。

5:registerBeanDefinitions

通过调用方法org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions完成注册BeanDefinition的功能,源码如下:

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;// 调用doRegisterBeanDefinitions并获取根元素作为参数,这里是<beans>元素doRegisterBeanDefinitions(doc.getDocumentElement());
}

继续看源码:

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {BeanDefinitionParserDelegate parent = this.delegate;// <2021-02-28 05:52>this.delegate = createDelegate(getReaderContext(), root, parent);// <2021-02-28 05:53>// 获取是否为根元素,其实就是判断命名空间值为http://www.springframework.org/schema/beans/if (this.delegate.isDefaultNamespace(root)) {// 获取profiles属性的值,profile是用来设置生效的环境变量的// 和spring.active.profiles,spring.active.default配套// 使用的,一般为空,如果是配置了则进一步判断是否满足环境变量// 要求,如果是不满足则不加载,满足则继续String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);// 配置了profileif (StringUtils.hasText(profileSpec)) {// 获取配置的profile信息String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);// 如果是环境变量中设置的spring.active.prifle,或者是// spring.active.default和当前根元素中设置的相同则不return,然后继续加载工作,否则returnif (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isDebugEnabled()) {logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}// 解析前处理,目前为空方法,留给子类扩展使用preProcessXml(root);// <2021-02-28 07:16>// 解析parseBeanDefinitions(root, this.delegate);// 解析后处理,目前是空方法,留给子类扩展使用postProcessXml(root);this.delegate = parent;
}

<2021-02-28 05:53>是处理profile信息的,如果是配置的profile在环境变量中没有设置,则不加载,如下xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans profile="gagagagaga" xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="testBeanDefinitionBean"class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean><bean id="testBeanDefinitionBean1"class="yudaosourcecode.spring.TestBeanDefinitionBean"></bean><!-- 这里引入自己的话会发生org.springframework.beans.factory.BeanDefinitionStoreException异常 --><!--<import resource="testbeandefinition.xml"/>-->
</beans>

在根标签<beans>中设置了profile="gagagagaga",如下的测试代码注释了设置对应配套环境变量的代码,因此不会加载bean:

@Test
public void testBeanDefinitionLoad() {// System.setProperty("spring.profiles.active", "gagagagaga");// 定义资源ClassPathResource classPathResource = new ClassPathResource("testbeandefinition.xml");// 定义IOC容器DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();// 定义bean定义读取器XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);// 通过bean定义读取器从资源中读取bean定义int i = xmlBeanDefinitionReader.loadBeanDefinitions(classPathResource);System.out.println("bean定义的个数是:" + i);
}

注意到其中的代码System.setProperty("spring.profiles.active", "gagagagaga");是注释掉的,运行debug,会进入到return:
在这里插入图片描述
运行可以看到加载的BeanDefinition的个数为0:

bean定义的个数是:0

如果把注释代码System.setProperty("spring.profiles.active", "gagagagaga");放开则就可以正常加载了,运行:

bean定义的个数是:2

<2021-02-28 05:52>处代码获取BeanDefinitionParserDelegate对象,该对象比较重要,负责解析工作。<2021-02-28 07:16>处源码如下:

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {// 如果是默认命名空间,即命名空间为http://www.springframework.org/schema/beans/if (delegate.isDefaultNamespace(root)) {// 获取所有的子节点NodeList nl = root.getChildNodes();// 遍历所有的子节点for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);// 如果是Element类型if (node instanceof Element) {// 强转为ElementElement ele = (Element) node;// 如果是默认命名空间标签,即值为// http://www.springframework.org/schema/beans/if (delegate.isDefaultNamespace(ele)) {// <2021-02-28 07:41>parseDefaultElement(ele, delegate);}else {// 处理非默认命名空间标签delegate.parseCustomElement(ele);}}}}else {// 处理非默认命名空间标签delegate.parseCustomElement(root);}
}

<2021-02-28 07:41>处代码解析默认元素,源码如下:

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {// 如果是import标签if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}// 如果是alias标签else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}// 如果是bean标签else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}// 如果是内嵌beans标签,则递归解析else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}
}

关于bean标签的解析可以参考这里,关于import标签的解析可以参考这里。