Spring源码-IOC之getBean

版本 Spring Framework 6.0.9​

1. BeanFactory

BeanFactory接口有五个getBean的重载方法,大致分为名称检索 和 类型检索 (入参同时有名称和类型属于按名称检索,原因是当入参只有类型时,先根据类型从bean工厂获取bean名称,再bean名称作为入参,调用按名称检索的getBean方法)

public interface BeanFactory {
	// 根据名称检索bean实例
	Object getBean(String name) throws BeansException;
	// 根据名称和类型(接口或者超类)检索bean实例
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
	// // 根据名称检索bean,指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数参数创建bean实例
	Object getBean(String name, Object... args) throws BeansException;
	// // 类型(接口或者超类)检索bean实例
	<T> T getBean(Class<T> requiredType) throws BeansException;
	// 根据类型(接口或者超类)检索bean,指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数参数创建bean实例
	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
}

2. getBean

在refresh过程中,spring容器通过bean工厂的getBean方法获取/创建bean实例,一般创建的bean工厂类型都是DefaultListableBeanFactory,按类型检索的getBean由DefaultListableBeanFactory实现,按名称检索的getBean由其父类AbstractBeanFactory实现。

2.1 按类型检索的getBean

DefaultListableBeanFactory类实现了按类型检索的getBean方法,通过对象类型获取ResolvableType后,调用DefaultListableBeanFactory的resolveBean方法解析。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
		// 调用resolveBean方法获取bean对象
		Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
		if (resolved == null) {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
		return (T) resolved;
	}
	// 省略其他代码
}

resolveBean方法中调用resolveNamedBean方法,解析给定的对象类型,获取唯一匹配的bean实例。resolveNamedBean方法中返回的NamedBeanHolder对象,既包含bean实例,同时保存了bean名称。

	@Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
		// 解析与给定对象类型唯一匹配的 Bean 实例,NamedBeanHolder包含其 Bean 名称。
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		// 尝试从父bean工厂检索
		BeanFactory parent = getParentBeanFactory();
		if (parent instanceof DefaultListableBeanFactory dlfb) {
			return dlfb.resolveBean(requiredType, args, nonUniqueAsNull);
		}
		else if (parent != null) {
			ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
			if (args != null) {
				return parentProvider.getObject(args);
			}
			else {
				return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
			}
		}
		return null;
	}

调用getBeanNamesForType方法,根据指定类型获取容器中的bean名称。再以bean名称为入参,调用重载的resolveNamedBean方法,方法内调用按名称检索的getBean方法。

	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {

		Assert.notNull(requiredType, "Required type must not be null");
		// 根据类型获取bean名称
		String[] candidateNames = getBeanNamesForType(requiredType);

		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				// 不包含给定名称的bean定义 或 该bean定义 autowireCandidate属性为true
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}

		if (candidateNames.length == 1) {
			return resolveNamedBean(candidateNames[0], requiredType, args);
		}
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			// 确定给定 Bean 集中的主要候选者  Primary
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
				// 确定给定 Bean 集中优先级最高的候选项  Priority  Ordered
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null) {
					return null;
				}
				if (beanInstance instanceof Class) {
					return resolveNamedBean(candidateName, requiredType, args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			// 只期望一个匹配的 Bean 但匹配到多个
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			String beanName, ResolvableType requiredType, @Nullable Object[] args) throws BeansException {

		Object bean = getBean(beanName, null, args);
		if (bean instanceof NullBean) {
			return null;
		}
		return new NamedBeanHolder<>(beanName, adaptBeanInstance(beanName, bean, requiredType.toClass()));
	}

所以按类型检索的genBean方法分为两部分:

  1. 解析给定对象类型获取容器中的bean名称
  2. 用bean名称调用按名称检索的genBean方法

2.2 按名称检索的getBean

按名称检索的getBean方法,具体实现逻辑在AbstractBeanFactory类里面的doGetBean方法中。


public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		return doGetBean(name, requiredType, null, false);
	}

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

	public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
			throws BeansException {

		return doGetBean(name, requiredType, args, false);
	}
	
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// 省略其他代码	
	}
	// 省略其他代码
}

3. doGetBean

整体执行过程:

  1. 获取实际的 Bean 名称,如果给定的名称包含工厂Bean前缀&,则去除所有&,如果是别名转换为实际名称
  2. 从单例池中获取单例对象
  3. 若存在(获取)
    1. 根据给定的name,前缀若为&,表明调用者想获取工厂bean,校验当前bean实例是否为bean工厂,是则直接返回,否则抛出BeanIsNotAFactoryException异常
    2. name不符合工厂bean的规则(前缀为&),说明调用者想要一个普通bean,如果 bean实例不是FactoryBean的子类,直接返回。
    3. 不符合第1、2点,则说明当前bean实例是FactoryBean的子类,但调用者想获取工厂bean生成的bean实例。先从factoryBeanObjectCache缓存中获取,没有则从工厂bean中获取对象(对象会放到factoryBeanObjectCache缓存)。
  4. 不存在(创建)
    1. 如果有父bean工厂, 尝试从中获取
    2. 如果bean定义设置了dependsOn,先解析dependsOn依赖对象
    3. 根据bean定义的scope属性,调用createBean创建bean实例(单例、原型、其他)
  5. 最后将对象进行类型转换
    在这里插入图片描述

