IOC Source -- Understanding Bean Loading Process

Keywords: xml Spring Java Attribute

1. Bean Loading Principle

Loading process: through ResourceLoader and its sub-class DefaultResourceLoader to locate the location of Resource files, realize the function of locating Resource files from class path, file system, url and so on. After locating, the Resource object is obtained, and then handed to BeanDefinitionReader. It is then delegated to BeanDefinitionParserDelegate to complete the analysis of bean s and obtain BeanDefinition object, and then through registration. The rBeanDefinition method is registered. The ibu in the IOC container maintains a HashMap to save the BeanDefinition object. The BeanDefinition in Spring is actually the JavaBean we use.

What is BeanDefinition Object

BeanDefinition is an interface that describes a bean instance with attribute values, constructor parameter values, and more information provided by the implementation.

Pay attention to understanding the loading process

Before you start, you need to read and understand this process carefully. With this process, the difficulty of reading source code is less than half.

Most of the source codes are annotated, and some are official English annotations. Chinese is the main line (this article is also mainly through the main line), in order to be comprehensive, you need to explore again.

1. bean.xml

A common bean configuration file, here I want to emphasize the format inside it, because it will be used when parsing tags. It has labels such as < beans > `beans > `import > ``alias > etc. They are parsed and translated into BeanDefinition objects below.

<beans>

  <!-- this definition could be inside one beanRefFactory.xml file -->
  <bean id="a.qualified.name.of.some.sort"
      class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <property name="configLocation" value="org/springframework/web/context/beans1.xml"/>
  </bean>

  <!-- while the following two could be inside another, also on the classpath,
    perhaps coming from another component jar -->
  <bean id="another.qualified.name"
      class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <property name="configLocation" value="org/springframework/web/context/beans1.xml"/>
    <property name="parent" ref="a.qualified.name.of.some.sort"/>
  </bean>

  <alias name="another.qualified.name" alias="a.qualified.name.which.is.an.alias"/>

</beans>

2. ResourceLoader.java

Policy interface for loading resources(Strategy mode).
DefaultResourceLoader is a standalone implementation that is usable outside an ApplicationContext, also used by ResourceEditor

An ApplicationContext is required to provide this functionality, plus extended ResourcePatternResolver support.

public interface ResourceLoader {

    /** Pseudo URL prefix for loading from the class path: "classpath:". */
    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;

        // Returns a Resource object (an object that specifies the location of the configuration file)
    Resource getResource(String location);

        // Return lassLoader of ResourceLoader
    @Nullable
    ClassLoader getClassLoader();
}

Then let's look at DefaultResourceLoader's implementation of the getResource() method.

    public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");

        for (ProtocolResolver protocolResolver : this.protocolResolvers) {
            Resource resource = protocolResolver.resolve(location, this);
            if (resource != null) {
                return resource;
            }
        }
               // If location begins with/
        if (location.startsWith("/")) {
            return getResourceByPath(location);
        }
                // If location begins with classpath:
        else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
        }
        else {
            try {
                // Try to parse the location as a URL...
                URL url = new URL(location);
                return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
            }
            catch (MalformedURLException ex) {
                // No URL -> resolve as resource path.
                return getResourceByPath(location);
            }
        }
    }

As you can see, it judges three scenarios: / classpath: url format matching, and then calls the corresponding processing method. I only analyze classpath:, because this is the most commonly used. So take a look at the ClassPathResource implementation:

    public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
        Assert.notNull(path, "Path must not be null");
        String pathToUse = StringUtils.cleanPath(path);
        if (pathToUse.startsWith("/")) {
            pathToUse = pathToUse.substring(1);
        }
        this.path = pathToUse;
        this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
    }

Looking at the above code means that when you configure the static resource file path, you don't have to tangle with the classpath: you don't need to write /, because if you write it, it will filter it out for you.

So how do URLs locate?

Tracking getResourceByPath(location) method:

    @Override
    protected Resource getResourceByPath(String path) {
        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        // Here we use file system resource objects to define bean files
        return new FileSystemResource(path);
    }

Okay, obviously... we're off track, because what we want is xml file and path parsing, but fortunately, no change of soup or dressing. This will be covered below.

Triggering bean loading

Back to the point, when we use spring to load beans. XML manually, we use:

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");

Start with the ClassPathXmlApplicationContext class:

3. ClassPathXmlApplicationContext.java

