自定义标签配置步骤
- 创建一个需要扩展的组件。
- 定义一个xsd文件描述组件内容。
- 创建一个文件,实现BeanDefinitionParser接口,用来解析xsd文件中的定义和组件定义。
- 创建一个handle文件,扩展自NamespaceHandlerSupport,目的是将组件注册到spring容器。
- 编写spring.handlers和spring.schemas文件,这两个文件的存放位置默认在工程的/META-INF/文件夹下。
Demo
创建接收配置的POJO
1 | public class RpcService implements Serializable{ |
1 | public class UserInfoService { |
元素的XSD文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
Handler处理
1 | public class RpcServiceNamespaceHandler extends NamespaceHandlerSupport { |
BeanDefinitionParser
1 | public class RpcServicePublishBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { |
spring.handlers和spring.schemals
spring.handlers
1 | http\://www.qbb.com/schema/qbb=qbb.rpc.RpcServiceNamespaceHandler1 |
spring.schemals
1 | http\://www.qbb.com/schema/qbb.xsd=META-INF/qbb-rpc.xsd1 |
注意这2个文件要放在META-INF下,要不把上面这些都打jar,要不META-INF放到class目录去,否则找不到。
Test
1 | <?xml version="1.0" encoding="UTF-8"?> |
注意添加,我的是Intellij,eclipse应该也有地方添加:
Intellij:
1 | public class MyBeanTest { |
自定义标签解析时序图
"源码解析
之前看beanfactory的解析的时候,解析标签的时候,会区分是默认的namespaces还是自定义的:
1 | //DefaultBeanDefinitionDocumentReader |
还是委托BeanDefinitionParserDelegate处理:
1 |
|
getNamespaceHandlerResolver()-resolve
1 | //DefaultNamespaceHandlerResolver |
到这里获取到处理自定义标签的NamespaceHandler。
NamespaceHandler-parse
1 | //NamespaceHandlerSupport |
看下BeanDefinition的parser方法:
1 | //AbstractBeanDefinitionParser |
上面Demo里面我们继承的是AbstractSingleBeanDefinitionParser,提供了进一步的封装:
1 | //AbstractSingleBeanDefinitionParser |
最主要的还是工具类BeanDefinitionBuilder利用Builder模式封装了BeanDefinition,提供了简单设置构造方法、属性的方法。
应用
- AOP标签(AOPNamespaceHandler)
总结
- 自定义的标签的扩展还是挺牛,看到好多地方用到,例如:通过自定义实现rpc的服务发现注册到zk;
- NamespaceHandler的init方法不一定要注册BeanDefinitionParser,可以注册个bean到spring里面,可以继承实现实例化前、实例化后、初始化前、初始化后处理器的方法,来拦截其他的bean注册,Aop就是这么处理的,当时看的时候还挺疑惑的,还感觉怎么不按常理出牌。