曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上) (3)

骨架代码里,遍历每个元素,在spring里,遍历到每个ele时,要去判断对应的namespace,如果是默认的,交给xxx处理;如果不是默认的,要根据namespace找到对应的namespacehandler,具体大家可以看看上一节:

曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的

我们在前面说了,本讲只先挑一个元素来讲解,即 。

util-constant元素详解 用法 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans "> <util:constant static-field= "java.sql.Connection.TRANSACTION_SERIALIZABLE"/> </beans>

以上,即定义了一个常量bean,这个bean的值,就是static-field中指定的,这里是java.sql.Connection#TRANSACTION_SERIALIZABLE,值为8。

/** * A constant indicating that * dirty reads, non-repeatable reads and phantom reads are prevented. * This level includes the prohibitions in * <code>TRANSACTION_REPEATABLE_READ</code> and further prohibits the * situation where one transaction reads all rows that satisfy * a <code>WHERE</code> condition, a second transaction inserts a row that * satisfies that <code>WHERE</code> condition, and the first transaction * rereads for the same condition, retrieving the additional * "phantom" row in the second read. */ int TRANSACTION_SERIALIZABLE = 8;

我们的测试代码如下:

package org.springframework.utilnamespace; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.MyFastJson; import java.util.List; import java.util.Map; @Slf4j public class TestConstant { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:util-namespace-test-constant.xml"},false); context.refresh(); Map<String, Object> map = context.getDefaultListableBeanFactory().getAllSingletonObjectMap(); log.info("singletons:{}", JSONObject.toJSONString(map)); List<BeanDefinition> list = context.getBeanFactory().getBeanDefinitionList(); MyFastJson.printJsonStringForBeanDefinitionList(list); // Object bean = context.getBean("chin.age"); // System.out.println("bean:" + bean); } }

注意,这里,我们没有调用getBean等方法,我们只是简单地,采用json输出了其bean definition,输出如下:

{ "abstract":false, "autowireCandidate":true, "autowireMode":0, // bean的class,好像是个factory,不是个int啊,我们那个bean,按理说,是int类型的 "beanClass":"org.springframework.beans.factory.config.FieldRetrievingFactoryBean", "beanClassName":"org.springframework.beans.factory.config.FieldRetrievingFactoryBean", "constructorArgumentValues":{ "argumentCount":0, "empty":true, "genericArgumentValues":[], "indexedArgumentValues":{} }, "dependencyCheck":0, "enforceDestroyMethod":true, "enforceInitMethod":true, "lazyInit":false, "lenientConstructorResolution":true, "methodOverrides":{ "empty":true, "overrides":[] }, "nonPublicAccessAllowed":true, "primary":false, "propertyValues":{ "converted":false, "empty":false, // 这个是我们给这个常量bean设置的值,被放在了property "propertyValueList":[ { "converted":false, "name":"staticField", "optional":false, "value":"java.sql.Connection.TRANSACTION_SERIALIZABLE" } ] }, "prototype":false, "qualifiers":[], "resolvedAutowireMode":0, "role":0, "scope":"", "singleton":true, "synthetic":false }

我们放开前面注释的两行代码:

Object bean = context.getBean("chin.age"); System.out.println("bean:" + bean);

output:

bean:8

有些同学估计有点蒙了,不要慌,这里简单说下结论,因为被解析为了一个工厂bean,这个在上面json里也看到了,类型为:org.springframework.beans.factory.config.FieldRetrievingFactoryBean。

当我们去getBean的时候,spring发现其为factory bean,就会调用这个工厂bean的工厂方法,去生产。

所以,这里呢,bean是谁?是那个工厂org.springframework.beans.factory.config.FieldRetrievingFactoryBean,而不是这个工厂的产品:数字8。

具体的解析过程 根据namespaceUri获得对应的namespaceHandler

从之前的骨架入手,spring里也有类似的代码:

DefaultBeanDefinitionDocumentReader#parseBeanDefinitions // 这个方法,里面可以看到通过root得到了children,然后对children遍历 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 { // 这里,如果是<util:constant>,因为不是默认命名空间,所以走这里。 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfszg.html