There are only one constructor (multiple) and one getConfigResources() method in this class. The constructor eventually goes to the following constructor (adapter pattern):

    public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {
    // Dynamic determination of which loader to load the configuration file
        1.super(parent);
    // Tell the reader where the profile is and locate the load profile
        2.setConfigLocations(configLocations);
    // Refresh
        if (refresh) {
            // Before IOC containers are created, if they already exist, they need to be destroyed and closed to ensure refresh.
            //Later, a new IOC container was used.
            3.refresh();
        }
    }

Note: This class is critical, and I think it defines a Life Cycle for an xml loaded bean:

  1. The super() method completes the designation of the class loader.
  2. setConfigLocations(configLocations); Method locates and parses the configuration file to get the Resource object.
  3. refresh(); Method parses the label to get the BeanDefition object and registers it with the IOC container after checking. (Main research methods)

I marked 1.2.3. Correspond to the following method x, easy to read.

First, get to know setConfigLocations(configLocations) in depth.

Method 2. setConfigLocations(configLocations)
    // Resolve Bean s to define resource file paths and process multiple resource file string arrays
    public void setConfigLocations(@Nullable 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++) {
                // resolvePath is a method of parsing strings into paths in the same class
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }

Then we continue to look at the refresh() method of ClassPathXmlApplicationContext above:

Method 3. refresh()
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Preparing context for refresh
            prepareRefresh();

            // Notify subclasses to refresh Bean factories
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Use this context to prepare the bean factory
            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();
            }
        }
    }

Note: The following methods are all about refresh() in-depth reading, this method sets a very deep set, the following reading may cause discomfort.

Then look at the obtainFreshBeanFactory() method in refresh():

Method 3.1 obtainFreshBeanFactory()
    // Call -- Refresh the bean factory
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // Delegation pattern: The parent class defines the refreshBeanFactory method, which specifically implements calling subclass containers
        refreshBeanFactory();
        return getBeanFactory();
    }

Then look at the refreshBeanFactory() method of obtainFreshBeanFactory().

Method 3.1.1 refreshBeanFactory()
       // Refresh bean factory
    protected final void refreshBeanFactory() throws BeansException {
        // If there are containers, destroy and close them first
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // Create IOC containers
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // Initialization of containers
            customizeBeanFactory(beanFactory);
            // Call the method defined by the loading Bean (using delegation mode)
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

Then follow the loadBeanDefinitions() method of refreshBeanFactory():

Method 3.1.1.1 loadBeanDefinitions()

Loading Bean Definition through XmlBean Definition Reader

    // Loading Bean Definition through XmlBean Definition Reader
    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        // Create a new XmlBean Definition Reader for bean Factory
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        // Set up Spring resource loader for Bean reader (because grandfather class is a subclass of ResourceLoader, so is ResourceLoader)
        beanDefinitionReader.setResourceLoader(this);
        //  Setting up SAX xml parser DOM4J for Bean reader
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        // Initialize BeanDefinition Reader
        initBeanDefinitionReader(beanDefinitionReader);
        // Real load bean definitions
        loadBeanDefinitions(beanDefinitionReader);
    }

Follow up the loadBean Definitions (XmlBean Definition Reader reader) method in the loadBean Definitions (DefaultListableBeanFactory BeanFactory) method:

Method 3.1.1.1.1 loadBeanDefinitions()

XMLBean reader loads BeanDefinition resources

    // XMLBean Reader Loads Bean Definition Resources
    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        // Location of Bean Definition Resources
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            // The XMLBean reader calls its parent AbstractBean DefinitionReader to read and locate Bean Definition Resources
            reader.loadBeanDefinitions(configResources);
        }
        // If the bean acquired in the subclass defines that the resource is positioned empty,
        // Get the resources set by the setConfigLocations method in the FileSystem Xml Application Context constructor
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            // The XMLBean reader calls its parent AbstractBean DefinitionReader to read and locate Bean Definition Resources
            reader.loadBeanDefinitions(configLocations);
        }
    }

    @Override
    public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int count = 0;
        //
        for (Resource resource : resources) {
            count += loadBeanDefinitions(resource);
        }
        return count;
    }

Following loadBeanDefinitions(): This is just an abstract method to find the implementation of the XmlBeanDefinitionReader subclass:

    @Override
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        return loadBeanDefinitions(new EncodedResource(resource));
    }

Further into loadBean Definitions:

