A thorough understanding of Bean analysis, creation, and use in Spring

Posted by fusionpixel on Sun, 28 Jun 2020 02:23:28 +0200

Spring Loads Beans, Instantiates Beans, Gets Bean Processes

The purpose of this paper is to analyze the process of Spring loading beans, instantiating beans, and getting beans by analyzing the source code. Some of the core content will be explained in the source code.Content is dull, careful!

  • Step one, start a Spring project

Spring Startup Entry

from Official Documents Here's how you can get started with Spring.

We passed in oneTest.xmlfile

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/test.xml");

  • xml file content
<?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 id="stringutil" class="com.baigt.utils.StringUtils"></bean>
</beans>

  • bean object (StringUtils)
public class StringUtils{
// some code
}

Bean parsing for source analysis

Analyzing Bean parsing process, instantiation process from source level,

Entry ClassPathXmlApplicationContext

Look at the class diagram first, and the code in different levels will be used repeatedly in subsequent source code.

ClassPathXmlApplicationContext instantiation

	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		this(new String[] {configLocation}, true, null);
	}
	// Omit some code 
	
	public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
		throws BeansException {

	super(parent);
	//The current ClassPathXmlApplicationContext is also a subclass of resource
	setConfigLocations(configLocations);
	//The refresh passed in front is true, executing the refresh method
	if (refresh) {
		refresh();
	}
}

AbstractApplicationContext#refresh

org.springframework.context.support.AbstractApplicationContext#refresh,AbstractApplicationContext is the parent of ClassPathXmlApplicationContext.Here refresh overrides the refresh method of Configurable ApplicationContext

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Pre-preparation for refresh, such as setting startTime, turning on activation state, closing state, etc.
			prepareRefresh();

			//Tell the subclass to refresh the content Bean factory (it is obvious from the class diagram that the entry class instance is also a bean factory)
			// Watch and refresh BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//Pre-set some properties used in this context, such as Classloader, Callback, environment, etc.
			prepareBeanFactory(beanFactory);

			try {
				// Notify the context subclass and post-process the beanFactory.For example, use a series of Webcontext subclasses
				postProcessBeanFactory(beanFactory);

				// Register BeanFactoryPostProcessor as a Bean in the current Context
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register BeanPostProcessor to intercept post-processing of Bean creation.
				registerBeanPostProcessors(beanFactory);

				// Initialize MessageSource for the current Context
				initMessageSource();

				// Initialize application event broadcasting for the current context
				initApplicationEventMulticaster();

				// Initialize other special bean objects such as webcontext
				onRefresh();

				// Check the listening beans and publish them (ApplicationListener)
				registerListeners();

				// Instantiate all other collection of singleton objects in BeanFactory (non-delayed)
				finishBeanFactoryInitialization(beanFactory);

				// Finally, publish Lifecycle Processor and ContextRefreshedEvent events
				finishRefresh();
			}

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

				// Failed to destroy bean s
				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();
			}
		}
	}


BeanFactory creation

If you know the BeanFactory, you know this class is an important foundation object for Spring.

Extend BeanFactory explanation
  • Is the root interface to access the Spring Bean container.Is a basic client, more features such as ListableBeanFactory, ConfigurableBeanFactory.

  • The implementation classes of this interface generally hold multiple BeanDefinition object information, such as number, Scope, instance, name, and so on.(comparable ListableBeanFactory)

  • BeanFactory is a central registry (registration) for the Application component

  • Typically, BeanFactory loads Bean data from configuration sources such as Xml and stores it in the factory.

  • In the case of HierarchicalBeanFactory, almost all methods in ListableBeanFactory check to see if they are parent factories.

  • beanFactory should support the following standard life cycles

<li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>
 *
 * <p>On shutdown of a bean factory, the following lifecycle methods apply:
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition

AbstractApplicationContext#obtainFreshBeanFactory
  • Continue BeanFactory creation process analysis
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// If a factory already exists, destroy it directly before rebuilding it
		refreshBeanFactory();
		//Basically from the beanFactory created above
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

AbstractRefreshableApplicationContext#refreshBeanFactory

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory.If a factory already exists, destroy it directly and rebuild it.The new factory loadBeanDefinitions.

Extended BeanDefinition Terms

