Underlying principles of spring IOC scope

Keywords: Java Spring Back-end

The scope in Spring is

a. The default value, singleton, represents a single instance object:

When the scope of a bean is set to singleton, there will only be one shared bean instance in the Spring IOC container, and all requests for a bean will only return the same instance of the bean as long as the id matches the bean definition. In other words, when a bean definition is set to singleton scope, the Spring IOC container will only create a unique instance of the bean definition. This single instance will be stored in the singleton cache, and all subsequent requests and references to the bean will return the cached object instance. Note that the singleton scope is completely different from the singleton in GOF design mode, which means that only one class exists in a ClassLoader, The singleton here means that a container corresponds to a bean, that is, when a bean is identified as singleton, only one bean will exist in the IOC container of spring.

b. prototype, representing multi instance objects:

For a bean deployed in the prototype scope, every request (injecting it into another bean or calling the container's getBean() method programmatically) will generate a new bean instance, which is equivalent to a new operation. For a bean in the prototype scope, one thing is very important, that is, Spring cannot be responsible for the whole life cycle of a prototype bean, After initializing, configuring, decorating or assembling a prototype instance, the container gives it to the client, and then ignores the prototype instance. Regardless of the scope, the container will call the initialization lifecycle callback methods of all objects, while for prototype, any configured destructor lifecycle callback methods will not be called. It is the responsibility of the client code to clear the objects in the prototype scope and release the expensive resources held by any prototype bean. (a possible way for the Spring container to release resources occupied by singleton scoped beans is by using the bean's post processor, which holds the reference of the bean to be cleared.)

c,request

d,session

e,globalSession

1. The key to implementing scope is AbstractBeanFactory. Let's take a look at its structure first

In its parent class DefaultSingletonBeanRegistry, Map (singletonObjects) is used to store singleton objects

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	//Cache singleton object
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
}

Let's look at the AbstractBeanFactory class

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	@Override
	public Object getBean(String name) throws BeansException {
        //doGetBean is really working
		return doGetBean(name, null, null, false);
	}
    
    protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//Get bean object name
		String beanName = transformedBeanName(name);
		Object beanInstance;

        //See whether the bean object can be obtained from the singletonObjects cache
		Object sharedInstance = getSingleton(beanName);
        //If you can get objects in singletonObjects, go to the following
		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 + "'");
				}
			}
            //If it is of FactoryBean type, it will be processed in this method and getObject will be called
            // Method to obtain the bean object, so it can ensure that the FactoryBean is singleton and getObject
            // Method always returns the same object to ensure that the object returned by getBean is the same
			//Detailed explanation: https://blog.csdn.net/xxg1993/article/details/100806923
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		
		else {
			......
            ......

				// Running here shows that the previous getSingleton method obtains the singleton object from the cache, which means that the object has not been created in the Spring factory, so this method 				    Finally, the createBean method will be called to create the bean object and cache it in the singleton collection, which is convenient for the previous getSingleton method to obtain it directly
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				//If it is a prototype, the object is created directly without caching
				else if (mbd.isPrototype()) {
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				......
                    ......
	}
    

Summary: first, check whether the bean object can be obtained from the cache. If it can, it indicates that it is a single instance and exists, and can be obtained directly; If it does not exist in the cache, there are two situations: 1) it is a singleton, but it is used for the first time and has not been created. The singleton object is created later and saved to the cache; 2) It is not a singleton. If the prototype is created and returned directly, it will not be saved to the cache.

Supplement: creation timing of objects in Spring

Singleton class (also the default scope of Spring bean object)

singleton is created and initialized when the xml configuration file is first read by the Application object.

Prototype class

It is created and initialized only when it is first fetched, or when it is a dependent object of the fetched object (which takes precedence over the fetched object).

Reference: 1 https://blog.csdn.net/qq_ 27529917/article/details/78468731? utm_ medium=distribute.pc_ relevant.none-task-blog-2defaultbaidujs_ title~default-1.highlightwordscore&spm=1001.2101.3001.4242.2

2,https://blog.csdn.net/Peelarmy/article/details/107366377?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.highlightwordscore&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.highlightwordscore

Posted by dubrubru on Fri, 05 Nov 2021 12:23:58 -0700