3.1 transformedBeanName

transformedBeanName方法返回 Bean 名称,逻辑分为两部分

  1. BeanFactoryUtils.transformedBeanName 去掉工厂取消引用前缀&
  2. canonicalName 将别名解析为规范名称
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}
	// 省略其他代码...
}

循环去掉前缀&,直至name不以&开头为止。

public abstract class BeanFactoryUtils {
	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		// 如果没有工厂Bean前缀&,直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		// 循环去除前缀&,直到不以&为前缀
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}
	// 省略其他代码...
}

canonicalName是AbstractBeanFactory 的父类SimpleAliasRegistry 方法,如果别名缓存map中存在key为name的值,返回name的关联值,即将别名转换成实际的bean名称。

public class SimpleAliasRegistry implements AliasRegistry {
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}
	// 省略其他代码...
}

3.2 getSingleton

getSingleton方法从三个级别的缓存中获取给定名称的对象,

  • 一级缓存:private final Map<String, Object> singletonObjects,初始化完成的bean对象
  • 二级缓存:private final Map<String, Object> earlySingletonObjects,实例化但未初始化的bean对象
  • 三级缓存:private final Map<String, ObjectFactory<?>> singletonFactories,存储的ObjectFactory是一个lambda表达式,通过getObject方法获取 实例化但未初始化的bean对象

先从一级缓存获取,若不存在判断当前bean名称是否创建中,如果是则从二级缓存中获取。还是获取不到,由于入参allowEarlyReference为true,下一步锁住一级缓存,再尝试从一、二级缓存获取,最后从三级缓存中获取,如果三级缓存有,则调用对象工厂ObjectFactory获取对象,并将对象放入二级缓存,移除三级缓存的引用。
在这里插入图片描述

isSingletonCurrentlyInCreation 方法判断singletonsCurrentlyInCreation集合中是否存在给定名称,表示当前bean名称正在创建。添加到singletonsCurrentlyInCreation的位置在创建单例对象过程中,后面标明位置。
在这里插入图片描述

3.3 getObjectForBeanInstance

getObjectForBeanInstance方法返回调用者期望的bean实例,逻辑分为三部分,

  1. 如果name以&开头,说明调用者想要工厂bean,判断当前bean实例是否为FactoryBean,是则直接返回。
  2. 如果name不以&开头,说明调用者想要普通bean,判断当前bean实例是否为FactoryBean,不是则直接返回。
  3. 第二点没返回,认为当前bean实例是工厂bean,尝试从工厂bean中获取bean。
    在这里插入图片描述

3.3.1 isFactoryDereference

isFactoryDereference方法判断name是否以&为前缀开头。
在这里插入图片描述

3.3.2 getCachedObjectForFactoryBean

getCachedObjectForFactoryBean方法从factoryBeanObjectCache缓存中获取对象,key为FactoryBean 名称,value为FactoryBean创建的对象。
在这里插入图片描述

3.3.3 getMergedLocalBeanDefinition

getMergedLocalBeanDefinition方法返回与父bean定义合并后(如果有)的bean定义,可以理解成完整的bean定义。先从缓存中获取合并的bean定义,如果不为空且不需要重新合并stale=false,直接返回。否则合并bean定义。否则执行合并操作。
在这里插入图片描述
getMergedBeanDefinition方法简单理解一下即是 如果当前bean定义设置了父bean名称,则获取父bean定义进行合并,没有则返回的当前bean定义,但两种情况的bean定义类型都转换成了RootBeanDefinition返回。
在这里插入图片描述

3.3.4 getObjectFromFactoryBean

getObjectFromFactoryBean方法:调用工厂bean 的getObject方法获取对象。
在这里插入图片描述

3.4 isPrototypeCurrentlyInCreation

判断当前bean名称在prototypesCurrentlyInCreation是否存在,如果在说明当前原型bean创建中,抛出BeanCurrentlyInCreationException异常。
在这里插入图片描述
在这里插入图片描述

3.5 originalBeanName

originalBeanName方法包含transformedBeanName方法,都是返回bean名称,区别在于如果name是工厂bean名称,以&为前缀,originalBeanName方法的回参包含&,而transformedBeanName不包含&。
在这里插入图片描述

3.6 markBeanAsCreated

typeCheckOnly注释含义说明为了类型检查还是实际使用,在getBean方法中都为false。

