Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the initialization process of the singleton Bean for Spring

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the knowledge of "what is the initialization process of Spring singleton Bean". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

The createBean method is a method of AbstractAutowireCapableBeanFactory, a subclass of AbstractBeanFactory. Take a look at its method implementation:

Protected Object createBean (final String beanName, final RootBeanDefinition mbd, final Object [] args)

Throws BeanCreationException {

If (logger.isDebugEnabled ()) {

Logger.debug ("Creating instance of bean'" + beanName + "'")

}

/ / Make sure bean class is actually resolved at this point.

ResolveBeanClass (mbd, beanName)

/ / Prepare method overrides.

Try {

Mbd.prepareMethodOverrides ()

}

Catch (BeanDefinitionValidationException ex) {

Throw new BeanDefinitionStoreException (mbd.getResourceDescription ()

BeanName, "Validation of method overrides failed", ex)

}

Try {

/ / Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

Object bean = resolveBeforeInstantiation (beanName, mbd)

If (bean! = null) {

Return bean

}

}

Catch (Throwable ex) {

Throw new BeanCreationException (mbd.getResourceDescription (), beanName

"BeanPostProcessor before instantiation of bean failed", ex)

}

Object beanInstance = doCreateBean (beanName, mbd, args)

If (logger.isDebugEnabled ()) {

Logger.debug ("Finished creating instance of bean'" + beanName + "'")

}

Return beanInstance

}

None of the previous code makes any sense, and the code executes to line 31:

Protected Object doCreateBean (final String beanName, final RootBeanDefinition mbd, final Object [] args) {

/ / Instantiate the bean.

BeanWrapper instanceWrapper = null

If (mbd.isSingleton ()) {

InstanceWrapper = this.factoryBeanInstanceCache.remove (beanName)

}

If (instanceWrapper = = null) {

InstanceWrapper = createBeanInstance (beanName, mbd, args)

}

Final Object bean = (instanceWrapper! = null? InstanceWrapper.getWrappedInstance (): null)

Class beanType = (instanceWrapper! = null? InstanceWrapper.getWrappedClass (): null)

/ / Allow post-processors to modify the merged bean definition.

Synchronized (mbd.postProcessingLock) {

If (! mbd.postProcessed) {

ApplyMergedBeanDefinitionPostProcessors (mbd, beanType, beanName)

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.isDebugEnabled ()) {

Logger.debug ("Eagerly caching bean'" + beanName +

"'to allow for resolving potential circular references")

}

AddSingletonFactory (beanName, new ObjectFactory () {

Public Object getObject () throws BeansException {

Return getEarlyBeanReference (beanName, mbd, bean)

}

});

}

/ / Initialize the bean instance.

Object exposedObject = bean

Try {

PopulateBean (beanName, mbd, instanceWrapper)

If (exposedObject! = null) {

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 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 "+

"'getBeanNamesOfType' 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

}

The code is traced here and has reached the main flow, and then the code of the doCreateBean method is analyzed in segments.

Create a Bean instance

The createBeanInstance method in line 8 creates an instance of Bean and wraps it as BeanWrapper. Take a look at the createBeanInstance method and post only the key ones in the last paragraph:

/ / 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)

}

/ / No special handling: simply use no-arg constructor.

Return instantiateBean (beanName, mbd)

This means that if the bean tag uses the constructor to inject the attribute, execute line 6, otherwise line 10. MultiFunctionBean uses the default constructor and uses setter to inject properties, so line 10 executes:

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 () {

Public Object run () {

Return getInstantiationStrategy () .instantiate (mbd, beanName, parent)

}

}, getAccessControlContext ()

}

Else {

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)

}

}

The code executes to 13 lines:

Public Object instantiate (RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {

/ / Don't override the class with CGLIB if no overrides.

If (beanDefinition.getMethodOverrides () .isEmpty ()) {

Constructor constructorToUse

Synchronized (beanDefinition.constructorArgumentLock) {

ConstructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod

If (constructorToUse = = null) {

Final Class clazz = beanDefinition.getBeanClass ()

If (clazz.isInterface ()) {

Throw new BeanInstantiationException (clazz, "Specified class is an interface")

}

Try {

If (System.getSecurityManager ()! = null) {

ConstructorToUse = AccessController.doPrivileged (new PrivilegedExceptionAction () {

Public Constructor run () throws Exception {

Return clazz.getDeclaredConstructor ((Class []) null)

}

});

}

Else {

ConstructorToUse = clazz.getDeclaredConstructor ((Class []) null)

}

BeanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse

}

Catch (Exception ex) {

Throw new BeanInstantiationException (clazz, "No default constructor found", ex)

}

}

}

Return BeanUtils.instantiateClass (constructorToUse)

}

Else {

/ / Must generate CGLIB subclass.

Return instantiateWithMethodInjection (beanDefinition, beanName, owner)

}

}

The whole piece of code is doing one thing, which is to choose a constructor to use. Of course, line 9 makes a judgment by the way: instantiating an interface will report an error.

Finally, call to line 30 and take a look at the code:

Public static T instantiateClass (Constructor ctor, Object... Args) throws BeanInstantiationException {

Assert.notNull (ctor, "Constructor must not be null")

Try {

ReflectionUtils.makeAccessible (ctor)

Return ctor.newInstance (args)

}

Catch (InstantiationException ex) {

Throw new BeanInstantiationException (ctor.getDeclaringClass ()

"Is it an abstract class?", ex)

}

Catch (IllegalAccessException ex) {

Throw new BeanInstantiationException (ctor.getDeclaringClass ()

"Is the constructor accessible?", ex)

}

Catch (IllegalArgumentException ex) {

Throw new BeanInstantiationException (ctor.getDeclaringClass ()

"Illegal arguments for constructor", ex)

}

Catch (InvocationTargetException ex) {

Throw new BeanInstantiationException (ctor.getDeclaringClass ()

"Constructor threw exception", ex.getTargetException ()

}

}

An instance of Bean is generated by reflection. See the previous step makeAccessible, which means that even if the constructor of Bean is private or protected, it still does not affect the construction of Bean.

Finally, note that the Bean instantiated here will not be returned directly, but will be packaged as BeanWrapper to continue to be used later.

This is the end of the content of "what is the initialization process of Spring's singleton Bean". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report