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

How is the Bean of each scope in Spring Ioc created?

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly explains how the Bean of each scope in Spring Ioc is created. The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn how to create the Bean of each scope in Spring Ioc.

1. Singleton

Code:

/ / Create bean instance. / / create a singleton Bean if (mbd.isSingleton ()) {/ / an anonymous inner class is used here to create a Bean instance object and register it with the dependent object sharedInstance = getSingleton (beanName, ()-> {try {/ / create a specified Bean instance object if there is a parent inheritance Then merge the definitions of the subclass and the parent class 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. / / explicitly clears the instance object destroySingleton (beanName) from the container singleton mode Bean cache; / / gets the instance object bean = getObjectForBeanInstance (sharedInstance, name, beanName, mbd) of a given Bean;}

An anonymous inner class is used here. First, get an ObjectFactory through the createBean (beanName, mbd, args) method.

Pass ObjectFactory as an argument to the getSingleton (beanName,objectFactory) method

Use the sharedInstance returned by the getSingleton (beanName,objectFactory) method to pass getObjectForBeanInstance (sharedInstance, name, beanName, mbd) as a parameter to return the final Bean instance (for more information, see loading of Spring Ioc's Bean (1))

/ / DefaultSingletonBeanRegistry.javapublic Object getSingleton (String beanName, ObjectFactory singletonFactory) {Assert.notNull (beanName, "Bean name must not be null"); / / Global locking synchronized (this.singletonObjects) {/ / get singleton bean from cache / / because singleton mode is actually reusing the created bean, this step must check Object singletonObject = this.singletonObjects.get (beanName) If (singletonObject = = null) {/ / whether the bean if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException (beanName) is being destroyed "Singleton bean creation not allowed while singletons of this factory are in destruction" + "(Do not request a bean from a BeanFactory in a destroy method implementation!)") } if (logger.isDebugEnabled ()) {logger.debug ("Creating shared instance of singleton bean'" + beanName + "'");} / / load pre-processing beforeSingletonCreation (beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions = = null) If (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet ();} try {/ / initialize bean / / this process actually calls the createBean () method singletonObject = singletonFactory.getObject () NewSingleton = true;} catch (IllegalStateException ex) {/ / Has the singleton object implicitly appeared in the meantime-> / if yes, proceed with it since the exception indicates that state. SingletonObject = this.singletonObjects.get (beanName); if (singletonObject = = null) {throw ex }} catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException: this.suppressedExceptions) {ex.addRelatedCause (suppressedException) }} throw ex;} finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null } / / Post processing afterSingletonCreation (beanName);} if (newSingleton) {/ / add addSingleton (beanName, singletonObject) to the cache;}} return singletonObject }}

In this code, we mainly do some preparation and preprocessing steps. The actual creation of Bean is implemented in the singletonFactory.getObject () method, while singletonFactory is the callback parameter after the creation of the createBean () method.

So what is the main thing this code does?

Attempt to get singleton Bean from cache

If it has already been loaded, return directly, otherwise start the loading process

Load pre-processing

Get Bean instance

Post processing

Join the cache

1.1. Load pre-processing

BeforeSingletonCreation (beanName) is a tagging method. Let's look at the code:

/ / used to add a flag. The current bean is in the process of creating protected void beforeSingletonCreation (String beanName) {if (! this.inCreationCheckExclusions.contains (beanName) & &! this.singletonsCurrentlyInCreation.add (beanName)) {/ / failed to add, throw new BeanCurrentlyInCreationException (beanName);}}

Add beanName to the singletonsCurrentlyInCreationmap to indicate that the singleton bean is being created, and if the addition fails, an exception is thrown.

1.2. Obtain Bean instance

Get the Bean through the singletonFactory returned by the createBean (beanName) method.

1.3. Post-processing

AfterSingletonCreation (beanName) is also a representation:

/ / used to remove the tag. The current Bean is not in the process of creating protected void afterSingletonCreation (String beanName) {if (! this.inCreationCheckExclusions.contains (beanName) & &! this.singletonsCurrentlyInCreation.remove (beanName)) {/ / failed to remove, throwing an exception throw new IllegalStateException ("Singleton'" + beanName + "'isn't currently in creation") }}

Remove the creation tag after creating the Bean.

This creation flag for pre-processing and post-processing is used when calling isSingletonCurrentlyInCreation (String beanName), which is used to determine whether the current bean is already being created.

1.4. Join the cache

Look directly at the code:

Protected void addSingleton (String beanName, Object singletonObject) {synchronized (this.singletonObjects) {this.singletonObjects.put (beanName, singletonObject); this.singletonFactories.remove (beanName); this.earlySingletonObjects.remove (beanName); this.registeredSingletons.add (beanName);}}

One put, one add, two remove operations.

