From d5fde46fc0bbf358ef4c30e719a22c0e96f5ee02 Mon Sep 17 00:00:00 2001 From: Guirong Hu Date: Fri, 7 Apr 2023 18:28:46 +0800 Subject: [PATCH] Allow PropertySourcesPlaceholderConfigurer to customize resolver --- .../PropertySourcesPlaceholderConfigurer.java | 17 +++++-- ...ertySourcesPlaceholderConfigurerTests.java | 47 ++++++++++++++++++- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java b/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java index 293c4fa2f269..3c3f142b153c 100644 --- a/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java +++ b/spring-context/src/main/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -139,8 +139,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) // See https://github.com/spring-projects/spring-framework/issues/27947 if (this.ignoreUnresolvablePlaceholders && (this.environment instanceof ConfigurableEnvironment configurableEnvironment)) { - PropertySourcesPropertyResolver resolver = - new PropertySourcesPropertyResolver(configurableEnvironment.getPropertySources()); + ConfigurablePropertyResolver resolver = createPropertyResolver(configurableEnvironment.getPropertySources()); resolver.setIgnoreUnresolvableNestedPlaceholders(true); propertyResolver = resolver; } @@ -169,11 +168,19 @@ public String getProperty(String key) { throw new BeanInitializationException("Could not load properties", ex); } } - - processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources)); + processProperties(beanFactory, createPropertyResolver(this.propertySources)); this.appliedPropertySources = this.propertySources; } + /** + * Factory method used to create the {@link ConfigurablePropertyResolver} + * instance used by the placeholder configurer. + * @since 6.0.8 + */ + protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { + return new PropertySourcesPropertyResolver(propertySources); + } + /** * Visit each bean definition in the given bean factory and attempt to replace ${...} property * placeholders with values from the given properties. diff --git a/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java b/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java index 839044820bac..0e0124ad015f 100644 --- a/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java +++ b/spring-context/src/test/java/org/springframework/context/support/PropertySourcesPlaceholderConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,12 +30,16 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.core.env.ConfigurablePropertyResolver; import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.PropertySource; +import org.springframework.core.env.PropertySources; +import org.springframework.core.env.PropertySourcesPropertyResolver; import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.testfixture.env.MockPropertySource; +import org.springframework.lang.Nullable; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; @@ -430,6 +434,47 @@ public void optionalPropertyWithoutValue() { assertThat(bf.getBean(OptionalTestBean.class).getName()).isEqualTo(Optional.empty()); } + @Test + void withCustomPropertyResolver() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerBeanDefinition("testBean", + genericBeanDefinition(TestBean.class) + .addPropertyValue("name", "${my.name}") + .getBeanDefinition()); + + MockEnvironment env = new MockEnvironment(); + env.setProperty("my.name", "myValue"); + + CustomPropertySourcesPlaceholderConfigurer configurer = new CustomPropertySourcesPlaceholderConfigurer(); + configurer.setEnvironment(env); + configurer.setIgnoreUnresolvablePlaceholders(true); + configurer.postProcessBeanFactory(beanFactory); + assertThat(beanFactory.getBean(TestBean.class).getName()).isEqualTo("myValue-custom"); + } + + private static class CustomPropertySourcesPropertyResolver extends PropertySourcesPropertyResolver { + + public CustomPropertySourcesPropertyResolver(PropertySources propertySources) { + super(propertySources); + } + + @Override + @Nullable + public String getProperty(String key) { + return super.getProperty(key) + "-custom"; + } + + } + + private static class CustomPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer { + + @Override + protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) { + return new CustomPropertySourcesPropertyResolver(propertySources); + } + + } + private static class OptionalTestBean {