随着春天引导的日渐流行,应用里的大部分配置都被隐藏了起来,我们仅需要关心真正的业务内容,控制器,服务存储库,拿起键盘就是一通业务代码的编码,具体的组件扫描,看来,占位符……都可以抛在脑后。但其实这种零配置在Java应用开发中,还真不太久。“由奢入俭难”,不少开发者都经历过Spring XML配置的冗长,再回到这种配置确实不好受。
但有些时候,由于配置的内容在春天引导这种零配置中并不能很好的实现,就需要我们仍使用XML的配置形式,然后再ImportSource进来。或者一些项目受环境等影响,未使用引导进行开发,此时也需要对配置有一定的了解。
那这次让我们往回看一些,看看在XML配置中,一些自定义的模式内容,是如何融合到Spring中进行配置的,例如:
春数据es
还有许多这样的例子,我们不再一一罗列。但通过上述两个图,我们发现一个共同的特点:
-
<李>都是通过schemaLocation将对应的模式引入李>
<李>在对应的豆元素中增加更具体的自定义配置李>
那这些自定义的配置,是在什么时候工作的呢& # 63;如何校验是否配置正确& # 63;
我们来看春天中包含一个名为春天。处理程序的文件,所有的自定义扩展,都是通过这个文件生效的.spring官方的aop, tx也都是这个原理。
这个文件在哪呢& # 63;
如上图所示,是meta - inf/spring。处理程序。文件内容也超级简单:
http \://www.springframework.org/schema/data/elasticsearch=org.springframework.data.elasticsearch.config.ElasticsearchNamespaceHandler
前面是各个模式前缀,后面是模式对应的解析类。这个spring.handlers文件是什么时候加载的呢& # 63;
这个也是发生在解析自定义配置文件过程中,有一个解决的过程,此时会将当前类加载器对应的所有包含春。处理程序文件加载过来。
我们再来看这个解析类,内容如下:
公开课ElasticsearchNamespaceHandler延伸NamespaceHandlerSupport { 公共ElasticsearchNamespaceHandler () { } 公共空间init () { RepositoryConfigurationExtension扩展=new ElasticsearchRepositoryConfigExtension (); RepositoryBeanDefinitionParser解析器=new RepositoryBeanDefinitionParser(扩展); 这一点。registerBeanDefinitionParser(“存储库”,解析器); 这一点。registerBeanDefinitionParser (“node-client”,新的NodeClientBeanDefinitionParser ()); 这一点。registerBeanDefinitionParser (“transport-client”,新的TransportClientBeanDefinitionParser ()); } }
首先是继承自NamesapceHandlerSupport
然后在重写的初始化方法中注册了一系列的解析器,每个解析器对应一个字符串,就是我们在xml配置文件是使用的自定义内容,比如上面的es的配置
& lt; elasticsearch: transport-client id=翱突Ф恕? 集群集群节点=" 192.168.73.186:9300 "
这里的配置最终就会通过TransportClientBeanDefinitionParser来进行解析
而上面提到的各个解析器,在初始化方法中,保存在了一个地图中
私人最终Map<字符串,BeanDefinitionParser>解析器=new HashMap ();>之前所谓注册解析器,就是在向这个解析器的映射进行把操作。
那回过头来,在春天中,最核心的内容是什么呢& # 63;是Bean。而实际上我们配置到XML里的这些内容,最终也会生在一个对应的Bean,所有的配置,只是为了生成Bean,这些自定义的配置,都称之为BeanDefinition。
所以,春天在解析配置文件是,会有如下的判断,是否是defaultNamespace,不是的话就走customElementParse
保护无效parseBeanDefinitions(根元素,BeanDefinitionParserDelegate委托){ 如果(delegate.isDefaultNamespace(根)){ 节点列表问=root.getChildNodes (); for (int i=0;我& lt;nl.getLength ();+ + i) { 节点的节点=nl.item(我); 如果(节点实例元素){ 元素避署=(元素)节点; 如果(delegate.isDefaultNamespace(避署)){ 这一点。parseDefaultElement(避署,委托); 其他}{ delegate.parseCustomElement(避署); } } } 其他}{ delegate.parseCustomElement(根); } }春天中自定义模式如何解析生效详解