激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring中property-placeholder的使用與解析詳解

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

2021-04-27 13:24出門向左 Java教程

本篇文章主要介紹了Spring中property-placeholder的使用與解析詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

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

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

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

property的使用

在xml文件中配置properties文件

?
1
2
3
4
5
6
7
8
9
10
11
12
<?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文件到環境.

?
1
2
3
4
5
6
7
8
@configuration
@propertysource("classpath:foo.properties")
public class propertieswithjavaconfig {
 @bean
 public static propertysourcesplaceholderconfigurer propertysourcesplaceholderconfigurer() {
  return new propertysourcesplaceholderconfigurer();
 }
}

properties的注入與使用

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

?
1
2
@value( "${jdbc.url}" )
private string jdbcurl;

還可以添加一個默認值

?
1
2
@value( "${jdbc.url:adefaulturl}" )
private string jdbcurl;

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

?
1
2
3
<bean id="datasource">
 <property name="url" value="${jdbc.url}" />
</bean>

源碼解析

properties配置信息的加載

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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解析器解析

?
1
2
3
4
5
6
7
8
9
10
11
12
@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

?
1
2
3
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實例化

?
1
2
3
protected void invokebeanfactorypostprocessors(configurablelistablebeanfactory beanfactory) {
  postprocessorregistrationdelegate.invokebeanfactorypostprocessors(beanfactory, getbeanfactorypostprocessors());
 }

propertysourcesplaceholderconfigurer實例化完成后,就直接進行觸發,并加載信息

?
1
2
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定義解析流程

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.cnblogs.com/leftthen/p/5615066.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: av之家在线观看 | 久久精品视频69 | 免费毛片播放 | 免费永久看羞羞片网站入口 | 欧美中文日韩 | 黄色的视频免费观看 | 欧美成人高清视频 | 一本色道精品久久一区二区三区 | 国产男人的天堂 | 免费看日产一区二区三区 | av免费av| 成人男女免费视频 | 在线播放视频一区二区 | 在线观看国产一区二区 | 国产精品视频亚洲 | 中国久久久 | 性生大片免费观看一片黄动漫 | 日本一区二区免费在线观看 | 久久国产精品影视 | 国产一区二区亚洲 | 96视频在线免费观看 | 999久久久精品 | 久久777国产线看观看精品 | 国产在线色| 性大片性大片免费 | 午夜精品网站 | 亚洲一区在线免费视频 | 国产正在播放 | 国产有色视频 | av日韩一区二区三区 | 免费国产精品视频 | 日韩精品dvd | 久久精品高清 | 久久精品探花 | 成人久久久久久久久久 | 日日夜av | 色婷婷久久久亚洲一区二区三区 | 黄色免费小视频网站 | 在线无码 | 成人精品视频网站 | 91性高湖久久久久久久久网站 |