欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2018年05月08日 15:30:56   作者:出門向左  
本篇文章主要介紹了Spring中property-placeholder的使用與解析詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

我們?cè)诨趕pring開(kāi)發(fā)應(yīng)用的時(shí)候,一般都會(huì)將數(shù)據(jù)庫(kù)的配置放置在properties文件中.

代碼分析的時(shí)候,涉及的知識(shí)點(diǎn)概要:

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

我們先來(lái)看看具體的使用吧

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文件就會(huì)被spring加載

如果想使用多個(gè)配置文件,可以添加order字段來(lái)進(jìn)行排序

使用PropertySource注解配置

Spring3.1添加了@PropertySource注解,方便添加property文件到環(huán)境.

@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;

還可以添加一個(gè)默認(rèn)值

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

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

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

源碼解析

properties配置信息的加載

Spring在啟動(dòng)時(shí)會(huì)通過(guò)AbstractApplicationContext#refresh啟動(dòng)容器初始化工作,期間會(huì)委托l(wèi)oadBeanDefinitions解析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通過(guò)層層委托,找到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);
  }
 }

這邊由于不是標(biāo)準(zhǔn)類定義,所以委托BeanDefinitionParserDelegate解析

通過(guò)NamespaceHandler查找到對(duì)應(yīng)的處理器是ContextNamespaceHandler,再通過(guò)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是這一輪代碼分析的重點(diǎn).

我們來(lái)看看它的父類吧.

1.BeanDefinitionParser

被DefaultBeanDefinitionDocumentReader用于解析個(gè)性化的標(biāo)簽

這邊只定義了一個(gè)解析Element的parse api

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

2.AbstractBeanDefinitionParser

BeanDefinitionParser接口的默認(rèn)抽象實(shí)現(xiàn).spring的拿手好戲,這邊提供了很多方便使用的api,并使用模板方法設(shè)計(jì)模式給子類提供自定義實(shí)現(xiàn)的鉤子

我們來(lái)看看parse時(shí)具體的處理邏輯把: 調(diào)用鉤子parseInternal解析

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

3.AbstractSingleBeanDefinitionParser

解析,定義單個(gè)BeanDefinition的抽象父類

在parseInternal中,解析出parentName,beanClass,source;并使用BeanDefinitionBuilder進(jìn)行封裝

4.AbstractPropertyLoadingBeanDefinitionParser

解析property相關(guān)的屬性,如location,properties-ref,file-encoding,order等

5.PropertyPlaceholderBeanDefinitionParser

這邊處理的事情不多,就是設(shè)置ingore-unresolvable和system-properties-mode

properties文件的加載,bean的實(shí)例化

接下來(lái),我們?cè)倏纯催@個(gè)bean是在什么時(shí)候?qū)嵗?一般類的實(shí)例化有2種,一種是單例系統(tǒng)啟動(dòng)就實(shí)例化;一種是非單例(或者單例懶加載)在getBean時(shí)實(shí)例化.

這邊的觸發(fā)卻是通過(guò)BeanFcatoryPostProcessor.

BeanFactoryPostProcessor是在bean實(shí)例化前,修改bean definition的,比如bean definition中的占位符就是這邊解決的,而我們現(xiàn)在使用的properties也是這邊解決的.

這個(gè)是通過(guò)PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors實(shí)現(xiàn)的.
掃描容器中的BeanFactoryPostProcessor,找到了這邊需要的PropertySourcesPlaceholderConfigurer,并通過(guò)容器的getBean實(shí)例化

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
 }

PropertySourcesPlaceholderConfigurer實(shí)例化完成后,就直接進(jìn)行觸發(fā),并加載信息

 OrderComparator.sort(priorityOrderedPostProcessors);
 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

我們?cè)賮?lái)看看PropertySourcesPlaceholderConfigurer的繼承體系把

1.BeanFactoryPostProcessor

定義一個(gè)用于修改容器中bean definition的屬性的接口.其實(shí)現(xiàn)類在一般類使用前先實(shí)例化,并對(duì)其他類的屬性進(jìn)行修改.

這跟BeanPostProcessor有明顯的區(qū)別,BeanPostProcessor是修改bean實(shí)例的.

2.PropertiesLoaderSupport

加載properties文件的抽象類.

這邊具體的加載邏輯是委托PropertiesLoaderUtils#fillProperties實(shí)現(xiàn)

3.PropertyResourceConfigurer

bean definition中占位符的替換就是這個(gè)抽象類實(shí)現(xiàn)的.

實(shí)現(xiàn)BeanFactoryPostProcessor#postProcessBeanFactory,迭代容器的中的類定義,進(jìn)行修改

具體如何修改就通過(guò)鉤子processProperties交由子類實(shí)現(xiàn)

4.PlaceholderConfigurerSupport

使用visitor設(shè)計(jì)模式,通過(guò)BeanDefinitionVisitor和StringValueResolver更新屬性

