最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的@PropertySource注解源碼詳細(xì)解析

 更新時(shí)間:2024年01月25日 11:35:09   作者:mumubili  
這篇文章主要介紹了Spring中的@PropertySource注解源碼詳細(xì)解析,@PropertySource注解,標(biāo)注在配置類@Configuration上面,下面主要分析一下@PropertySource注解的處理過(guò)程,也就是怎么把配置信息從.properies文件放到environment中的,需要的朋友可以參考下

前言

通常,我們?cè)陂_(kāi)發(fā)java spring項(xiàng)目時(shí),會(huì)包含多套環(huán)境(profile),并且分別提供了不同環(huán)境下的屬性文件(.properties),在引用屬性文件時(shí),都會(huì)用到@PropertySource注解,標(biāo)注在配置類@Configuration上面,下面主要分析一下@PropertySource注解的處理過(guò)程,也就是怎么把配置信息從.properies文件放到environment中的;

1. @PropertySource處理入口

@PropertySource使用時(shí)都會(huì)和@Configuration放在一起,對(duì)@PropertySource的處理也是放在@Configuration解析處理過(guò)程中的(對(duì)@Configuration的處理過(guò)程后面再單獨(dú)進(jìn)行分析),參見(jiàn)源碼如下:

/**
	 * Apply processing and build a complete {@link ConfigurationClass} by reading the
	 * annotations, members and methods from the source class. This method can be called
	 * multiple times as relevant sources are discovered.
	 * @param configClass the configuration class being build
	 * @param sourceClass a source class
	 * @return the superclass, or {@code null} if none found or previously processed
	 */
	protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
			throws IOException {
		// Recursively process any member (nested) classes first
		processMemberClasses(configClass, sourceClass);
		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}
    //......其余部分省略
}

上面for循環(huán)處理的過(guò)程,實(shí)質(zhì)上主要包含了兩步:

  • 解析@PropertySource注解,包括單獨(dú)聲明的@PropertySource注解,以及在容器注解@PropertySources value屬性中指定的注解;
  • 將解析的@PropertySource注解放到environment中;

下面分別對(duì)這兩個(gè)過(guò)程進(jìn)行分析;

2. @PropertySource注解解析

解析過(guò)程主要封裝到了AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)當(dāng)中,根據(jù)進(jìn)去源碼如下:

static Set<AnnotationAttributes> attributesForRepeatable(
			AnnotationMetadata metadata, String containerClassName, String annotationClassName) {
		Set<AnnotationAttributes> result = new LinkedHashSet<AnnotationAttributes>();
		// Direct annotation present?
		addAttributesIfNotNull(result, metadata.getAnnotationAttributes(annotationClassName, false));
		// Container annotation present?
		Map<String, Object> container = metadata.getAnnotationAttributes(containerClassName, false);
		if (container != null && container.containsKey("value")) {
			for (Map<String, Object> containedAttributes : (Map<String, Object>[]) container.get("value")) {
				addAttributesIfNotNull(result, containedAttributes);
			}
		}
		// Return merged result
		return Collections.unmodifiableSet(result);
	}
private static void addAttributesIfNotNull(Set<AnnotationAttributes> result, Map<String, Object> attributes) {
		if (attributes != null) {
			result.add(AnnotationAttributes.fromMap(attributes));
		}
	}

這里,首先獲取配置類上@PropertySource注解,解析成AnnotationAttributes map對(duì)象,放到result中;

然后解析容器注解@PropertySources value屬性值,并將解析的@PropertySource列表放到result中;

這樣@PropertySource注解和@PropertySources容器注解解析完畢;

3. 構(gòu)造ResourcePropertySource對(duì)象

這里主要分析一下processPropertySource(propertySource)的過(guò)程,源碼如下:

