code: private void processPropertyPlaceHolders() {
          Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class);
  
          if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) {
              BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) applicationContext)
                      .getBeanFactory().getBeanDefinition(beanName);
  
              // PropertyResourceConfigurer does not expose any methods to explicitly perform
              // property placeholder substitution. Instead, create a BeanFactory that just
              // contains this mapper scanner and post process the factory.
              DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
              factory.registerBeanDefinition(beanName, mapperScannerBean);
  
              for (PropertyResourceConfigurer prc : prcs.values()) {
                  prc.postProcessBeanFactory(factory);
              }
  
              PropertyValues values = mapperScannerBean.getPropertyValues();
  
              this.basePackage = updatePropertyValue("basePackage", values);
              this.sqlSessionFactoryBeanName = updatePropertyValue("sqlSessionFactoryBeanName", values);
              this.sqlSessionTemplateBeanName = updatePropertyValue("sqlSessionTemplateBeanName", values);
          }
      }
docs: /*
  BeanDefinitionRegistries are called early in application startup, before
  BeanFactoryPostProcessors. This means that PropertyResourceConfigurers will not have been
  loaded and any property substitution of this class' properties will fail. To avoid this, find
  any PropertyResourceConfigurers defined in the context and run them on this class' bean
  definition. Then update the values.