Loading bean s through explicit xml files

    // Loading bean s through explicit xml files
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (logger.isTraceEnabled()) {
            logger.trace("Loading XML bean definitions from " + encodedResource);
        }

        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet<>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
        try {
            // Converting resource files to the IO stream of InputStream
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
                // Obtaining xml parsing resources from streams
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    // Set encoding
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
                // Specific reading process
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
            finally {
                inputStream.close();
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
        finally {
            currentResources.remove(encodedResource);
            if (currentResources.isEmpty()) {
                this.resourcesCurrentlyBeingLoaded.remove();
            }
        }
    }

Further into doLoadBean Definitions ():

Really start loading BeanDefinitions

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {

        try {
            // Converting xml files to DOM objects
            Document doc = doLoadDocument(inputSource, resource);
            // Define the parsing process for beans, which uses Spring's bean configuration rules
            int count = registerBeanDefinitions(doc, resource);
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + count + " bean definitions from " + resource);
            }
            return count;
        }
        ...  ...  ..
}

The doLoadDocument() method parses the flow and returns a Document object: return builder.parse(inputSource); to avoid disrupting the idea, do it yourself.

You need to go further: registerBeanDefinitions()

Register BeanDefinitions

    public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        // Get the number of bean s registered in the container
        int countBefore = getRegistry().getBeanDefinitionCount();
        // Parsing process entry, where delegation mode is used
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        // Number of bean s for statistical parsing
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }

Further into the registerBeanDefinitions() method (which is the result of the delegation pattern):

    @Override
    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        // Get the XML descriptor
        this.readerContext = readerContext;
        doRegisterBeanDefinitions(doc.getDocumentElement());
    }

Deep into doRegisterBean Definitions (doc. getDocumentElement ();:

Really start registering BeanDefinitions:

protected void doRegisterBeanDefinitions(Element root) {
        // Any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);

        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                // We cannot use Profiles.of(...) since profile expressions are not supported
                // in XML config. See SPR-12458 for details.
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                "] not matching: " + getReaderContext().getResource());
                    }
                    return;
                }
            }
        }

        // Before the bean parses the definition, do a custom parse to see if it is a user-defined tag?
        preProcessXml(root);
        // Start parsing the document object defined by the bean
        parseBeanDefinitions(root, this.delegate);
        // After parsing the bean definition, customize the parsing to increase the scalability of the parsing process
        postProcessXml(root);

        this.delegate = parent;
    }

Next, look at parseBean Definitions (root, this. delegate);:

The root element of the document begins to parse and translate into Bean Definitions

    // Starting with the root element of document, parse and translate it into Bean Definitions
    protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        // The document object defined by the bean uses spring's default xml namespace
        if (delegate.isDefaultNamespace(root)) {
            // Gets all byte points of the document object root element defined by the bean
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                // Getting the document node is an xml element node
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    // The document element node defined by the bean uses spring's default xml namespace
                    if (delegate.isDefaultNamespace(ele)) {
                        // Resolving Element Nodes Using spring's bean Rules
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        // Instead of using spring's default xml namespace, user-defined parsing rules are used to parse element nodes
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        // Parse < import > tag elements and import parsing
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        // alias
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        // bean
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        // beans
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

ImportBean Definition Resource (ele), `process Alias Registration (ele), `process Bean Definition (ele, delegate)'; these three methods show the detailed process of tag parsing.
As you can see, it actually uses DOM4J to parse tags such as import bean alias, and then recursively within the tag until all the attributes are obtained and encapsulated in the BeanDefition object. For example, the processBeanDefinition method:

Give me an element to parse into Bean Definition

    // Give me an element to parse into Bean Definition
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        // Real Analytical Process
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // Register the final decorated instance.
                // Registration: Register db to ioc, delegation mode
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

Continue to dig deeper into registerBeanDefinition():

Register BeanDefinitions to the bean factory

    // Register BeanDefinitions to the bean factory
    // Definition Holder: bean definition, including name and aliases
    // registry: Registered bean factory
    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();
        // True registration
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

Further into registry. registerBeanDefinition (beanName, definition Holder. getBeanDefinition ());

Register BeanDefinitions to IOC Containers

Note: The class of this method is the interface, and what we're looking at is the method implemented by DefaultListableBeanFactory.java.

    // Implement the BeanDefinition Registry interface and register BeanDefinitions 
    @Override
    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");

        // Is the check AbstractBean Definition?
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                // Markup bean Definition takes effect
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }

        // Determine whether the bean already exists in the bean Definition Map
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        //If there is no such bean
        if (existingDefinition != null) {
            //If bd is not allowed to overwrite registered bean s, an exception is thrown
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            }
            // If overwriting is allowed, then the bean with the same name, registered overwriting is registered first.
            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 + "]");
                }
            }
            // Register to a container, beanDefinitionMap is a container
            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;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

This method checks the beans that need to be loaded and put s them into the bean Definition Map if there is no problem. The bean Definition Map is actually IOC. So our beans are loaded into the IOC container.

Posted by phpMover on Mon, 06 May 2019 22:15:40 -0700