自定义配置文件到spring 中,有时候想做一些数据结构的配置化信息,根据业务做一个扩展。
首先:
在项目的META-INF目录下新建两个文件spring.handlers,和spring.shcemas
Spring.handlers在类org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver中已经写死了要取mapping的handlerMappingsLocation的路径
public static finalString DEFAULT_HANDLER_MAPPINGS_LOCATION ="META-INF/spring.handlers";
Spring.Schemas 在org.springframework.beans.factory.xml.PluggableSchemaResolver这个类中
同样写死了位置
public static finalString DEFAULT_SCHEMA_MAPPINGS_LOCATION = "META-INF/spring.schemas";
初始化的时候第一次调用的时候会调用
PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation,this.classLoader)
把所有的文件名包含的取出来放入map中。
spring.handlers内容:
http\://www.ruishenh.com/custom/mytest=com.ruishenh.spring.config.MyNamespaceHandler
spring.schemas内容:
http\://www.ruishenh.com/custom/mytest/myTest.xsd=customTag/myTest.xsd
customTag/myTest.xsd文件:
spring/myTest.xml文件:
com.ruishenh.spring.config.MyNamespaceHandler 命名空间处理类:
package com.ruishenh.spring.config;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport{
@Override
public void init() {
registerBeanDefinitionParser("executor",newMyBeanDefinitionParser(MyExecutor.class));
registerBeanDefinitionParser("entity",newMyBeanDefinitionParser(MyEntity.class));
}
}
这个类主要是在DefaultNamespaceHandlerResolver这个类中getHandlerMappings()取到了所有的META-INF/spring.handlers的文件内容存入map,然后根据当前的命名空间找到对应的NamespaceHandler,然后反射出对象调用init()
Class> handlerClass =ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)){
throw new FatalBeanException("Class ["+ className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
NamespaceHandlernamespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
namespaceHandler.init();
com.ruishenh.spring.config.MyBeanDefinitionParser解析类:
packagecom.ruishenh.spring.config;
importorg.springframework.beans.factory.config.BeanDefinition;
importorg.springframework.beans.factory.config.RuntimeBeanReference;
importorg.springframework.beans.factory.support.RootBeanDefinition;
importorg.springframework.beans.factory.xml.BeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Element;
importorg.w3c.dom.NamedNodeMap;
importorg.w3c.dom.Node;
public classMyBeanDefinitionParser implements BeanDefinitionParser {
private Class> clssze;
publicMyBeanDefinitionParser(Class> cls) {
this.clssze = cls;
}
@Override
public BeanDefinition parse(Elementelement, ParserContext parserContext) {
RootBeanDefinitionbeanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(clssze);
String id = null;
id =element.getAttribute("name");
if (id == null) {
if (clssze ==MyExecutor.class) {
id = "test_myExecutor";
} else if (clssze ==MyEntity.class) {
id ="test_myentity";
} else {
throw newIllegalStateException("MyBeanDefinitionParser.parse,未知的业务逻辑处理:class:" +element.getAttribute("class"));
}
}
int counter = 2;
while(parserContext.getRegistry().containsBeanDefinition(id)) {
id = id +(counter++);
}
if (id != null &&id.length() > 0) {
if(parserContext.getRegistry().containsBeanDefinition(id)) {
throw newIllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id,beanDefinition);
}
NamedNodeMap nnm =element.getAttributes();
for (int i = 0; i
这个类会在
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Elementroot, BeanDefinitionParserDelegate delegate)这个方法中入口执行
然后到org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(Elementelement, ParserContext parserContext);
最后找到对应的BeanDefinitionParser执行parse方法。至于放入BeanDefinitionParser的入口就在自定义的NamespaceHandler中init()方法中。
com/ruishenh/spring/config/MyEntity.java实体类:
package com.ruishenh.spring.config;
import com.ruishenh.model.BaseModel;
public classMyEntity extendsBaseModel{
private int dbTypeID;
private String dbTypeName;
private String splitBy;
private String sql;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSplitBy() {
return splitBy;
}
public void setSplitBy(StringsplitBy) {
this.splitBy = splitBy;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
public int getDbTypeID() {
return dbTypeID;
}
public void setDbTypeID(int dbTypeID) {
this.dbTypeID = dbTypeID;
}
public String getDbTypeName(){
return dbTypeName;
}
public void setDbTypeName(StringdbTypeName) {
this.dbTypeName = dbTypeName;
}
}
com/ruishenh/spring/config/MyExecutor.java实体类:
package com.ruishenh.spring.config;
import com.ruishenh.model.BaseModel;
public classMyExecutor extends BaseModel{
private String name;
private int delay;
private int interval;
private String address;
private MyEntity entity;
public MyEntity getEntity() {
return entity;
}
public void setEntity(MyEntity entity) {
this.entity = entity;
}
public int getDelay() {
return delay;
}
public void setDelay(int delay) {
this.delay = delay;
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public String getAddress() {
return address;
}
public void setAddress(Stringaddress) {
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试类:
package com.ruishenh.spring.test;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.ruishenh.spring.config.MyEntity;
import com.ruishenh.spring.config.MyExecutor;
public classTest {
public static void main(String[] args) {
Stringconf = "classpath:spring/myTest.xml";
FileSystemXmlApplicationContextac = newFileSystemXmlApplicationContext(conf);
MyExecutorme = ac.getBean(MyExecutor.class);
System.out.println(me.toString());
MyEntity mye = ac.getBean(MyEntity.class);
System.out.println(mye.toString());
}
}
运行结果:
MyExecutor[name=myexecutor,delay=2000,interval=5000,address=127.0.0.1,entity=MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]]
MyEntity[dbTypeID=1,dbTypeName=mysql,splitBy=id,sql=1,name=mye]