[put] singletonObjects attribute, cache for singleton bean.

[remove] singletonFactories attribute, cache for singleton bean Factory.

The [remove] earlySingletonObjects property, the cache of the singleton bean created "early".

[add] registeredSingletons attribute, a singleton cache that has been registered.

II. Prototype

Code:

/ / create multiple Bean else if (mbd.isPrototype ()) {/ / It's a prototype-> create a new instance. / / prototype pattern (Prototype) creates a new object Object prototypeInstance = null; try {/ / load preprocessing each time. The default function is to register the currently created prototype object beforePrototypeCreation (beanName). / / create the specified Bean object instance prototypeInstance = createBean (beanName, mbd, args);} finally {/ / load post processing. The default function tells the IOC container that the prototype object of the specified Bean will no longer create afterPrototypeCreation (beanName). } / / get the instance object bean = getObjectForBeanInstance (prototypeInstance, name, beanName, mbd) of a given Bean;}

The prototype pattern is simple, just create a new instance and no longer fetch it from the cache.

BeforePrototypeCreation (beanName) pre-processing to mark the current bean as the prototype being created.

AfterPrototypeCreation (beanName) post-processing to cancel the current bean's being created flag.

Call the getObjectFrBeanInstance () method to get the final bean. (for more information, please see loading Bean of Spring Ioc (1))

3. Other scopes / / the Bean to be created is neither Singleton nor Prototype / / such as request, session, application, etc. Lifecycle else {String scopeName = mbd.getScope (); final Scope scope = this.scopes.get (scopeName) / / if the lifecycle range is not configured in the Bean definition resource, the Bean definition is invalid if (scope = = null) {throw new IllegalStateException ("No Scope registered for scope name'" + scopeName + "'") } try {/ / another anonymous inner class is used here Get an instance of the specified lifecycle range Object scopedInstance = scope.get (beanName, ()-> {/ / pre-processing beforePrototypeCreation (beanName)) Try {return createBean (beanName, mbd, args) } finally {/ / Post processing afterPrototypeCreation (beanName);}}) / / get the instance object bean = getObjectForBeanInstance (scopedInstance, name, beanName, mbd) of a given Bean;} catch (IllegalStateException ex) {throw new BeanCreationException (beanName, "Scope'" + scopeName + "'is not active for the current thread) Consider "+" defining a scoped proxy for this bean if you intend to refer to it from a singleton ", ex);}

It is divided into the following steps:

Get the scope name from the Scope comment

Pre-processing

CreateBean ()

Post processing

Scope.get () gets bean

The getObjectForBeanInstance () method gets the Bean

The core process is the same as the prototype pattern, except that scope.get () is called here to get the bean.

Object get (String name, ObjectFactory objectFactory)

Scope.get () is an interface that has several implementation classes:

Let's take a look at an implementation SimpleThreadScope that comes with spring:

/ SimpleThreadScope.javaprivate final ThreadLocal threadScope = new NamedThreadLocal ("SimpleThreadScope") {@ Override protected Map initialValue () {return new HashMap ();}} / / get the instance of bean @ Override public Object get (String name, ObjectFactory objectFactory) {/ / get the scope cache Map scope = this.threadScope.get (); Object scopedObject = scope.get (name); if (scopedObject = = null) {scopedObject = objectFactory.getObject () / / join the cache scope.put (name, scopedObject);} return scopedObject;}

Other scope implementations will not be implemented one by one, and interested friends can take a look at them for themselves.

Summary

There are two important methods in the above code:

CreateBean (beanName, mbd, args)

GetObjectForBeanInstance (Object beanInstance, String name, String beanName, RootBeanDefinition mbd)

These two methods are all used in the three code branches, which will be analyzed in detail in the next article in createBean. The getObjectForBeanInstance method has been analyzed in the loading of Spring Ioc's Bean (1).

Here we quote the analysis of this method by "Spring source code depth parsing":

The main purpose of this method is to verify the correctness of the following bean. In fact, it is to check whether the current bean is a bean of type FactoryBean.

If so, you need to call the getObject () method of the FactoryBean instance corresponding to the bean as the return value.

Whether the bean obtained from the cache or the bean loaded through different scope policies are only the original bean state, it is not necessarily the bean we ultimately want.

For example, if we need to process the factory bean, what we get here is actually the initial state of the factory bean, but what we really need is the bean returned in the factory-method method defined in the factory bean, and the getObjectForBeanInstance (Object beanInstance, String name, String beanName, RootBeanDefinition mbd) method does the job.

Thank you for reading, the above is "how the Bean of each scope in Spring Ioc is created", after the study of this article, I believe you have a deeper understanding of how the Bean of each scope in Spring Ioc is created, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

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

Internet Technology

Wechat

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

12
Report