spring中bean的加载(一)

本文详细探讨了Spring中bean的加载过程,从beanName的转换、缓存加载单例、FactoryBean的使用、依赖检查到不同scope的bean创建,揭示了Spring在实例化bean时的复杂性和巧妙策略。特别提到了在创建bean前后的后处理器应用,以及如何处理FactoryBean和循环依赖。此外,还介绍了如何从bean的实例中获取对象,强调了在获取单例bean时的逻辑。文章通过代码分析,一步步展示了Spring如何保证bean的正确加载和管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Boot 面试精讲

1.前言

Spring中bean加载的功能实现远比bean的解析要复杂得多.对于加载bean的功能,在Spring中的调用方式为:

MyTestBean bean=(MyTestBean) bf.getBean()"myTestBean")

这句代码实现了什么样的功能呢?先快速体验一下Spring中代码是如何实现的(AbstractBeanFactory类的getBean方法):

@Override
public Object getBean(String name) throws BeansException {
   
	return doGetBean(name, null, null, false);
}

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

        //提取对应的beanName
		final String beanName = transformedBeanName(name);
		Object bean;

		/*
		 *检查缓存中或者实例工厂中是否存在对应的实例
         *之所以会首先使用这段代码,是因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依          *赖.Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提前曝光,也就是将      
         *ObjectFactory加入到缓存中,一旦下个bean创建时需要依赖上个bean,则直接使用ObjectFactory.
         */
        //直接尝试从缓存中获取或者singletonFactory中的ObjectFactory中获取
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
   
			if (logger.isDebugEnabled()) {
   
				if (isSingletonCurrentlyInCreation(beanName)) {
   
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
   
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
            //返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
   
			//只有在单例情况才会尝试解决循环依赖,原型模式下,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时
            //候,就会产生当A还未创建完成的时候因为对于B的创建再次返回创建A,造成循环依赖
			if (isPrototypeCurrentlyInCreation(beanName)) {
   
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
            //如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试从parentBeanFactory中
            //检测
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
   
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
                //递归到BeanFactory中寻找
				else if (args != null) {
   
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
   
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
            //如果不是仅仅做类型检查,则是创建bean,这里要进行记录
			if (!typeCheckOnly) {
   
				markBeanAsCreated(beanName);
			}

            //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
            //如果指定BeanName是子Bean的话,同时会合并父类的相关属性
			try {
   
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
                //如果存在依赖则需要递归实例化依赖的bean
				if (dependsOn != null) {
   
					for (String dep : dependsOn) {
   
						if (isDependent(beanName, dep)) {
   
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
                        //缓存依赖调用
						registerDependentBean(dep, beanName);
						try {
   
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
   
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
                //实例化依赖的bean后便可以实例化mbd本身了
                //singleton模式的创建
				if (mbd.isSingleton()) {
   
					sharedInstance = getSingleton(beanName, () -> {
   
						try {
   
							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);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
   
                    //property模式的创建(new)
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
   
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
   
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
   
                    //指定的scope上实例化bean
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
   
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
   
						Object scopedInstance = scope.get(beanName, () -> {
   
							beforePrototypeCreation
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值