亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring中property-placeholder的使用與解析詳解

2024-07-14 08:40:43
字體:
來源:轉載
供稿:網友

我們在基于spring開發應用的時候,一般都會將數據庫的配置放置在properties文件中.

代碼分析的時候,涉及的知識點概要:

1.NamespaceHandler 解析xml配置文件中的自定義命名空間
2.ContextNamespaceHandler 上下文相關的解析器,這邊定義了具體如何解析property-placeholder的解析器
3.BeanDefinitionParser 解析bean definition的接口
4.BeanFactoryPostProcessor 加載好bean definition后可以對其進行修改
5.PropertySourcesPlaceholderConfigurer 處理bean definition 中的占位符

我們先來看看具體的使用吧

property的使用

在xml文件中配置properties文件

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="  http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.2.xsd">  <context:property-placeholder location="classpath:foo.properties" /></beans>

這樣/src/main/resources/foo.properties文件就會被spring加載

如果想使用多個配置文件,可以添加order字段來進行排序

使用PropertySource注解配置

Spring3.1添加了@PropertySource注解,方便添加property文件到環境.

@Configuration@PropertySource("classpath:foo.properties")public class PropertiesWithJavaConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {  return new PropertySourcesPlaceholderConfigurer(); }}

properties的注入與使用

1.java中使用@Value注解獲取

@Value( "${jdbc.url}" )private String jdbcUrl;

還可以添加一個默認值

@Value( "${jdbc.url:aDefaultUrl}" )private String jdbcUrl;

1.在Spring的xml配置文件中獲取

<bean id="dataSource"> <property name="url" value="${jdbc.url}" /></bean>

源碼解析

properties配置信息的加載

Spring在啟動時會通過AbstractApplicationContext#refresh啟動容器初始化工作,期間會委托loadBeanDefinitions解析xml配置文件.

 protected final void refreshBeanFactory() throws BeansException {  if (hasBeanFactory()) {   destroyBeans();   closeBeanFactory();  }  try {   DefaultListableBeanFactory beanFactory = createBeanFactory();   beanFactory.setSerializationId(getId());   customizeBeanFactory(beanFactory);   loadBeanDefinitions(beanFactory);   synchronized (this.beanFactoryMonitor) {    this.beanFactory = beanFactory;   }  }  catch (IOException ex) {   throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);  } }

loadBeanDefinitions通過層層委托,找到DefaultBeanDefinitionDocumentReader#parseBeanDefinition解析具體的bean

 protected void 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", new PropertyOverrideBeanDefinitionParser());  registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());  registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());  registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());  registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());  registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());  registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); }

PropertyPlaceholderBeanDefinitionParser是這一輪代碼分析的重點.

我們來看看它的父類吧.

1.BeanDefinitionParser

被DefaultBeanDefinitionDocumentReader用于解析個性化的標簽

這邊只定義了一個解析Element的parse api

public interface BeanDefinitionParser {BeanDefinition parse(Element element, ParserContext parserContext);}

2.AbstractBeanDefinitionParser

BeanDefinitionParser接口的默認抽象實現.spring的拿手好戲,這邊提供了很多方便使用的api,并使用模板方法設計模式給子類提供自定義實現的鉤子

我們來看看parse時具體的處理邏輯把: 調用鉤子parseInternal解析

  1. 生成bean id,使用BeanNameGenerator生成,或者直接讀取id屬性
  2. 處理name 與別名aliases
  3. 往容器中注冊bean
  4. 進行事件觸發

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實例化前,修改bean definition的,比如bean definition中的占位符就是這邊解決的,而我們現在使用的properties也是這邊解決的.

這個是通過PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors實現的.
掃描容器中的BeanFactoryPostProcessor,找到了這邊需要的PropertySourcesPlaceholderConfigurer,并通過容器的getBean實例化

