ClassPathXmlApplicationContext load configuration process

spring loads basic xml configuration

The simplest xml configuration, loaded with ClassPathXmlApplicationContext

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
       <bean class="com.forcht.test.SimpleBean"/>
</beans>
 public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        SimpleBean simpleBean = applicationContext.getBean(SimpleBean.class);
        simpleBean.send();
    }

View the inheritance relationship of ClassPathXmlApplicationContext

Trace source code through breakpoint debug
ClassPathXmlApplicationContext constructor source code, calling the constructor of the parent class until AbstractApplicationContext

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

View the AbstractApplicationContext constructor source code

public AbstractApplicationContext(ApplicationContext parent) {
        this();
        setParent(parent);
    }
public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }
//This method creates a resource handler
protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }

So far, ClassPathXmlApplicationContext has two resource loaders (one is inherited from DefaultResourceLoader by AbstractApplicationContext, and the other is the pathmatching resourcepatternresolver actively created by AbstractApplicationContext)
DefaultResourceLoader can only load resources of a specific classpath, and pathmatching resourcepatternresolver can load multiple resources according to Ant style.

The setConfigLocations(configLocations) method of AbstractRefreshableConfigApplicationContext is called after the construction method of each parent is returned.

The purpose of this method is to resolve the placeholder to the actual address

public void setConfigLocations(String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }
protected String resolvePath(String path) {
        return getEnvironment().resolveRequiredPlaceholders(path);
    }

The getEnvironment() method is defined by the ConfigurableApplicationContext interface and implemented in AbstractApplicationContext. In fact, it is to determine whether the environment is empty or not. If it is not empty, create a StandardEnvironment

@Override
    public ConfigurableEnvironment getEnvironment() {
        if (this.environment == null) {
            this.environment = createEnvironment();
        }
        return this.environment;
    }
    protected ConfigurableEnvironment createEnvironment() {
        return new StandardEnvironment();
    }

Spring bean parsing is in the refresh method. All spring initialization is completed in this method, which is implemented in AbstractApplicationContext

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

//fresh preparation, including setting the startup time, whether to activate the identification bit, and initializing the property source configuration

protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);

        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }

        // Initialize any placeholder property sources in the context environment
        //This method is empty
        initPropertySources();

        // Validate that all properties marked as required are resolvable
        // see ConfigurablePropertyResolver#setRequiredProperties
        //Attribute checking
        getEnvironment().validateRequiredProperties();

        // Allow for the collection of early ApplicationEvents,
        // to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    }

Create beanFactory
Call the obtainFreshBeanFactory method of AbstractApplicationContext to get the obtainFreshBeanFactory

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //This method is implemented in AbstractRefreshableApplicationContext
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

refreshBeanFactory method

@Override
    protected final void refreshBeanFactory() throws BeansException {        
    //Destroy BeanFactory if it already exists
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
        //Create a DefaultListableBeanFactory 
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //Customized beanFactory, implemented by AbstractRefreshableApplicationContext
            customizeBeanFactory(beanFactory);
            //Load bean, implemented by AbstractXmlApplicationContext
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

Custom bean, implementation of customizeBeanFactory method

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }

Loading bean

@Override
    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 bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

Tags: Spring xml encoding Attribute

Posted on Wed, 01 Apr 2020 05:09:50 -0700 by marginalboy