Before Spring officially starts refresh, a bit of pre-refresh preparation:
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @nullable ApplicationContext parent) throws BeansException {// Call the parent constructor to create an object, including the attribute assignment operation super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); }}Copy the code
Call the parent class constructor for related object creation, including the assignment of attributes. We can look at the call stack to see how it works:
It will eventually initializeStandardEnvironment
Object, callcustomizePropertySources
The environment variable () method takes the setting topropertySources
中
@Override protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast( new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); propertySources.addLast( new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); }Copy the code
In StandardEnvironment’s parent class, AbstractEnvironment, you can see the familiar spring.profiles. Active, which is used to switch configuration files between different environments. We will call the following method when we do the variable replacement, for example, we define a configuration file of spring-${user}. XML, which will be replaced with spring-daobao. XML, dabao is the current computer name:
protected String parseStringValue( String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) { int startIndex = value.indexOf(this.placeholderPrefix); if (startIndex == -1) { return value; } StringBuilder result = new StringBuilder(value); while (startIndex ! = -1) { int endIndex = findPlaceholderEndIndex(result, startIndex); if (endIndex ! = -1) { String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); String originalPlaceholder = placeholder; if (visitedPlaceholders == null) { visitedPlaceholders = new HashSet<>(4); } if (! visitedPlaceholders.add(originalPlaceholder)) { throw new IllegalArgumentException( "Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); } // Recursive invocation, parsing placeholders contained in the placeholder key. placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders); // Now obtain the value for the fully resolved key... String propVal = placeholderResolver.resolvePlaceholder(placeholder); if (propVal == null && this.valueSeparator ! = null) { int separatorIndex = placeholder.indexOf(this.valueSeparator); if (separatorIndex ! = -1) { String actualPlaceholder = placeholder.substring(0, separatorIndex); String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); if (propVal == null) { propVal = defaultValue; } } } if (propVal ! = null) { // Recursive invocation, parsing placeholders contained in the // previously resolved placeholder value. propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); if (logger.isTraceEnabled()) { logger.trace("Resolved placeholder '" + placeholder + "'"); } startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length()); } else if (this.ignoreUnresolvablePlaceholders) { // Proceed with unprocessed value. startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); } else { throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'" + " in value "" + value + """); } visitedPlaceholders.remove(originalPlaceholder); } else { startIndex = -1; } } return result.toString(); }Copy the code
// Initialize the BeanFactory, read the XML file, and record the resulting BeanFactory in the attributes of the current entity.
The refreshBeanFactory method calls loadBeanDefinitions and loads the configuration file to initialize the BeanDefinition
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, Then proceed with actually loading the beanDefinitionReader. InitBeanDefinitionReader (beanDefinitionReader) is set here; // Start loading beanDefinition loadBeanDefinitions(beanDefinitionReader); }Copy the code
Parse the bean label contents of the XML file into the BeanDefinition
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); // Parse the class attribute String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } // Parse parent attribute String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition {AbstractBeanDefinition} The actual implementation is GenericBeanDefinition AbstractBeanDefinition bd = createBeanDefinition(className, parent); / / parsing bean tag a variety of other attributes parseBeanDefinitionAttributes (ele, beanName containingBean, bd); / / set the description information bd. SetDescription (DomUtils. GetChildElementValueByTagName (ele, DESCRIPTION_ELEMENT)); ParseMetaElements (ele, bd); / / parse the lookup method attribute parseLookupOverrideSubElements (ele, bd. GetMethodOverrides ()); / / parsing replaced - parseReplacedMethodSubElements method attributes (ele, bd. GetMethodOverrides ()); / / parse the constructor argument parseConstructorArgElements (ele, bd); ParsePropertyElements (ele, bd); ParseQualifierElements (ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }Copy the code
BeanDefinitionNames: beanDefinitionNames: beanDefinitionNames: beanDefinitionNames: beanDefinitionNames
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); If (beanDefinition instanceof AbstractBeanDefinition) {try { It is mainly the verification of methodOverrides corresponding to abstractBeanDefinition property, // check whether methodOverrides exist with factory method or methodOverrides does not exist at all ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); If (existingDefinition! = null) {// If the corresponding beanName is registered and the bean is configured not to be overwritten, an exception is thrown if (! isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (! beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } this.beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); }} else {/ / Still in startup registration phase / / registered beanDefinition enclosing beanDefinitionMap. Put (beanName, beanDefinition); / / record beanName enclosing beanDefinitionNames. Add (beanName); removeManualSingletonName(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition ! = null | | containsSingleton (beanName)) {/ / reset all the corresponding cache resetBeanDefinition beanName (beanName); } else if (isConfigurationFrozen()) { clearByTypeCache(); }}Copy the code