/**
	 * Process the given <code>@PropertySource</code> annotation metadata.
	 * @param propertySource metadata for the <code>@PropertySource</code> annotation found
	 * @throws IOException if loading a property source failed
	 */
	private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
		String name = propertySource.getString("name");
		if (!StringUtils.hasLength(name)) {
			name = null;
		}
		String encoding = propertySource.getString("encoding");
		if (!StringUtils.hasLength(encoding)) {
			encoding = null;
		}
		String[] locations = propertySource.getStringArray("value");
		Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
		boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
		Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
		PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
				DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
		for (String location : locations) {
			try {
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
				Resource resource = this.resourceLoader.getResource(resolvedLocation);
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			catch (IllegalArgumentException ex) {
				// Placeholders not resolvable
				if (ignoreResourceNotFound) {
					if (logger.isInfoEnabled()) {
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				}
				else {
					throw ex;
				}
			}
			catch (IOException ex) {
				// Resource not found when trying to open it
				if (ignoreResourceNotFound &&
						(ex instanceof FileNotFoundException || ex instanceof UnknownHostException)) {
					if (logger.isInfoEnabled()) {
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				}
				else {
					throw ex;
				}
			}
		}
	}

其中@PropertySource的主要屬性value(這里放到了locations中)保存了屬性文件的存放位置,對(duì)每一個(gè)location的解析主要分為如下3步:

  • 解析location中包含的占位符
  • 加載Resource對(duì)象
  • 構(gòu)造ResourcePropertySource對(duì)象
  • PropertySource加載到environment當(dāng)中

其中第三步構(gòu)造ResourcePropertySource主要用到了PropertySourceFactory,這里默認(rèn)實(shí)現(xiàn)是DefaultPropertySourceFactory,內(nèi)部實(shí)現(xiàn)源碼如下:

/**
 * The default implementation for {@link PropertySourceFactory},
 * wrapping every resource in a {@link ResourcePropertySource}.
 *
 * @author Juergen Hoeller
 * @since 4.3
 * @see PropertySourceFactory
 * @see ResourcePropertySource
 */
public class DefaultPropertySourceFactory implements PropertySourceFactory {
	@Override
	public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
		return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
	}
}

上面主要通過(guò)resource構(gòu)造了ResourcePropertySource對(duì)象,其構(gòu)造函數(shù)如下:

/**
	 * Create a PropertySource based on Properties loaded from the given resource.
	 * The name of the PropertySource will be generated based on the
	 * {@link Resource#getDescription() description} of the given resource.
	 */
	public ResourcePropertySource(EncodedResource resource) throws IOException {
		super(getNameForResource(resource.getResource()), PropertiesLoaderUtils.loadProperties(resource));
		this.resourceName = null;
	}

如上,可見(jiàn)先是由resource構(gòu)造了Peoperties對(duì)象,然后構(gòu)造了PropertiesPropertySource父類.....

如下是ResourcePropertySource的繼承結(jié)構(gòu),最終加載的屬性值放入到了PropertySource的成員變量source中;

4. PropertySource配置加載到environment當(dāng)中

構(gòu)造完ResourcePropertySource對(duì)象之后,下面將該對(duì)象放入到environment中,源碼如下:

private void addPropertySource(PropertySource<?> propertySource) {
		String name = propertySource.getName();
		MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
		if (propertySources.contains(name) && this.propertySourceNames.contains(name)) {
			// We've already added a version, we need to extend it
			PropertySource<?> existing = propertySources.get(name);
			PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ?
					((ResourcePropertySource) propertySource).withResourceName() : propertySource);
			if (existing instanceof CompositePropertySource) {
				((CompositePropertySource) existing).addFirstPropertySource(newSource);
			}
			else {
				if (existing instanceof ResourcePropertySource) {
					existing = ((ResourcePropertySource) existing).withResourceName();
				}
				CompositePropertySource composite = new CompositePropertySource(name);
				composite.addPropertySource(newSource);
				composite.addPropertySource(existing);
				propertySources.replace(name, composite);
			}
		}
		else {
			if (this.propertySourceNames.isEmpty()) {
				propertySources.addLast(propertySource);
			}
			else {
				String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
				propertySources.addBefore(firstProcessed, propertySource);
			}
		}
		this.propertySourceNames.add(name);
	}

