Spring-IOC作用域底层原理

Spring中作用域有

a、默认值,singleton,表示单实例对象:

当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把 一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都 将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中 只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时 候,spring的IOC容器中只会存在一个该bean。

b、prototype,表示多实例对象:

prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。 清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被singleton作用域bean占用资源的一种可行方式是,通过使用 bean的后置处理器,该处理器持有要被清除的bean的引用。)

c、request

d、session

e、globalSession

1、实现scope的关键在于AbstractBeanFactory,首先看一下其结构
在这里插入图片描述
其父类DefaultSingletonBeanRegistry中有Map(singletonObjects)用来存放单例对象

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	//缓存单例对象
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
}

我们再看AbstractBeanFactory类

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	@Override
	public Object getBean(String name) throws BeansException {
        //其中doGetBean是真正干活的
		return doGetBean(name, null, null, false);
	}
    
    protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//获取bean对象名
		String beanName = transformedBeanName(name);
		Object beanInstance;

        //从singletonObjects缓存中看能否获取bean对象
		Object sharedInstance = getSingleton(beanName);
        //如果能够在singletonObjects中获取到对象,进入下面
		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 + "'");
				}
			}
            /*如果是FactoryBean类型的将会在该方法中被处理,并调用getObject
            方法获取bean对象,因此能够保证FactoryBean是单例的且getObject
            方法返回的一直是同一个对象才能保证getBean返回的对象是同一个*/
			//详解:https://blog.csdn.net/xxg1993/article/details/100806923
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
		
		else {
			……
            ……

				/*跑到这里则说明前面的getSingleton方法从缓存中获取到单例对象,
				意味着Spring工厂中还未创建该对象,
				因此该方法中最终会调用createBean方法创建bean对象并缓存到单例集合中,
				方便前面的getSingleton方法直接获取*/
				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);
				}
				//如果是prototype,则直接创建对象,不缓存
				else if (mbd.isPrototype()) {
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				……
                    ……
	}
    

总结:首先从缓存中看能否获取到bean对象,如果可以就说明是单例的,且存在的,可以直接获取;如果缓存中不存在,有两种情况:1)是单例的,但是是第一次使用,还未创建,后续进行单例对象的创建,并保存到缓存中;2)不是单例的,如果是prototype直接创建返回,不保存到缓存中。

补充: Spring中对象的创建时机

单例类(也是Spring bean对象默认的scope)

单例类(singleton),会在xml配置文件第一次被Application对象读取的时候,被创建并初始化。

原型类 (prototype)

只有在第一次被取出时,或者作为被取出对象的依赖对象时(会优先于被取出对象),被创建并初始化。

参考: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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值