property-placeholder源码解析
properties配置信息的加载
Spring在启动时会通过AbstractApplicationContext#refresh启动容器初始化工作,期间会委托loadBeanDefinitions解析xml配置文件.
protectedfinal void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactorybeanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw newApplicationContextException("I/O error parsing bean definition source for" + getDisplayName(), ex);
}
}
loadBeanDefinitions通过层层委托,找到DefaultBeanDefinitionDocumentReader#parseBeanDefinition解析具体的bean
protectedvoid parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate){
if (delegate.isDefaultNamespace(root)){
NodeList nl = root.getChildNodes();
for (int i = 0; i <nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if(delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
这边由于不是标准类定义,所以委托BeanDefinitionParserDelegate解析
通过NamespaceHandler查找到对应的处理器是ContextNamespaceHandler,再通过id找到PropertyPlaceholderBeanDefinitionParser解析器解析
@Override
public void init() {
// 这就是我们要找的解析器
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", newPropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", newAnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan",new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", newLoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", newMBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", newMBeanServerBeanDefinitionParser());
}
PropertyPlaceholderBeanDefinitionParser是这一轮代码分析的重点.
我们来看看它的父类吧.
1、BeanDefinitionParser
被DefaultBeanDefinitionDocumentReader用于解析个性化的标签
这边只定义了一个解析Element的parse api
public interface BeanDefinitionParser {
BeanDefinitionparse(Element element, ParserContext parserContext);
}
2、AbstractBeanDefinitionParser
BeanDefinitionParser接口的默认抽象实现.spring的拿手好戏,这边提供了很多方便使用的api,并使用模板方法设计模式给子类提供自定义实现的钩子
我们来看看parse时具体的处理逻辑把:
Ø 调用钩子parseInternal解析
Ø 生成bean id,使用BeanNameGenerator生成,或者直接读取id属性
Ø 处理name 与别名aliases
Ø 往容器中注册bean
Ø 进行事件触发
3、AbstractSingleBeanDefinitionParser
解析,定义单个BeanDefinition的抽象父类
在parseInternal中,解析出parentName,beanClass,source;并使用BeanDefinitionBuilder进行封装
4、AbstractPropertyLoadingBeanDefinitionParser
解析property相关的属性,如location,properties-ref,file-encoding,order等
5、PropertyPlaceholderBeanDefinitionParser
这边处理的事情不多,就是设置ingore-unresolvable和system-properties-mode
properties文件的加载,bean的实例化
接下来,我们再看看这个bean是在什么时候实例化的,一般类的实例化有2种,一种是单例系统启动就实例化;一种是非单例(或者单例懒加载)在getBean时实例化.
这边的触发却是通过BeanFcatoryPostProcessor.
BeanFactoryPostProcessor是在bean实例化前,修改beandefinition的,比如bean definition中的占位符就是这边解决的,而我们现在使用的properties也是这边解决的.
这个是通过PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors实现的.
扫描容器中的BeanFactoryPostProcessor,找到了这边需要的PropertySourcesPlaceholderConfigurer,并通过容器的getBean实例化
protectedvoid invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,getBeanFactoryPostProcessors());
}
PropertySourcesPlaceholderConfigurer实例化完成后,就直接进行触发,并加载信息
OrderComparator.sort(priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors,beanFactory);
我们再来看看PropertySourcesPlaceholderConfigurer的继承体系把
1、BeanFactoryPostProcessor
定义一个用于修改容器中bean definition的属性的接口.其实现类在一般类使用前先实例化,并对其他类的属性进行修改.
这跟BeanPostProcessor有明显的区别,BeanPostProcessor是修改bean实例的.
2、PropertiesLoaderSupport
加载properties文件的抽象类.
这边具体的加载逻辑是委托PropertiesLoaderUtils#fillProperties实现
3、PropertyResourceConfigurer
bean definition中占位符的替换就是这个抽象类实现的.
实现BeanFactoryPostProcessor#postProcessBeanFactory,迭代容器的中的类定义,进行修改
具体如何修改就通过钩子processProperties交由子类实现
4、PlaceholderConfigurerSupport
使用visitor设计模式,通过BeanDefinitionVisitor和StringValueResolver更新属性
StringValueResolver是一个转化String类型数据的接口,真正更新属性的api实现竟然是在PropertyPlaceholderHelper#parseStringValue
5、PropertySourcesPlaceholderConfigurer
覆写postProcessorBeanFactory api定义解析流程
关注微信公众号和今日头条,精彩文章持续更新中。。。。。