spring为解析xml创建bean提供了一种非常解藕的方式。
整体架构面向接口编程,AbstractApplicationContext的refresh方法被调用时,在刷新BeanFactory的时候会解析配置文件。框架提供了:
接口 org.springframework.beans.factory.xml.NamespaceHandler;
抽象实现类 org.springframework.beans.factory.xml.NamespaceHandlerSupport;
以及
org.springframework.beans.factory.xml.BeanDefinitionParser;
org.springframework.beans.factory.xml.BeanDefinitionDecorator;
接口去完成xml解析的解藕。
用法:
1,创建抽象类NamespaceHandlerSupport的实现类。子类实现init方法,方法内部调用NamespaceHandlerSupport抽象父类的注册方法:
registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser);
registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec);
registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec);
2, 从以上方法可以看出我们还需要提供BeanDefinitionParser、BeanDefinitionDecorator接口的实现。这二个接口是解析xml的具体实现描述,因此需要提供这些接口的实现类。
BeanDefinitionParser接口提供方法:
BeanDefinition parse(Element element, ParserContext parserContext);
生成非代理bean时,采用这个解析器接口。
BeanDefinitionDecorator接口提供方法:
BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext);
生成代理bean时,采用这个解析器接口。
接口实现主要做的事情:往bean元信息对象添加属性。bean元信息,spring提供 GenericBeanDefinition、ChildBeanDefinition、RootBeanDefinition三个类去描述bean的信息。属性值由xml配置文件中获取。
另外,spring提供了BeanDefinitionBuilder类,方便创建上诉三个不同bean定义对象。
3,按照上面的步骤代码层面已经实现了,还存在一个问题,怎么让spring框架去找到NamespaceHandler的实现类呢?
spring提供了DefaultNamespaceHandlerResolver,这个类会默认加载所有依赖jar里面的META-INF/spring.handlers属性文件。
此文件配置内容为健值对形式。键为xml配置文件中根节点的 “xsi:schemaLocation” 属性的值。值为NamespaceHandler实现类的全路径名。
因此需要我们按照这种形式创建文件。