一 自定义标签范例
1.实现自己的注解xsd
<xsd:schema
xmlns=“http://blog.youkuaiyun.com/cutesource/schema/people”
xmlns:xsd=“http://www.w3.org/2001/XMLSchema”
xmlns:beans=“http://www.springframework.org/schema/beans”
targetNamespace=“http://blog.youkuaiyun.com/cutesource/schema/people”
elementFormDefault=“qualified”
attributeFormDefault=“unqualified”>
<xsd:import namespace=“http://www.springframework.org/schema/beans” />
<xsd:element name=“people”>
xsd:complexType
xsd:complexContent
<xsd:extension base=“beans:identifiedType”>
<xsd:attribute name=“name” type=“xsd:string” />
<xsd:attribute name=“age” type=“xsd:int” />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
2.定义META-INF/spring.schemas 配置文件
http://blog.youkuaiyun.com/cutesource/schema/people.xsd=META-INF/people.xsd
3.定义META-INF/spring.handlers 配置处理类
http://blog.youkuaiyun.com/cutesource/schema/people=com.study.mike.spring.ext.TestNamespanceHandler
4.实现处理类,这里并没有真正处理,而是委托给TestElementParser解析
package com.study.mike.spring.ext;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class TestNamespanceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
System.out.println("init ");
registerBeanDefinitionParser("people",new TestElementParser());
}
}
5. 实现解析类
package com.study.mike.spring.ext;
import com.study.mike.spring.test.Test;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
public class TestElementParser extends AbstractSingleBeanDefinitionParser {
protected void doParse(Element element, BeanDefinitionBuilder builder) {
builder.getBeanDefinition().setBeanClass(Test.class);
String id = element.getAttribute("id");
builder.addPropertyValue("id",id);
}
}
6 测试类
package com.study.mike.spring.test;
public class Test {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
ApplicationContext context = new ClassPathXmlApplicationContext(“application.xml”);
二 原理解析
在这里我们从XmlBeanDefinitionReader开始解读。要完成这件事,spring需要完成什么呢!
从代码上看,我们需要完成解析xml文件,将Document解析成BeanDefinition并注册。
从xml文件上我们可以获取到地址。
在这里我们可以设置本地的sxd的地址,那代码是如何做到的
从这里是XmlBeanDefinitionReader,我们可以看到了,一个是解析xml,一个是注册beanDefine,并持有了一个xml 解读器
1 .解析xml分析,
可以看到这个接口最重要的是实体解析器EntityResolver。
XmlBeanDefinitionReader拿到了PluggableSchemaResolver schema解析器
这里配置了配置文件的地方
接下来开始执行了解析,获取到配置键值对,从而找到了我我们自己设置的xsd文件。
如何获取到这个键值对呢,这里使用了双重检查,保证只生成一个mapping
有了这些数据,就可以将xml文件解析成Document,
接下来就开始执行解析到bean定义的工作
这里有解析自定义组件的方法
在这里,获取到了自定义标签的名称空间,使用动态工厂模式创建出一个解析器
这里是如何工作的呢、从XmlBeanDefinitionReader开始解读,提供了一个默认的NamespaceHandlerResolver控制器,
可以看到,这个处理器带着配置文件的地址。
这里和xml解析类时,也是获取到这个路劲下的配置文件,获取到指定的处理器,这种设计可以达到动态的增加组件,而不需要修改代码。
到了这里,我们就获取到处理类。并基于自定义的名称获取到自定义的一个解析器,没有就使用默认的。
在使用解析器解析时,采用父类定义了模板的方法,执行了注册的功能,而解析的操作由子类实现,到这里就注册完成了