注意,這里對(duì)于@PropertySource注解獲取的配置屬性放入到了environment的后面,實(shí)際在application.properties后面,也即application.properties的優(yōu)先級(jí)高于@PropertySource引入的配置,后面單獨(dú)對(duì)這塊進(jìn)行分析;

到此這篇關(guān)于Spring中的@PropertySource注解源碼詳細(xì)解析的文章就介紹到這了,更多相關(guān)@PropertySource注解源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決IDEA中pom.xml文件變?yōu)榛疑膯?wèn)題

    解決IDEA中pom.xml文件變?yōu)榛疑膯?wèn)題

    這篇文章主要給大家介紹了如何解決IDEA中pom.xml文件變?yōu)榛疑膯?wèn)題,文中通過(guò)圖文結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • Java方法反射實(shí)現(xiàn)原理詳解

    Java方法反射實(shí)現(xiàn)原理詳解

    這篇文章主要為大家詳細(xì)介紹了Java方法反射的實(shí)現(xiàn)原理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java?中不全部使用?Static?方法的理由

    Java?中不全部使用?Static?方法的理由

    這篇文章主要介紹了Java?中不全部使用?Static?方法的理由,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • Java基于redis和mysql實(shí)現(xiàn)簡(jiǎn)單的秒殺(附demo)

    Java基于redis和mysql實(shí)現(xiàn)簡(jiǎn)單的秒殺(附demo)

    這篇文章主要介紹了Java基于redis和mysql實(shí)現(xiàn)簡(jiǎn)單的秒殺(附demo),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • IDEA如何取消空格補(bǔ)全代碼

    IDEA如何取消空格補(bǔ)全代碼

    這篇文章主要介紹了IDEA如何取消空格補(bǔ)全代碼的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • springboot實(shí)現(xiàn)指定mybatis中mapper文件掃描路徑

    springboot實(shí)現(xiàn)指定mybatis中mapper文件掃描路徑

    這篇文章主要介紹了springboot實(shí)現(xiàn)指定mybatis中mapper文件掃描路徑方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java數(shù)組的擴(kuò)容代碼示例

    Java數(shù)組的擴(kuò)容代碼示例

    這篇文章主要介紹了Java數(shù)組的擴(kuò)容,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-09-09
  • 一個(gè)Java的main方法在JVM中的執(zhí)行流程示例詳解

    一個(gè)Java的main方法在JVM中的執(zhí)行流程示例詳解

    main方法是Java程序的入口點(diǎn),程序從這里開(kāi)始執(zhí)行,這篇文章主要介紹了一個(gè)Java的main方法在JVM中執(zhí)行流程的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-09-09
  • javamail 發(fā)送郵件的實(shí)例代碼分享

    javamail 發(fā)送郵件的實(shí)例代碼分享

    今天學(xué)習(xí)了一下JavaMail,javamail發(fā)送郵件確實(shí)是一個(gè)比較麻煩的問(wèn)題。為了以后使用方便,自己寫(xiě)了段代碼,打成jar包,以方便以后使用
    2013-08-08
  • SWT(JFace)體驗(yàn)之FillLayout布局

    SWT(JFace)體驗(yàn)之FillLayout布局

    FillLayout是非常簡(jiǎn)單的一種布局方式,它會(huì)以同樣大小對(duì)父組件中的子組件進(jìn)行布局,這些子組件將以一行或一列的形式排列。
    2009-06-06

最新評(píng)論

吉木乃县| 茶陵县| 吉安市| 邢台县| 永州市| 徐闻县| 阜新| 高青县| 林州市| 兴城市| 鄂伦春自治旗| 永吉县| 嘉义市| 韶山市| 古交市| 崇左市| 邵武市| 曲周县| 汶川县| 林口县| 游戏| 甘洛县| 泉州市| 毕节市| 太仓市| 武胜县| 历史| 湖州市| 始兴县| 泊头市| 出国| 乌鲁木齐市| 溧阳市| 永胜县| 无极县| 马公市| 南通市| 宝清县| 慈溪市| 兴山县| 峨边|