BeanDefinition describes the properties that a Bean instance has, such as Scope (singleton or Prototype),beanClassName, whether it is delayed loading, dependencies, and so on (and other properties).Of course, this is the smallest BeanDefiniton interface, and RootBeanDefinition is a more powerful subclass implementation.

  • Back to BeanFactory creation.
	protected final void refreshBeanFactory() throws BeansException {
		//If a bean factory destroys beans, close the bean factory
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//Create DefaultListableBeanFactory, which is a subclass of BeanDefinitionRegistry
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			customizeBeanFactory(beanFactory);
			//Load BeanDefinition (in this case, parse the Bean tag in Xml and load it into BeanDefinition)
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				//Assign to beanFactory in Context
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			
		}
	}

AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory).Here's just an example of the current Xml approach that will enter here.

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create an XmlBeanDefinitionReader instance with the given beanFactory(BeanDefinitionRegistry)
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		// ClassPathXmlApplicationContext is also a ResouceLoader
		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);
		// Generate BeanDefinition by XmlBeanDefinitionReader parsing
		loadBeanDefinitions(beanDefinitionReader);
	}
	
	//Connect
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		// Incoming in EntryTest.xmlStored inThis.configLocationsYes, you can get it here.
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String...)

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(java.lang.String...).Read from incoming path.

	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}

	//Connect
		public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}
	// Connect  
	// The class diagram shows that this object (ClassPathXmlApplicationContext) is also an instance of DefaultResourceLoader and has been set into reader, so follow the else logic
	public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			// Resource pattern matching available.
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int loadCount = loadBeanDefinitions(resources);
				if (actualResources != null) {
					for (Resource resource : resources) {
						actualResources.add(resource);
					}
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
				}
				return loadCount;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			// Can only load single resouce locations from absolute paths that were passed in for usTest.xmlRoute
			Resource resource = resourceLoader.getResource(location);
			//Let's follow up!!!
			int loadCount = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
			}
			return loadCount;
		}
	}

XmlBeanDefinitionReader#loadBeanDefinitions(Resource)

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource).Loading Beans from xml

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

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		//...omit code
		try {
			// Front we passed inTest.xmlInput Flow
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//True load bean definition from xml
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			
		}
	}

// Connect
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			// Parse xml file as Document
			Document doc = doLoadDocument(inputSource, resource);
			return registerBeanDefinitions(doc, resource);
		}
		catch (BeanDefinitionStoreException ex) {
			// Omit Code
		}
	}
// Connect
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		// Register BeanDefinition from reader to factory
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#registerBeanDefinitions.Register BeanDefinition objects.

	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}
	// Followed by parsing the xml through delegation mode and template mode   
	protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);
		// Omit code...

		preProcessXml(root);
		//Focus only on this code
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}
//Continue to focus only on Spring's own parsing
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						// Spring's own tag resolution
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}
	//Connect to nested support for parsing Import tags, alias, bean s
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			//Attention should be paid to resolving the bean tag here in the example
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

	//Connect to process BeanDefinition
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// Core parsing steps (using delegation mode)
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register final decoration instance
				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));
		}
	}


BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element)

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element).True xml to BeanDefinition logic code.

	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}
	// Parse the xml, generate an AbstractBeanDefinition object instance, and give it to AbstractBeanDefinition management
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>();
		//If the name tag is used, alias name
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		// Parse element content into BeanDefinition
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				}
				catch (Exception ex) {
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			//Wrap as BeanDefinitionHolder object
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		try {
			String parent = null;
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
			//Create basic BeanDefinition objects, set beanName, ParentName, ClassLoader, and so on
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			//Resolve attribute tags such as singleton, lazy-init, scope, abstract, and so on, and set them to the BeanDefinition instance (hereinafter referred to as bd)
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			// Resolve description s tags set to Bd objects
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			// Resolve meta tags set to bd objects
			parseMetaElements(ele, bd);
			
			// Resolve lookup-method tags set to bd objects
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			// Resolve replaced-method tags set to bd objects
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			// Resolve constructor-arg tags set to bd objects
			parseConstructorArgElements(ele, bd);
			// Resolve property tags set to bd objects (such as url s, user s, pwd properties that we inject when using datasource)
			parsePropertyElements(ele, bd);
			// Resolve qualifier tags set to bd objects
			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;
	}

	protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
			throws ClassNotFoundException {

		return BeanDefinitionReaderUtils.createBeanDefinition(
				parentName, className, this.readerContext.getBeanClassLoader());
	}
org.springframework.beans.factory.support.BeanDefinitionReaderUtils#createBeanDefinition

	public static AbstractBeanDefinition createBeanDefinition(
			String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {

		GenericBeanDefinition bd = new GenericBeanDefinition();
		bd.setParentName(parentName);
		if (className != null) {
			if (classLoader != null) {
				bd.setBeanClass(ClassUtils.forName(className, classLoader));
			}
			else {
				bd.setBeanClassName(className);
			}
		}
		return bd;
	}

Return to DefaultBeanDefinition DocumentReader#processBeanDefinition

Layer 1 call returns, returns toOrg.springframework.beans.Factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition.We continue to analyze BeanDDefinitionReaderUtils.registerBeanDefinitionPart.This part is the step to actually associate BeanDefiniton with the current Context.

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				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));
		}
	}