markBeanAsCreated方法判断alreadyCreated中是否存在bean名称,如果不存在则锁住mergedBeanDefinitions合并定义缓存,isBeanEligibleForMetadataCaching方法在DefaultListableBeanFactory中判断bean定义是否已经冻结 或 alreadyCreated是否已存在,不是则清空合并bean定义缓存,说明bean定义元数据有可能变化。最后添加到alreadyCreated集合中,表明当前bean名称已创建。

即往alreadyCreated集合中添加beanName
在这里插入图片描述

在这里插入图片描述

  • AbstractBeanFactory#isBeanEligibleForMetadataCaching
    org.springframework.beans.factory.support.AbstractBeanFactory#isBeanEligibleForMetadataCaching
  • DefaultListableBeanFactory#isBeanEligibleForMetadataCaching
    org.springframework.beans.factory.support.DefaultListableBeanFactory#isBeanEligibleForMetadataCaching

3.7 checkMergedBeanDefinition

checkMergedBeanDefinition判断合并bean定义的abstract属性是否为true,abstract标识当前bean定义允不允许实例化。
在这里插入图片描述

3.8 mbd.isSingleton()

如果合并bean定义是单例,即判断其scope属性是否为singleton或空。再调用getSingleton方法获取单例。
在这里插入图片描述
getSingleton方法先尝试从缓存中获取,获取不到再调用singletonFactory.getObject()方法,通过单例工厂获取对象,实际返回的是lambda表达式。
在这里插入图片描述

3.8.1 singletonFactory.getObject()

入参的ObjectFactory是一个函数式接口,这里的getObject即是getSingleton中的第二个入参try-catch方法,调用createBean(),如果期间报错调用destroySingleton()
在这里插入图片描述

3.8.2 beforeSingletonCreation、afterSingletonCreation

inCreationCheckExclusions校验当前bean名称被排除检查,一般都为空,前半部分判断为true,主要看singletonsCurrentlyInCreation集合。

beforeSingletonCreation方法往singletonsCurrentlyInCreation集合中添加bean名称,添加成功表示单例开始创建。

afterSingletonCreation方法从singletonsCurrentlyInCreation集合中移除bean名称,移除成功表示单例创建完成。

在这里插入图片描述

3.8.3 addSingleton

singletonFactory.getObject()方法调用成功返回对象后,将newSingleton设置为true,再调用addSingleton方法。
在这里插入图片描述

将对象添加到singletonObjects缓存,key为bean名称,value为单例对象。并从二级、三级缓存中移除。再添加到registeredSingletons集合,registeredSingletons存在的bean名称已创建单例对象。
在这里插入图片描述

3.9 mbd.isPrototype()

如果合并bean定义的scope属性是prototype,直接调用createBean方法创建对象,没有单例缓存的步骤。
在这里插入图片描述

3.9.1 beforePrototypeCreation、afterPrototypeCreation

beforePrototypeCreation、afterPrototypeCreation和上面的3.8.2类似,表明原型bean正在创建。不同在于prototypesCurrentlyInCreation是一个ThreadLocal,并且返回的对象有可能是String,也有可能是set。
在这里插入图片描述
在这里插入图片描述

3.10 mbd.getScope()

根据合并bean定义的scope属性,从scopes中获取对应的Scope对象,调用其get方法获取对象。scopes是一个map,key为作用域名称,value为作用域对象。
在这里插入图片描述

3.10.1 Scope

Scope接口和DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)一样,第二个入参是lambda表达式,在调用Scope实现类的get方法期间,回调ObjectFactory的getObject方法创建对象。
在这里插入图片描述

3.11 adaptBeanInstance

如果bean和requiredType类型不相匹配,则通过类型转换器TypeConverter进行转换,否则直接强转(T) bean。一般情况下,都直接强转。
在这里插入图片描述

3.11.1 getTypeConverter

如果没有设置自定义的转换器,getTypeConverter返回一个默认转换器。
在这里插入图片描述
默认转换器SimpleTypeConverter的registerCustomEditors方法中,propertyEditorRegistrars集合包含一个ResourceEditorRegistrar实例,该实例在refresh阶段的prepareBeanFactory添加进去。
在这里插入图片描述
在这里插入图片描述

3.11.2 getTypeConverter().convertIfNecessary(bean, requiredType)

将if条件注释,强制走类型转换器的convertIfNecessary方法,查看调用逻辑。
在这里插入图片描述
默认转换器SimpleTypeConverter最终调用的是TypeConverterDelegate#convertIfNecessary方法。逻辑里面尝试使用类型编辑器(如果有)、类型转换服务(如果有)、各个类型判断转换,如果都没有则最终强转,与adaptBeanInstance方法的最后步骤(T) bean强转一样,所以程序走到强转步骤,也能正常解析将object类型强转成User.class返回结果。
在这里插入图片描述

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值