QQ 425343603 Java Learning Exchange Group (717726984)

The current source version of Spring is 5.2.10.release

Spring source code parsing notes (2) start process (1).

On an article, we define the bean (beanDefinition) loading is completed, the next step is to set the we load bean instantiation, we skip the unnecessary part, middle to finishBeanFactoryInitialization this method directly.

If you want to see how the core is implemented directly, rather than reading the previous source code, you can do the reverse and work backwards from the conclusion.

Complete the Bean factory initialization (finishBeanFactoryInitialization)

/** * Completes the initialization of the bean factory for this context, initializing all remaining singleton beans. * /
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// Initialize the transformation service for this context.
	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
		beanFactory.setConversionService(
				beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
	}

	// If there is no bean post-handler, register a default embedded value parser
	/ / (for example accomplished beans) before any registered:
	// At this point, it is mainly used to comment the parsing of attribute values.
	if(! beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); }// Initialize LoadTimeWeaverAware beans early to allow their converters to be registered early.
	String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false.false);
	for (String weaverAwareName : weaverAwareNames) {
		getBean(weaverAwareName);
	}

	// Stop using temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allows caching of all bean definition metadata without further changes.
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy initialization) singletons. (Here is the instantiation entry)
	beanFactory.preInstantiateSingletons();
}
Copy the code

PreInstantiateSingletons preInstantiateSingletons preInstantiateSingletons preInstantiateSingletons

preInstantiateSingletons

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

@Override
public void preInstantiateSingletons(a) throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}

	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

	// Trigger the initialization of all non-lazy-loaded singleton beans...
	for (String beanName : beanNames) {
		// Get the bean definition
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		// Not abstract class and singleton and not lazy initialization
		if(! bd.isAbstract() && bd.isSingleton() && ! bd.isLazyInit()) {// Is a factory bean
			if (isFactoryBean(beanName)) {
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceofFactoryBean) { FactoryBean<? > factory = (FactoryBean<? >) bean;boolean isEagerInit;
					if(System.getSecurityManager() ! =null && factory instanceofSmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<? >) factory)::isEagerInit, getAccessControlContext()); }else {
						isEagerInit = (factory instanceofSmartFactoryBean && ((SmartFactoryBean<? >) factory).isEagerInit()); }if(isEagerInit) { getBean(beanName); }}}else {
				// Normal bean definitions go through this entry
				// (here is the instantiation entry)getBean(beanName); }}}Copy the code

The main purpose here is to determine the factoryBean and its associated processing, and our general bean object goes to the last logical step. Let’s move on to the doGetBean implementation.

Get the bean (doGetBean)

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

protected <T> T doGetBean(
		String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
		throws BeansException {

	// Get the bean name
	String beanName = transformedBeanName(name);
	Object bean;

	// Eagerly check the singleton cache for manually registered singletons.
	// Get a singleton object from the cache
	Object sharedInstance = getSingleton(beanName);
	if(sharedInstance ! =null && args == null) {
		if (logger.isTraceEnabled()) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
						"' that is not fully initialized yet - a consequence of a circular reference");
			}
			else {
				logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	// The previous logic basically does not walk during initialization.

	else {
		// Determine if the prototype is currently being created
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// Check the parent factory
		BeanFactory parentBeanFactory = getParentBeanFactory();
		if(parentBeanFactory ! =null && !containsBeanDefinition(beanName)) {
			// If not, find the parent factory
			String nameToLookup = originalBeanName(name);
			if (parentBeanFactory instanceof AbstractBeanFactory) {
				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
						nameToLookup, requiredType, args, typeCheckOnly);
			}
			else if(args ! =null) {
				// Delegation to parent with explicit args.
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else if(requiredType ! =null) {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
			else {
				return(T) parentBeanFactory.getBean(nameToLookup); }}if(! typeCheckOnly) { markBeanAsCreated(beanName); }try {
			// Get the bean definition
			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			// Check the merge Bean definition
			checkMergedBeanDefinition(mbd, beanName, args);

			// Ensure the initialization of the bean on which the current bean depends.
			String[] dependsOn = mbd.getDependsOn();
			// The dependency exists
			if(dependsOn ! =null) {
				// Iterate over dependencies
				for (String dep : dependsOn) {
					if (isDependent(beanName, dep)) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
					}
					// Register the dependency bean
					registerDependentBean(dep, beanName);
					try {
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"'" + beanName + "' depends on missing bean '" + dep + "'", ex); }}}// Create the bean instance object.
			if (mbd.isSingleton()) {
				sharedInstance = getSingleton(beanName, () -> {
					try {
						// Here is the instantiated entry (createBean)
						return createBean(beanName, mbd, args);
					}
					catch (BeansException ex) {
						// Explicitly remove instance from singleton cache: It might have been put there
						// eagerly by the creation process, to allow for circular reference resolution.
						// Also remove any beans that received a temporary reference to the bean.
						destroySingleton(beanName);
						throwex; }}); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }/ / to omit
}
Copy the code

In case it gets too long and ignores some of the comments, let’s go through the main logic of this section, which does a few things.

  • Get the bean name (beanName)
  • Get the Bean definition
  • Pass the parameters used to create the object (ARGS)
  • Checking dependencies (depenOn)
  • First instantiate the dependency (getBean)
  • Instantiate the dependency (createBean)
  • Instantiate the current object (createBean)

We’re done reading about the createBean method, so we’ll continue to read more about createBean, the entry to the instantiated bean.

CreateBean (createBean)

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

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// Parse the Bean class to get the real classClass<? > resolvedClass = resolveBeanClass(mbd, beanName);if(resolvedClass ! =null&&! mbd.hasBeanClass() && mbd.getBeanClassName() ! =null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// Prepare method overlays (not detailed).
	try {
		mbdToUse.prepareMethodOverrides();
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance (without further ado).
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if(bean ! =null) {
			returnbean; }}catch (Throwable ex) {
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}

	try {
		// Instantiate the bean entry (instantiate entry)
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	/ / ignore...
}
Copy the code

This part is to find out which classes are actually available based on the bean name (beanName) and bean definition (beanDeifinition).

Next, read doCreateBean, the specific method for creating an instance of a bean.

CreateBean (doCreateBean)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {

	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<? > beanType = instanceWrapper.getWrappedClass();if(beanType ! = NullBean.class) { mbd.resolvedTargetType = beanType; }// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if(! mbd.postProcessed) {try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true; }}// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isTraceEnabled()) {
			logger.trace("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
		populateBean(beanName, mbd, instanceWrapper);
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); }}if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if(earlySingletonReference ! =null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if(! actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."); }}}}// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}
Copy the code

The following two parts are omitted. The specific method names are listed here. Basically, they are pre-processing before creating the bean.

CreateBeanInstance (createBeanInstance)

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance

InstantiateBeans

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#instantiateBean

The real instantiation tool methods are the following two methods, which are quite straightforward to use reflection knowledge, constructors to create instance objects.

Instantiate

org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.supp ort.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
	// Do not overwrite classes with CGLIB if there is no overwrite.
	if(! bd.hasMethodOverrides()) {// Constructor variableConstructor<? > constructorToUse;// Constructor argument lock (lock)
		synchronized (bd.constructorArgumentLock) {
			// Parse the constructor or factory method to the constructor variableconstructorToUse = (Constructor<? >) bd.resolvedConstructorOrFactoryMethod;// If it is null
			if (constructorToUse == null) {
				// Get the class defined by the bean
				finalClass<? > clazz = bd.getBeanClass();If the class is an interface, throw an exception
				if (clazz.isInterface()) {
					throw new BeanInstantiationException(clazz, "Specified class is an interface");
				}
				try {
					// Promote permission gain constructor if system security management exists
					if(System.getSecurityManager() ! =null) { constructorToUse = AccessController.doPrivileged( (PrivilegedExceptionAction<Constructor<? >>) clazz::getDeclaredConstructor); }else {
						// Get the constructor
						constructorToUse = clazz.getDeclaredConstructor();
					}
					// Get the constructor
					bd.resolvedConstructorOrFactoryMethod = constructorToUse;
				}
				catch (Throwable ex) {
					throw new BeanInstantiationException(clazz, "No default constructor found", ex); }}}// Instantiate the object according to the constructor
		return BeanUtils.instantiateClass(constructorToUse);
	}
	else {
		// CGLIB subclasses must be generated (aop related). s.=
		returninstantiateWithMethodInjection(bd, beanName, owner); }}Copy the code

This section gets the constructor, and the next section instantiates the object through the constructor.

instantiateClass

org.springframework.beans.BeanUtils#instantiateClass(java.lang.reflect.Constructor, java.lang.Object…)

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
	// Check whether it is null
	Assert.notNull(ctor, "Constructor must not be null");
	try {
		// Make the constructor accessible
		ReflectionUtils.makeAccessible(ctor);
		// Kotlin (ignore)
		if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
			return KotlinDelegate.instantiateClass(ctor, args);
		}
		else {
			// Get an array of parameter typesClass<? >[] parameterTypes = ctor.getParameterTypes();// If the array of parameter types obtained is smaller than the array of parameter objects passed, an error is thrown
			Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
			// Initializes the parameters passed
			Object[] argsWithDefaultValues = new Object[args.length];
			// Iterate over the parameters
			for (int i = 0 ; i < args.length; i++) {
				if (args[i] == null) {
					// Assign the object toClass<? > parameterType = parameterTypes[i];// Handle primitive types
					// {Class@1933} "int" -> {Integer@1934} 0
					// {Class@1935} "boolean" -> {Boolean@1894} false
					// {Class@1936} "short" -> {Short@1937} 0
					// {Class@1938} "byte" -> {Byte@1939} 0
					// {Class@1940} "long" -> {Long@1941} 0
					argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
				}
				else {
					// The passed parameter object is assigned to the obtained parameter typeargsWithDefaultValues[i] = args[i]; }}// Instantiate the object through the constructor
			returnctor.newInstance(argsWithDefaultValues); }}catch (InstantiationException ex) {
		throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
	}
	catch (IllegalAccessException ex) {
		throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
	}
	catch (IllegalArgumentException ex) {
		throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
	}
	catch (InvocationTargetException ex) {
		throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException()); }}Copy the code

When we see ctor.newinstance, we have done something like new Object(); At this point, we are done instantiating our bean.

conclusion

Finally, there are a few methods that we need to focus on. If you focus on instantiation of bean objects, you can put breakpoints on this method.

org.springframework.beans.BeanUtils#instantiateClass(java.lang.reflect.Constructor, java.lang.Object…)

The following is the call stack, which can be read according to the corresponding source line number, starting from the last line to the front.

instantiate:87, SimpleInstantiationStrategy (org.springframework.beans.factory.support) instantiateBean:1310, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) createBeanInstance:1213, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) doCreateBean:556, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) lambda
d o G e t B e a n doGetBean
0:324, AbstractBeanFactory (org.springframework.beans.factory.support) getObject:-1, 1010931249 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$10) getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support) doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support) getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support) preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support) finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support) refresh:551, AbstractApplicationContext (org.springframework.context.support)

At this point, all of the defined bean objects are instantiated, but cannot be directly used by us because some of the dependency property values we often use have not yet been injected.

In the next chapter, we’ll look at how property injection and initialization are implemented.