org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition

Give the BeanDefiniton Holder holds to the BeanDefinitionRegistry (the current context is also a registry instance, DefaultListableBeanFactory)

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		// Core focus on this logic
		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);
			}
		}
	}

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

Enter this method for the first time, 1. beanDefinition is an instance of AbstractBeanDefinition type, validate;2. oldBeanDefinition is empty, execute else code 3. BeanCreationStarted is false, perform beanDefinitionMap, beanDefinitionNames, manualSingletonNames value operations.

  • Pay special attention to these objects (beanDefinitionMap, beanDefinitionNames, manualSingletonNames), which you will use when instantiating and retrieving beans
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");
		// validate if it is an instance of AbstractBeanDefinition type
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		// First entry old is empty
		if (oldBeanDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(oldBeanDefinition)) {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
		//First false
			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<String>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				//It is still in the start-up registration phase (i.e., there is no real instantiation, just the property definition of the bean is taken, and it is not directly usable yet).)
				
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

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

SpringBean Creation

After BeanDefiniton is injected into the registry, step by step back to the AbstractApplicationContext#refresh method, where we focus only on the basic Bean instantiation process.

synchronized (this.startupShutdownMonitor) {
			try {
				
				// Mainly this code
				finishBeanFactoryInitialization(beanFactory);

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

AbstractApplicationContext#finishBeanFactoryInitialization
  • org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

finishBeanFactoryInitialization.Instantiate other normal collection of non-delayed loaded instances held by BeanFactory.Look down here at the "preInstantiateSingletons" method

	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		//Omit code...

		// Instantiate other normal collection of non-delayed loaded instances held by BeanFactory
		beanFactory.preInstantiateSingletons();
	}

DefaultListableBeanFactory#preInstantiateSingletons

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons.There are two types of beans created, FactoryBean and Ordinary Bean.Here we will only analyze ordinary beans.

  • Notice the "this.beanDefinitionNames"Is"obtainFreshBeanFactory()"to create assignments.BeanDefinition of our StringUtils.
		List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
				else {
					//We are focusing on this locality
					getBean(beanName);
				}
			}
		}

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)

Continue to follow up

	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

(singleton)org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

Here we are going to create an instance of the singleton (fetch it from the cache if you have one).The way to create it is through the createBean method in the ObjectFactory internal class implementation.Let's start with the logic of getSingleton.

		// Logic that first comes in empty and last goes down
		Object sharedInstance = getSingleton(beanName);
		// adoptThis.beanDefinitionMapYou can see the source code yourself.It's not a very long story here.
		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		//...
		if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
							 	//Logic to ultimately create beans
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
	//....		
	// Note here that the single cache is set up and can be used directly later
	if (newSingleton) {
		addSingleton(beanName, singletonObject);
	}

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

The core logic we're going to analyze here (instance singleton) is called ObjectFactory.getObject That is, we have the inner class above, and the implementation of the inner class is done through createBean.Let's look at the logic of createBean.

			try {
					//Returning to the getObject method of the ObjectFactory of AbstractBeanFactory#doGetBean, execute the createBean method in it
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

Subclass implementation of AbstractBeanFactory

	AbstractAutowireCapableBeanFactory#createBean(java.lang.Class<T>)
	public <T> T createBean(Class<T> beanClass) throws BeansException {
		// Use prototype bean definition, to avoid registering bean as dependent bean.
		RootBeanDefinition bd = new RootBeanDefinition(beanClass);
		bd.setScope(SCOPE_PROTOTYPE);
		bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
		return (T) createBean(beanClass.getName(), bd, null);
	}

// Connect
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		
		RootBeanDefinition mbdToUse = mbd;
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			
		}
		// Instance Creation for Ordinary Bean s
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}


