property-placeholder源码解析

46 篇文章 0 订阅
18 篇文章 2 订阅

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定义解析流程

关注微信公众号和今日头条,精彩文章持续更新中。。。。。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值