1、总体思路:
1.1) 编写标签schema
1.2) 添加文件spring.schemas和spring.handlers(目录固定在classpath:/META-INF下,被依赖代码必须打成一个jar包)
1.3) 编写一堆handler。
2、详细说明
自定义的标签一定有属于自己的namespace,所以要有个namespaceHandler(继承NamespaceHandlerSupport),这个handler的作用就是注册自定义标签的parser,且该handler的全称必须写在spring.handlers里。
自定义标签也需要引入namespace,这个namespace全称及schema文件所在路径就写在spring.schemas文件里(与文件spring.handlers同目录)。
自定义的每一种标签都对应一个parser(实现接口BeanDefinitionParser)和beanClass。parser就是从xml的element中抽取相关信息,生成一个BeanDefinition(如GenericBeanDefinition)实例definition,并将beanClass、beanName和propertyValue赋给definition,最后将definition注册到ParserContext里。
beanName可以调用spring提供的id生成器
String beanName = BeanDefinitionReaderUtils.generateBeanName(definition, parserContext.getRegistry());
这里的propertyValue是用来给新new的beanClass的成员字段赋值用的。propertyValue是一个List,List中每个成员(key是成员字段名,value是成员字段值类型此处是Object)都对应beanClass的一个成员字段。
这里的beanClass可以实现FactoryBean或InitializingBean来生成个性化的bean。
FactoryBean有个接口public T getObject(){},spring在实例化完一个bean之后,判断下该bean是否实现了FactoryBean接口,如果实现了,那么调用下getObject()接口,以返回值作为真正的bean实例。
InitializingBean有个接口public void afterPropertiesSet(),spring在new一个bean对象,并且完成该对象的成员字段的赋值后,调用下该接口(注意getObject是在该接口之后才调用)。
3、使用自定义的xml标签
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sg="http://code.sample.com/schema/sg"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.sample.com/schema/sg
http://code.sample.com/schema/sg/sg.xsd">
<sg:property-placeholder location="classpath*:conf/sample.properties"/>
<sg:application container-id="${sample.container.id}" container-port="${sample.container.default.port}"
register-http="${sample.g