AbstractAutowireCapableBeanFactory#doCreateBean

The core concern is the processing of instanceWrapper and exposedObject objects

	BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//Create a Wrapper object for a bean instance
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		// bean instances have been created in wrapper (incomplete)
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		//Omit some code.
		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// Inject property into Bean
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}
		//Omit some code.
		return exposedObject;

AbstractAutowireCapableBeanFactory#createBeanInstance

instanceWrapper = createBeanInstance(beanName, mbd, args); this method creates Bean objects for lass with a specified name and supports three strategies: parameterless, factoryMethod, AutoWireConstructor.Default execution of "instantiateBean" without parameters

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		// Normally we are not FactoryMethod and have a construct (or can have a hash)
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName, mbd, ctors, args);
		}
		//Use parameterless construction instances without special processing
		// No special handling: simply use no-arg constructor.
		return instantiateBean(beanName, mbd);
	}

AbstractAutowireCapableBeanFactory#instantiateBean

Generate an instance through "getInstantiationStrategy().instantiate(mbd, beanName, parent)".

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			if (System.getSecurityManager() != null) {
				beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
					@Override
					public Object run() {
						return getInstantiationStrategy().instantiate(mbd, beanName, parent);
					}
				}, getAccessControlContext());
			}
			else {
				// This code logic is typically used to generate bean instances
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

SimpleInstantiationStrategy#instantiate

org.springframework.beans.factory.support.SimpleInstantiationStrategy#Instantiate(Org.springframework.beans.Factory.support.RootBeanDefinition,Java.lang.String,Org.springframework.beans.Factory.BeanFactory).Get an instance of the lass construction method for the corresponding BeanName in BeanDefinition from bd and hand it to BeanUtils to instantiate the real bean object

public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		if (bd.getMethodOverrides().isEmpty()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
								@Override
								public Constructor<?> run() throws Exception {
									return clazz.getDeclaredConstructor((Class[]) null);
								}
							});
						}
						else {
							//Gets the Constructor instance of the Class defined by the bean tag in xml
							constructorToUse =	clazz.getDeclaredConstructor((Class[]) null);
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			//Instantiate a Class defined by a bean tag in xml
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

Return to the AbstractAutowireCapableBeanFactory#doCreateBean method

Let's continue to look at what exposedObject does.Load Bean's Property, initBean object.Let's focus on the initializeBean method.

final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Object exposedObject = bean;
		try {
			//Loading properties such as Property can be other Bean objects or basic properties such as String.See the applyPropertyValues method in populateBean
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				//Initialize Bean Object
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}

AbstractAutowireCapableBeanFactory#initializeBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

Initialize the given Bean (execute BeanPost when RootBeanDefinition is empty), execute the related methods of wired (BeanNameAware, BeanClassLoaderAware, BeanFactoryAware), and execute initMethod.For example, InitializingBean#afterPropertiesSet(); or a custom init method.

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			//Method to execute wire s (BeanNameAware, BeanClassLoaderAware, BeanFactoryAware)
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//Execute init method
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

AbstractAutowireCapableBeanFactory#invokeInitMethods

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods.Execute the afterPropertiesSet method.If it is a custom init method, invokeCustomInitMethod is called.

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
							((InitializingBean) bean).afterPropertiesSet();
							return null;
						}
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null) {
			String initMethodName = mbd.getInitMethodName();
			if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}


Return AbstractApplicationContext#refresh

This Bean instantiation is complete.

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

SpringBean Get

Or our example, in the ApplicationContext instance we returned, there is a getBean method, so let's focus on the implementation of getBean.

 		//ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/test.xml");
        context.getBean(StringUtils.class);

AbstractApplicationContext#getBean

	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

DefaultListableBeanFactory#getBean(java.lang.Class<T>)

org.springframework.beans.factory.support.DefaultListableBeanFactory#GetBean(Java.lang.Class<T>).The source code logic of resolveNamedBean is analyzed here.

	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}
	
	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		//Get NamedBeanHolder Object Core Get SpringBean Logic
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
		if (namedBean != null) {
			//Finally, return to the instance here
			return namedBean.getBeanInstance();
		}
		BeanFactory parent = getParentBeanFactory();
		if (parent != null) {
			return parent.getBean(requiredType, args);
		}
		throw new NoSuchBeanDefinitionException(requiredType);
	}
	//Connect