StringValueResolver是一個(gè)轉(zhuǎn)化String類型數(shù)據(jù)的接口,真正更新屬性的api實(shí)現(xiàn)竟然是在

PropertyPlaceholderHelper#parseStringValue

5.PropertySourcesPlaceholderConfigurer

覆寫postProcessorBeanFactory api定義解析流程

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java調(diào)用js文件的兩種常用方法示例(支持V8引擎)

    java調(diào)用js文件的兩種常用方法示例(支持V8引擎)

    在Java中調(diào)用JavaScript的方法通常涉及到使用Java的腳本引擎,下面這篇文章主要給大家介紹了關(guān)于java調(diào)用js文件的兩種常用方法(支持V8引擎)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • Java Spring Boot實(shí)戰(zhàn)練習(xí)之單元測(cè)試篇

    Java Spring Boot實(shí)戰(zhàn)練習(xí)之單元測(cè)試篇

    單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。對(duì)于單元測(cè)試中單元的含義,一般來(lái)說(shuō),要根據(jù)實(shí)際情況去判定其具體含義,如C語(yǔ)言中單元指一個(gè)函數(shù),Java里單元指一個(gè)類,圖形化的軟件中可以指一個(gè)窗口或一個(gè)菜單等
    2021-10-10
  • Spring實(shí)戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作示例

    Spring實(shí)戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之協(xié)調(diào)作用域不同步的Bean操作,結(jié)合實(shí)例形式分析了Spring協(xié)調(diào)作用域不同步的Bean相關(guān)配置及使用技巧,需要的朋友可以參考下
    2019-11-11
  • Spring Boot中使用Activiti的方法教程(二)

    Spring Boot中使用Activiti的方法教程(二)

    工作流(Workflow),就是“業(yè)務(wù)過(guò)程的部分或整體在計(jì)算機(jī)應(yīng)用環(huán)境下的自動(dòng)化”,下面這篇文章主要給大家介紹了關(guān)于Spring Boot中使用Activiti的相關(guān)資料,需要的朋友可以參考下
    2018-08-08
  • Spring Boot 項(xiàng)目創(chuàng)建的詳細(xì)步驟(圖文)

    Spring Boot 項(xiàng)目創(chuàng)建的詳細(xì)步驟(圖文)

    這篇文章主要介紹了Spring Boot 項(xiàng)目創(chuàng)建的詳細(xì)步驟(圖文),這里我們有兩種創(chuàng)建Spring Boot項(xiàng)目的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • java反射簡(jiǎn)單實(shí)例

    java反射簡(jiǎn)單實(shí)例

    這篇文章主要介紹了java反射機(jī)制,以一個(gè)簡(jiǎn)單實(shí)例形式分析了Java反射的原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-02-02
  • SpringBoot+MyBatis實(shí)現(xiàn)MD5加密數(shù)據(jù)庫(kù)用戶密碼的方法

    SpringBoot+MyBatis實(shí)現(xiàn)MD5加密數(shù)據(jù)庫(kù)用戶密碼的方法

    MD5技術(shù)主要用于對(duì)用戶密碼加密,增加賬戶的安全性,他具有不可逆的特性,不會(huì)被輕易解密,這篇文章給大家介紹SpringBoot+MyBatis實(shí)現(xiàn)MD5加密數(shù)據(jù)庫(kù)用戶密碼的方法,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Java中keytool的使用

    Java中keytool的使用

    Keytool 是一個(gè)JAVA環(huán)境下的安全鑰匙與證書的管理工具,Keytool將密鑰(key)和證書(certificates)存在一個(gè)稱為keystore 的文件(受密碼保護(hù))中,本文重點(diǎn)給大家介紹keytool的使用,感興趣的朋友一起看看吧
    2022-02-02
  • Java中的日期時(shí)間類實(shí)例詳解(Date、Calendar、DateFormat)

    Java中的日期時(shí)間類實(shí)例詳解(Date、Calendar、DateFormat)

    在JDK1.0中,Date類是唯一的一個(gè)代表時(shí)間的類,但是由于Date類不便于實(shí)現(xiàn)國(guó)際化,所以從JDK1.1版本開(kāi)始,推薦使用Calendar類進(jìn)行時(shí)間和日期處理,這篇文章主要介紹了Java中的日期時(shí)間類詳解(Date、Calendar、DateFormat),需要的朋友可以參考下
    2023-11-11
  • Java網(wǎng)絡(luò)編程之簡(jiǎn)易聊天室的實(shí)現(xiàn)

    Java網(wǎng)絡(luò)編程之簡(jiǎn)易聊天室的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)一個(gè)簡(jiǎn)易聊天室功能,可以實(shí)現(xiàn)運(yùn)行客戶端和連接服務(wù)器,文中的示例代碼講解詳細(xì),需要的可以了解一下
    2022-10-10

最新評(píng)論