spring配置加载PropertyResourceConfigurer和PropertyPlaceholderConfigurer

在这里插入图片描述

继承图UML

PropertySourcesPlaceholderConfigurer

  1. PropertySourcesPlaceholderConfigurer,也就是 BeanFactoryPostProcessor接口的一个实现,PropertySourcesPlaceholderConfigurer:
    在这里插入图片描述

PropertyPlaceholderConfigurer

  1. PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是 BeanFactoryPostProcessor接口的一个实现PropertySourcesPlaceholderConfigurer继承图:在这里插入图片描述

补充知识点

1. PropertiesLoaderSupport

抽象类,提供从properties文件中读取配置信息的能力,该类的属性locations指定需要加载的文件所在的路径。mergeProperties()中加载和合并所有的Properties属性, 可动态控制配置文件和BeanDefinition(默认配置)加载顺序.

public abstract class PropertiesLoaderSupport {

    /** Logger available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());

    /**
     * 本地资源例如从xml加载的配置信息等
     */
    @Nullable
    protected Properties[] localProperties;

    /**
     * 为true则localProperties会覆盖从locations获取的属性值
     */
    protected boolean localOverride = false;

    /**
     * 配置文件Properties地址
     */
    @Nullable
    private Resource[] locations;

    /**
     * 当解析不到对应的配置文件是否报错
     */
    private boolean ignoreResourceNotFound = false;

    @Nullable
    private String fileEncoding;

    /**
     * Properties文件加载策略,可以配置加载编码形式等. 默认为DefaultPropertiesPersister,实质委托Properties.load 或者 Properties.store
       */
      private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
  
      /**
       * Set local properties, e.g. via the "props" tag in XML bean definitions.
       * These can be considered defaults, to be overridden by properties
       * loaded from files.
       */
      public void setProperties(Properties properties) {
          this.localProperties = new Properties[] {properties};
      }
  
      /**
       * Set local properties, e.g. via the "props" tag in XML bean definitions,
       * allowing for merging multiple properties sets into one.
       */
      public void setPropertiesArray(Properties... propertiesArray) {
          this.localProperties = propertiesArray;
      }
  
      /**
       * Set a location of a properties file to be loaded.
       * <p>Can point to a classic properties file or to an XML file
       * that follows JDK 1.5's properties XML format.
       */
      public void setLocation(Resource location) {
          this.locations = new Resource[] {location};
      }
  
      /**
       * Set locations of properties files to be loaded.
       * <p>Can point to classic properties files or to XML files
       * that follow JDK 1.5's properties XML format.
       * <p>Note: Properties defined in later files will override
       * properties defined earlier files, in case of overlapping keys.
       * Hence, make sure that the most specific files are the last
       * ones in the given list of locations.
       */
      public void setLocations(Resource... locations) {
          this.locations = locations;
      }
  
      /**
       * Set whether local properties override properties from files.
       * <p>Default is "false": Properties from files override local defaults.
       * Can be switched to "true" to let local properties override defaults
       * from files.
       */
      public void setLocalOverride(boolean localOverride) {
          this.localOverride = localOverride;
      }
  
      /**
       * Set if failure to find the property resource should be ignored.
       * <p>"true" is appropriate if the properties file is completely optional.
       * Default is "false".
       */
      public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) {
          this.ignoreResourceNotFound = ignoreResourceNotFound;
      }
  
      /**
       * Set the encoding to use for parsing properties files.
       * <p>Default is none, using the {@code java.util.Properties}
       * default encoding.
       * <p>Only applies to classic properties files, not to XML files.
       * @see org.springframework.util.PropertiesPersister#load
      */
     public void setFileEncoding(String encoding) {
         this.fileEncoding = encoding;
     }
 
     /**
      * Set the PropertiesPersister to use for parsing properties files.
      * The default is DefaultPropertiesPersister.
      * @see org.springframework.util.DefaultPropertiesPersister
      */
     public void setPropertiesPersister(@Nullable PropertiesPersister propertiesPersister) {
         this.propertiesPersister =
                 (propertiesPersister != null ? propertiesPersister : new DefaultPropertiesPersister());
     }
 
     /**
      * 加载和合并所有的Properties属性, 可动态控制 配置文件属性 和 BeanDefinition属性(默认配置) 加载顺序
      */
     protected Properties mergeProperties() throws IOException {
        Properties result = new Properties();

        if (this.localOverride) {
            // Load properties from file upfront, to let local properties override.
            loadProperties(result);
        }

        if (this.localProperties != null) {
            for (Properties localProp : this.localProperties) {
                CollectionUtils.mergePropertiesIntoMap(localProp, result);
            }
        }

        if (!this.localOverride) {
            // Load properties from file afterwards, to let those properties override.
             loadProperties(result);
         }
 
         return result;
     }
 
     /**
      * 将配置文件信息,加载进入Properties实例
      */
     protected void loadProperties(Properties props) throws IOException {
        if (this.locations != null) {
            for (Resource location : this.locations) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Loading properties file from " + location);
                 }
                 try {
                     PropertiesLoaderUtils.fillProperties(
                             props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister);
                }
                catch (FileNotFoundException | UnknownHostException ex) {
                    if (this.ignoreResourceNotFound) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Properties resource not found: " + ex.getMessage());
                         }
                     }
                     else {
                         throw ex;
                     }
                 }
             }
         }
     }

 }