DefaultListableBeanFactory#resolveNamedBean(java.lang.Class<T>, java.lang.Object...)

The source code in the example executes "new NamedBeanHolder<T> (beanName, getBean (beanName, requiredType, args)".BeanName=Test.xmlID defined in, that is, "stringutil".Below we will focus on the logic of the getBeanNamesForType and getBean methods.

//requiredType= StringUtil  args=null
private <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
		// There is only one ["stringutil"] in the example of getting names based on Class type
		String[] candidateNames = getBeanNamesForType(requiredType);

		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<String>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}
		// In our example, length==1, beanName=stringutil is consistent with the id we defined
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			//Note the execution logic of the getBean method
			return new NamedBeanHolder<T>(beanName, getBean(beanName, requiredType, args));
		}
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = new LinkedHashMap<String, Object>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName)) {
					candidates.put(beanName, getBean(beanName, requiredType, args));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			String candidateName = determinePrimaryCandidate(candidates, requiredType);
			if (candidateName == null) {
				candidateName = determineHighestPriorityCandidate(candidates, requiredType);
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType, args);
				}
				return new NamedBeanHolder<T>(candidateName, (T) beanInstance);
			}
			throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
		}

		return null;
	}

DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class<?>)

Finally, when parsing the xml (loadBeanDefinition), use theThis.beanDefinitionNamesGet the beanName in the collection.See the source code for the "doGetBeanNamesForType" method below.

	public String[] getBeanNamesForType(Class<?> type) {
		return getBeanNamesForType(type, true, true);
	}
	// type==StringUtil is not empty
	public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
			return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
		}
		//cache is empty size==0
		Map<Class<?>, String[]> cache =
				(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
		String[] resolvedBeanNames = cache.get(type);
		if (resolvedBeanNames != null) {
			return resolvedBeanNames;
		}
		// Will do this!!!!
		resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
		if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
			cache.put(type, resolvedBeanNames);
		}
		return resolvedBeanNames;
	}
// fromThis.beanDefinitionNamesGet beanName in
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		List<String> result = new ArrayList<String>();

		// Check all bean definitions.
		for (String beanName : this.beanDefinitionNames) {
			// Only consider bean as eligible if the bean name
			// is not defined as alias for some other bean.
			if (!isAlias(beanName)) {
				try {
					RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
					// Only check bean definition if it is complete.
					if (!mbd.isAbstract() && (allowEagerInit ||
							(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
									!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
						// In case of FactoryBean, match object created by FactoryBean.
						boolean isFactoryBean = isFactoryBean(beanName, mbd);
						BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
						boolean matchFound =
								(allowEagerInit || !isFactoryBean ||
										(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
								(includeNonSingletons ||
										(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
								isTypeMatch(beanName, type);
						if (!matchFound && isFactoryBean) {
							// In case of FactoryBean, try to match FactoryBean instance itself next.
							beanName = FACTORY_BEAN_PREFIX + beanName;
							matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
						}
						if (matchFound) {
							//This will be done last
							result.add(beanName);
						}
					}
				}
				catch (CannotLoadBeanClassException ex) {
					
				}
				catch (BeanDefinitionStoreException ex) {
					
				}
			}
		}

		

		return StringUtils.toStringArray(result);
	}

AbstractBeanFactory#getBean(String, Class<T>, Object...)

The process of creating a singleBean takes a closer look at the code created, which is not covered here.

	public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
		return doGetBean(name, requiredType, args, false);
	}
	
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		// Get from the cache.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		//Omit code created by bean s
		return (T) bean;
	}

Return to the DefaultListableBeanFactory#getBean's "namedBean.getBeanInstance()"method
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}

Get Completed

Return to "Context.getBean(StringUtils.class";", get a Bean instance"

StringUtils sutils=context.getBean(StringUtils.class);

epilogue

The Spring version used for analysis is 4.3.18.If there are any discrepancies in the code, please distinguish them by yourself.Finally, if there are any errors, please correct them.Author: ricky QQ Group: 244930845.

Topics: Programming xml Spring Java encoding