什么是Spring的占位符?
在以前的Spring Xml配置中我们可能会有如下配置:
1 | java复制代码<?xml version="1.0" encoding="UTF-8"?> |
在上面的配置中jdbc这个Bean的url属性值${jdbc.url}就代表占位符,占位符的真实值就存放在上述配置中的context:property-placeholder自定义元素的location属性所代表的配置文件jdbc.properties中,这个配置文件里就一行内容:
1 | ini复制代码jdbc.url=127.0.0.1 |
那问题就来了,Spring又是在什么阶段去解析并且把占位符替换为实际值的呢?
Spring什么时候去解析并占位符
从context:place-holder我们就可以知道它是一个自定义xml标签,那Spring势必要解析它,我就直接黏贴Spring解析这个自定义元素的入口代码给各位看官。该代码就在BeanDefinitionParserDelegate这个类中:
1 | java复制代码/** |
主要关注点:
delegate.parseCustomElement(ele);
1 | java复制代码 @Nullable |
到这里我们又要关注这个NamespaceHandler是怎么获取到的,从上面代码可知,Spring会从当前readerContext获取到NamespaceHandlerResolver后通过其resolve方法并根据传入的当前namespaceUri就可以获得当前适合的NamespaceHandler。
1 | java复制代码/** |
从上面的代码中可知Spring使用的是默认的DefaultNamespaceHandlerResolver,它当然也给开发者留了自定义NamespaceHandlerResolver的机会。那我们现在就可以看看DefaultNamespaceHandlerResolver如何根据namespaceUri解析到对应的NamespaceHandler的。
首先context:place-holder获取到的就是context命名空间,完整路径为http://www.springframework.org/schema/context。我们从DefaultNamespaceHandlerResolver类中可以看到它是如何解析这个命名空间的。
1 | java复制代码/** |
上面代码中的handlerMappingsLocation一般就是Spring默认的路径:
1 | java复制代码 //指定了默认的handler路径 ,可以传入指定路径改变 |
我们就回到spring-context项目工程下的resoures/META-INF文件夹下的spring.handlers文件里定义了如下规则:
1 | ruby复制代码http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler |
可以看到context自定义命名空间就是对应的ContextNamespaceHandler。我们打开这个类瞧一瞧:
1 | java复制代码public class ContextNamespaceHandler extends NamespaceHandlerSupport { |
发现它只定义了一个init方法,顾名思义就是初始化的意思,那想当然的就是它啥时候会执行初始化呢?我们回到DefaultNamespaceHandler的resolve方法,发现它内部有一处**namespaceHandler.init();, **这里就执行了对应命名空间处理器的初始化方法。接下来我们又要看看初始化了做了些啥,我们发现它调用了同一个方法registerBeanDefinitionParser也就是注册Bean定义解析器,到这里我们先按下暂停键,再捋下上面的整体流程:
- Spring在解析自定义标签的时候会根据自定义命名空间去查找合适的NamespaceHandler.
- 自定义的NamespaceHandler是由NamespaceHandlerResolver去解析得到的。
- NamespaceHandlerResolver会根据classLoader.getResources查找所有类路径下的spring.handlers。
- 查找到后把文件内容转换成handlerMappings,然后根据传入的自定义命名空间匹配到NamespaceHandler
- 执行NamespaceHandler的init方法注册BeanDefinitionParser。
那这个parser做了点什么强大的功能呢?我们下回分解。
本文转载自: 掘金