2. PropertyResourceConfigurer

抽象类,继承PropertiesLoaderSupport并实现BeanFactoryPostProcessor接口,资源加载和占位符替换入口。在postProcessBeanFactory()方法从配置文件中读取了配置项,并调用抽象方法processProperties()由子类决定处理逻辑。除此之外,提供了convertProperty()方法,该方法是个扩展点,其实里面什么都没做,它可以用来子类在处理这些配置信息前,对配置信息进行一些转换,例如配置属性的解密。


 public abstract class PropertyResourceConfigurer extends PropertiesLoaderSupport
        implements BeanFactoryPostProcessor, PriorityOrdered {

    private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered  
    /**     
    * BeanFactoryPostProcessor拓展接口, 资源加载和占位符替换入口
     */      @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
         try {
             // 继承自PropertiesLoaderSupport, 加载配置文件   
             Properties mergedProps = mergeProperties();

            // 对已加载属性配置进行处理, spring一个拓展点. 例如从配置文件获取密文, 此时可以做解密
            convertProperties(mergedProps);

            // 抽象方法, 由子类实现占位符替换逻辑
            processProperties(beanFactory, mergedProps);
       }
       catch (IOException ex) {
           throw new BeanInitializationException("Could not load properties", ex);
       }
   }

   protected void convertProperties(Properties props) {
       Enumeration<?> propertyNames = props.propertyNames();
       while (propertyNames.hasMoreElements()) {
           String propertyName = (String) propertyNames.nextElement();
           String propertyValue = props.getProperty(propertyName);
           //  默认返回原始值, 子类重写实现定制功能, 如:配置文件获取密文, 此时可以做解密
           String convertedValue = convertProperty(propertyName, propertyValue);
           if (!ObjectUtils.nullSafeEquals(propertyValue, convertedValue)) {
               props.setProperty(propertyName, convertedValue);
           }
       }
   }

   protected String convertProperty(String propertyName, String propertyValue) {
       return convertPropertyValue(propertyValue);
   }

   /**      
   * 默认返回原始值, 子类重写实现定制功能, 如:配置文件获取密文, 此时可以做解密
    */    
    protected String convertPropertyValue(String originalValue) {
       return originalValue;
   }

   /**    
   * 抽象方法, 由子类实现占位符替换逻辑
   */  
   protected abstract void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
             throws BeansException;
 
 }

3. PlaceholderConfigurerSupport

抽象类,该类持有占位符符号的前缀、后缀、分隔符,在doProcessProperties()方法实现对BeanDefinition实例中的占位符进行替换。


 public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
         implements BeanNameAware, BeanFactoryAware {
  
      /** Default placeholder prefix: {@value}. */      
      public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
 
      /** Default placeholder suffix: {@value}. */   
     public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
  
     /** Default value separator: {@value}. */
     public static final String DEFAULT_VALUE_SEPARATOR = ":";
 
     /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX}. */
     protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
 
    /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX}. */
    protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;

    /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR}. */
    @Nullable
    protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;

    protected boolean trimValues = false;

    @Nullable
    protected String nullValue;

    /**     
    * 当解析不到对应的key是否忽略, 默认为false.
    * 在配置多个解析类的时候, 可设置为ture防止属性加载报错.
      */    
      protected boolean ignoreUnresolvablePlaceholders = false;
 
     @Nullable
     private String beanName;
 
     @Nullable
     private BeanFactory beanFactory;
 
     // 省略getter 和 setter ........
     /**      * 实现对BeanDefinition实例中的占位符进行替换*/    
     protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
             StringValueResolver valueResolver) {
 
         /**          * 循环获得所有BeanDefinition, 依据模版类StringValueResolver替换对应BeanDefinition的占位符*/       
         BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
 
         String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
         for (String curName : beanNames) {
             // Check that we're not parsing our own bean definition,
             // to avoid failing on unresolvable placeholders in properties file locations.56             if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
                BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
                try {
                    visitor.visitBeanDefinition(bd);
                }
                catch (Exception ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
                 }
             }
         }
 
         // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
         beanFactoryToProcess.resolveAliases(valueResolver);
 
         // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
         beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
     }

