Spring中的NamespaceHandler与BeanDefinitionParser详解
作者:thewindkee
1.前文
由Spring启动过程之-obtainFreshBeanFactory()
可以看到NamespaceHandler、BeanDefinitionParser为解析配置文件中的Element起重要作用。
那么它本身是如何被加载的呢?
2.NamespaceHandler之ContextNamespaceHandler
常见的NamespaceHandler实例:ContextNamespaceHandler
很明显能看出有常用的 context:annotation-config/、<context:component-scan base-package=“xx”/>、context:property-placeholder/对应的解析类。
3.BeanDefinitionParser的作用
解析相关节点,并注册BeanDefinition。
3.1 PropertyPlaceholderBeanDefinitionParser
大致流程为解析<context:property-placeholder location="classpath:module.properties" />节点,包装PropertySourcesPlaceholderConfigurer为BeanDefinition,将里面的属性装配到BeanDefinition中,并注册到BeanDefinitionMap。
PropertyPlaceholderBeanDefinitionParser#parse: AbstractBeanDefinitionParser-> parseInternal-> BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();//创建BeanDefinition ... builder.getRawBeanDefinition().setBeanClass(PropertySourcesPlaceholderConfigurer.class); ... doParse(element, parserContext, builder)-> super.doParse(element, parserContext, builder);//解析公共属性:location,fileEncoding等 ....//做特殊属性的解析 return builder.getBeanDefinition(); //统一注册 registerBeanDefinition(holder, parserContext.getRegistry());
3.2 ComponentScanBeanDefinitionParser
解析节点<context:component-scan base-package="com.gkwind"/>本身。并根据其配置,做特殊的class扫描,将符合配置的class,如被@Component标记过的类 包装成BeanDefinition,注入到BeanDefinitionMap中。 注意这里做的工作是根据配置,扫描加载了配置对应的多个类
ComponentScanBeanDefinitionParser#parse流程
NamespaceHandler 加载过程
跟踪源码, 可以发现解析非自定义命名空间parseCustomElement时会调用DefaultNamespaceHandlerResolver#resolve,然后resolve得到的所有NamespaceHandler。之后得到命名空间对应的NamespaceHandler 再NamespaceHandler#init初始化相关的parser。
getHandlerMappings以SPI的方式得到所有spring.handlers
NamespaceHandler 加载流程
作用:可实现自定义标签
知道了NamespaceHandler与BeanDefinitionParser作用后, 我们可以自定义schema,然后在spring的xml中自定义命名空间thewindkee标签<thewindkeetag>,再实现thewindkee对应的NamespaceHandler与<thewindkeetag>的BeanDefinitionParser,最后将NamespaceHandler配置到META-INF/spring.handlers。
大致Java代码:
class TheWindKeeNamespaceHandler extends NamespaceHandlerSupport { public void init(){ registerBeanDefinitionParser("thewindkeetag", new TheWindKeeTagBeanDefinitionParser()); } } class TheWindKeeTagBeanDefinitionParser extends AbstractBeanDefinitionParser{ public final BeanDefinition parse(Element element, ParserContext parserContext) { //解析element .... //注册BeanDefinition registerBeanDefinition(holder, parserContext.getRegistry()); } }
到此这篇关于Spring中的NamespaceHandler与BeanDefinitionParser详解的文章就介绍到这了,更多相关NamespaceHandler与BeanDefinitionParser内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!