protected void 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定義解析流程

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97精品国产97久久久久久| 欧美精品精品精品精品免费| 国产色婷婷国产综合在线理论片a| 亚洲成色www8888| 日韩av不卡在线| 视频在线观看99| 日韩欧美视频一区二区三区| 中文字幕亚洲欧美日韩在线不卡| 亚洲人成欧美中文字幕| 成人xxxx视频| 国产精品久久久久久久久久东京| 国产亚洲激情在线| 91精品国产综合久久香蕉的用户体验| 色777狠狠综合秋免鲁丝| 国产中文字幕亚洲| 欧美精品久久久久久久久久| 亚洲欧美国产日韩天堂区| 欧美日韩国产一区二区三区| 日本免费一区二区三区视频观看| 国产成人精品视| 成人夜晚看av| 亚洲免费福利视频| 欧美日韩激情小视频| 91亚洲人电影| 日韩精品免费在线| 久久久久免费精品国产| 永久免费看mv网站入口亚洲| 国产精品入口福利| 欧美电影在线观看完整版| 亚洲自拍偷拍色图| 欧美日韩久久久久| www.欧美精品| 国产亚洲精品成人av久久ww| 久久精品电影网站| 97在线免费观看视频| 国产精品福利久久久| 亚洲日本成人女熟在线观看| 欧美在线视频免费观看| 成人免费在线网址| 在线播放国产精品| 自拍亚洲一区欧美另类| 亚洲午夜av久久乱码| 久久视频这里只有精品| 97超级碰在线看视频免费在线看| 欧美激情在线有限公司| 日韩av一区二区在线观看| 欧美黑人一区二区三区| 97超级碰碰碰| 日本亚洲欧洲色α| 欧美成人h版在线观看| 亚洲精品ady| 欧美精品在线网站| 97超级碰碰碰久久久| 日韩小视频在线观看| 国产99在线|中文| 欧美日本国产在线| 欧美日韩国产精品一区二区三区四区| 国产一区二区三区高清在线观看| 日韩女优人人人人射在线视频| 亚洲精品久久久久国产| 色综合视频网站| 欧美另类老女人| 2019中文字幕全在线观看| 精品高清美女精品国产区| 久久精品亚洲94久久精品| 日韩一区二区三区在线播放| 国产日韩欧美在线| 美乳少妇欧美精品| 亚洲免费电影在线观看| 91超碰caoporn97人人| 国产精品视频男人的天堂| 亚洲精品456在线播放狼人| 日韩中文有码在线视频| 68精品久久久久久欧美| 91av在线不卡| 精品亚洲一区二区三区四区五区| 色偷偷综合社区| 欧美激情亚洲激情| 亚洲综合精品一区二区| 91免费视频网站| 亚洲精品ady| 欧美乱大交xxxxx| 久国内精品在线| 日韩电影视频免费| 国产在线视频2019最新视频| 91亚洲一区精品| 91精品久久久久久综合乱菊| 精品国内自产拍在线观看| 久久久久久亚洲精品中文字幕| 精品成人在线视频| 国产一区二区三区在线观看视频| 精品视频在线导航| xxxxxxxxx欧美| 国产精品自拍偷拍视频| 久久99视频精品| 91美女福利视频高清| 久久国产精品首页| 久久久久久久久电影| 欧美成人精品一区二区三区| 欧美亚洲国产视频小说| 欧美在线一区二区视频| 51ⅴ精品国产91久久久久久| 成人性生交大片免费看小说| 69av视频在线播放| 青青草99啪国产免费| 热re91久久精品国99热蜜臀| 成人在线精品视频| 成人黄色大片在线免费观看| 亚洲精品国产成人| 国产精品视频免费在线| 川上优av一区二区线观看| 57pao精品| 欧美大胆a视频| 欧美精品激情视频| 正在播放亚洲1区| 久久久久久久成人| 992tv在线成人免费观看| 亚洲美女在线视频| 久久久久久久久国产精品| 国产成人精品日本亚洲专区61| 欧美日韩裸体免费视频| 裸体女人亚洲精品一区| 91精品国产自产在线观看永久| 欧美亚洲日本网站| 国产一区二区激情| 国产精品久久久久久久一区探花| 亚洲美女久久久| 成人天堂噜噜噜| 日韩av在线直播| 亚洲黄色av女优在线观看| 日韩av在线一区二区| 国产精品老女人视频| 国产精品一区二区性色av| 国产999精品久久久影片官网| 4k岛国日韩精品**专区| 欧美老少做受xxxx高潮| 97热精品视频官网| 国产拍精品一二三| 国产一区二区三区在线| 久久精品成人欧美大片古装| 久久久久久久999精品视频| 欧美高清电影在线看| 精品一区二区三区四区| 亚洲精品自在久久| 国产原创欧美精品| 亚洲午夜色婷婷在线| 国产精品91免费在线| 欧美日本啪啪无遮挡网站| 一区二区欧美激情| 欧美成人免费一级人片100| 欧美裸体男粗大视频在线观看| 亚洲成人黄色网| 5566日本婷婷色中文字幕97| 午夜美女久久久久爽久久| 成人福利免费观看| 亚洲男人天堂网站| 日韩欧美在线视频免费观看| 欧美日韩国产一中文字不卡| 欧美精品www在线观看| 亚洲国产成人在线播放| 91成人福利在线| 亚洲欧美一区二区三区久久| 亚洲sss综合天堂久久| 不卡av电影在线观看|