解析

PropertyPlaceholderConfigurer

继承自PlaceholderConfigurerSupport,并实现抽象方法processProperties()。该方法会创建模版类PlaceholderResolvingStringValueResolver,该类提供解析字符串的方法resolveStringValue。创建了StringValueResolver实现类后,交由它的父类PlaceholderConfigurerSupport的doProcessProperties()处理。

  • BeanDefinition:在spring容器初始化时,扫描并获取每个bean的声明(例如在xml中声明、通过注解声明等),然后组装成BeanDefinition,它描述了一个bean实例,拥有属性值,构造参数值和具体实现提供的其他信息。
  • BeanDefinitionVisitor:负责访问BeanDefinition,包括
    1. 从beanDefinition实例中,获取spring约定的可以替换的参数;
    2. 使用占位符解析器解析占位符,并从properties中获取它对应的值,最后把值设置到BeanDefinition中。
  • PropertyPlaceholderHelper:持有占位符的前缀、后缀、多值的分隔符,负责把占位符的字符串去除前缀、后缀. 调用PropertyPlaceholderConfigurerResolver进行字符串替换.
  • PropertyPlaceholderConfigurerResolver:从properties中将传入占位符替换为对应的值.
public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport {
 
     /** Never check system properties. */ 
     public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
 
     /**  
     * Check system properties if not resolvable in the specified properties.
      * This is the default.
      */ 
      public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
 
     /** 
     * Check system properties first, before trying the specified properties.
      * This allows system properties to override any other property source.
      */
      public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
 
     /** 
     * spring提供工具类, 利用jdk反射机制, 对类常量(public static final)进行映射, 可通过常量名称进行访问.
       */ 
       private static final Constants constants = new Constants(PropertyPlaceholderConfigurer.class);
 
     /** 
     * 三种模式, 默认为 1: 
      * SYSTEM_PROPERTIES_MODE_NEVER-0: 此时以配置文件为准,不会加载 JVM系统变量和系统环境变量
       * SYSTEM_PROPERTIES_MODE_FALLBACK-1: 此时以配置文件优先, 加载不到会再次load JVM系统变量和系统环境变量
       * SYSTEM_PROPERTIES_MODE_OVERRIDE-2: 此时以JVM系统变量和系统环境变量, 加载不到会再次load 配置文件变量
      */ 
      private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
 
     /** 
     * 控制是否会加载系统环境变量
      */ 
      private boolean searchSystemEnvironment =
             !SpringProperties.getFlag(AbstractEnvironment.IGNORE_GETENV_PROPERTY_NAME);
 
 
     /** 
     * Set the system property mode by the name of the corresponding constant,
      * e.g. "SYSTEM_PROPERTIES_MODE_OVERRIDE".
      * @param constantName name of the constant
      * @throws java.lang.IllegalArgumentException if an invalid constant was specified
      * @see #setSystemPropertiesMode
      */ 
      public void setSystemPropertiesModeName(String constantName) throws IllegalArgumentException {
         this.systemPropertiesMode = constants.asNumber(constantName).intValue();
     }
  
     public void setSystemPropertiesMode(int systemPropertiesMode) {
         this.systemPropertiesMode = systemPropertiesMode;
     }
     
     public void setSearchSystemEnvironment(boolean searchSystemEnvironment) {
         this.searchSystemEnvironment = searchSystemEnvironment;
     }
 
     /** 
     * 依据systemPropertiesMode配置的策略, 根据占位符名称换取对应的值
      */ 
      @Nullable
     protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) {
         String propVal = null;
         if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
             propVal = resolveSystemProperty(placeholder);
         }
         if (propVal == null) {
             propVal = resolvePlaceholder(placeholder, props);
         }
         if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
             propVal = resolveSystemProperty(placeholder);
         }
         return propVal;
     }
 
     @Nullable
     protected String resolvePlaceholder(String placeholder, Properties props) {
         return props.getProperty(placeholder);
     }
 
     @Nullable
     protected String resolveSystemProperty(String key) {
         try {
             String value = System.getProperty(key);
             // 依据searchSystemEnvironment 判断是否搜索环境变量 85             if (value == null && this.searchSystemEnvironment) {
                  value = System.getenv(key);
              }
              return value;
          }
          catch (Throwable ex) {
              if (logger.isDebugEnabled()) {
                  logger.debug("Could not access system property '" + key + "': " + ex);
              }
              return null;
          }
      }
  
  
      /**
      * 重写PlaceholderConfigurerSupport抽象方法processProperties, 实现替换逻辑
      * Visit each bean definition in the given bean factory and attempt to replace ${...} property
      * placeholders with values from the given properties.
      */
      @Override
     protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
            throws BeansException {

        StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
        doProcessProperties(beanFactoryToProcess, valueResolver);
    }


    /**
    * 实际替换占位符的模版类
     */
     private class PlaceholderResolvingStringValueResolver implements StringValueResolver {

        private final PropertyPlaceholderHelper helper;

        private final PlaceholderResolver resolver;

        public PlaceholderResolvingStringValueResolver(Properties props) {
            this.helper = new PropertyPlaceholderHelper(
                    placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
            this.resolver = new PropertyPlaceholderConfigurerResolver(props);
        }

        @Override
        @Nullable
        public String resolveStringValue(String strVal) throws BeansException {
            String resolved = this.helper.replacePlaceholders(strVal, this.resolver);
            if (trimValues) {
                resolved = resolved.trim();
            }
            return (resolved.equals(nullValue) ? null : resolved);
        }
    }

    private final class PropertyPlaceholderConfigurerResolver implements PlaceholderResolver {
 
         private final Properties props;
 
         private PropertyPlaceholderConfigurerResolver(Properties props) {
             this.props = props;
         }
 
         @Override
         @Nullable
         public String resolvePlaceholder(String placeholderName) {
             return PropertyPlaceholderConfigurer.this.resolvePlaceholder(placeholderName,
                     this.props, systemPropertiesMode);
         }
     }
 
 }

PropertySourcesPlaceholderConfigurer

PropertySourcesPlaceholderConfigurer该类有一个PropertySources的集合,集合中放的是PropertySource,它是一个抽象类,getProperty方法交由子类实现;每一个PropertySource可以是一个Properties,而且PropertySource可以是任何东西;例如:System.getProperteis 、System.getenv;而该类直接重写了postProcessBeanFactory方法,如果PropertySources集合为空,此类会把Environment、Properties文件、localProperties放到集合中:

  • PropertySourcesPlaceholderConfigurer会将Properties转换为属性集合PropertySources,以解析替换所有占位符.而PropertyPlaceholderConfigurer使用原始JDK Properties
  • 解析的来源包含: mergeProperties获取配置文件中的properties 和 Environment环境变量中的properties
  • 通过localOverride 控制加载的先后顺序
  • 一旦setPropertySources设置了propertySources属性资源,其他的资源将会被忽略.以此达到用户更细粒度控制资源加载
public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implements EnvironmentAware {

    // 1、标识不同来源的属性配置, 从配置文件获取 或者 环境变量获取和系统变量(比如springboot中applications.properties定义属性)  
	/** 
	* {@value} is the name given to the {@link PropertySource} for the set of
    * {@linkplain #mergeProperties() merged properties} supplied to this configurer.
    */  
	  public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties";
 
     /** 
	 * {@value} is the name given to the {@link PropertySource} that wraps the
      * {@linkplain #setEnvironment environment} supplied to this configurer.
      */ 
	  public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";
 
     @Nullable
     private MutablePropertySources propertySources;
 
     @Nullable
     private PropertySources appliedPropertySources;
 
     @Nullable
     private Environment environment;
 
 
     /** 
	 * Customize the set of {@link PropertySources} to be used by this configurer.
      * <p>Setting this property indicates that environment property sources and
      * local properties should be ignored.
      * @see #postProcessBeanFactory
      */ 
	  public void setPropertySources(PropertySources propertySources) {
         this.propertySources = new MutablePropertySources(propertySources);
     }
 
     /** 
	 * {@code PropertySources} from the given {@link Environment}
      * will be searched when replacing ${...} placeholders.
      * @see #setPropertySources
      * @see #postProcessBeanFactory
      */ 
	  @Override
     public void setEnvironment(Environment environment) {
         this.environment = environment;
     }
 
 
     // PropertySourcesPlaceholderConfigurer会将Properties转换为属性集合PropertySources,以解析替换所有占位符.而PropertyPlaceholderConfigurer使用原始JDK Properties
     // 解析的来源包含: mergeProperties获取配置文件中的properties 和 Environment环境变量中的properties
     // 也是通过localOverride 控制加载的先后顺序
     // 一旦setPropertySources设置了propertySources属性资源,其他的资源将会被忽略.以此达到用户更细粒度控制资源加载 
     /** 
	 * Processing occurs by replacing ${...} placeholders in bean definitions by resolving each
      * against this configurer's set of {@link PropertySources}, which includes:
      * <ul>
      * <li>all {@linkplain org.springframework.core.env.ConfigurableEnvironment#getPropertySources
      * environment property sources}, if an {@code Environment} {@linkplain #setEnvironment is present}
      * <li>{@linkplain #mergeProperties merged local properties}, if {@linkplain #setLocation any}
      * {@linkplain #setLocations have} {@linkplain #setProperties been}
      * {@linkplain #setPropertiesArray specified}
      * <li>any property sources set by calling {@link #setPropertySources}
      * </ul>
      * <p>If {@link #setPropertySources} is called, <strong>environment and local properties will be
      * ignored</strong>. This method is designed to give the user fine-grained control over property
      * sources, and once set, the configurer makes no assumptions about adding additional sources.
      */ 
	  @Override
     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
         if (this.propertySources == null) {
             this.propertySources = new MutablePropertySources();
             if (this.environment != null) {
                 this.propertySources.addLast(
                     new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
                         @Override
                         @Nullable
                         public String getProperty(String key) {
                             return this.source.getProperty(key);
                         }
                     }
                 );
             }
             try {
                 PropertySource<?> localPropertySource =
                         new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
                 if (this.localOverride) {
                     this.propertySources.addFirst(localPropertySource);
                 } else {
                     this.propertySources.addLast(localPropertySource);
                 }
             }
             catch (IOException ex) {
                 throw new BeanInitializationException("Could not load properties", ex);
             }
         }
 
         processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
         this.appliedPropertySources = this.propertySources;
     }
 
     /**
	 * Visit each bean definition in the given bean factory and attempt to replace ${...} property
      * placeholders with values from the given properties.
      */
	  protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
             final ConfigurablePropertyResolver propertyResolver) throws BeansException {
 
         // 区分于PropertyPlaceholderConfigurer, 使用ConfigurablePropertyResolver实例持有占位符的前缀、后缀、多值的分隔符 已经进行字符串替换
         propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
         propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
         propertyResolver.setValueSeparator(this.valueSeparator);
 
         StringValueResolver valueResolver = strVal -> {
             String resolved = (this.ignoreUnresolvablePlaceholders ?
                     propertyResolver.resolvePlaceholders(strVal) :
                     propertyResolver.resolveRequiredPlaceholders(strVal));
             if (this.trimValues) {
                 resolved = resolved.trim();
             }
             return (resolved.equals(this.nullValue) ? null : resolved);
         };
 
         // 委托抽象类PlaceholderConfigurerSupport#doProcessProperties解析,同PropertyPlaceholderConfigurer一样
         doProcessProperties(beanFactoryToProcess, valueResolver);
     }
 
     // 此时已废弃PlaceholderConfigurerSupport#processProperties
     /**
     * Implemented for compatibility with
      * {@link org.springframework.beans.factory.config.PlaceholderConfigurerSupport}.
      * @deprecated in favor of
      * {@link #processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver)}
      * @throws UnsupportedOperationException in this implementation
      */
	  @Override
     @Deprecated
     protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) {
         throw new UnsupportedOperationException(
                 "Call processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver) instead");
     }
 
     /**
	 * Return the property sources that were actually applied during
      * {@link #postProcessBeanFactory(ConfigurableListableBeanFactory) post-processing}.
      * @return the property sources that were applied
      * @throws IllegalStateException if the property sources have not yet been applied
      * @since 4.0
      */
	  public PropertySources getAppliedPropertySources() throws IllegalStateException {
         Assert.state(this.appliedPropertySources != null, "PropertySources have not yet been applied");
         return this.appliedPropertySources;
     }
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值