先把上一片博客的图整过来:
上边的这张简易流程图是getBean的过程,在这里进行拆分,本篇博文主要是将前两步的源码,即getBean和doGetBean。
1、getBean
查看getBean的源码,发现有几个实现,但是每个实现都很简单,都是调用了doGetBean的防范,如下:
@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);
}
下面我们还是重点查看doGetBean的方法。
2、doGetBean
doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly)
- name:bean的名字
- requiredType:需要转换的类型
- args:参数
- typeCheckOnly:是否仅仅是类型检查
源码如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//提取对应的bean
final String beanName = transformedBeanName(name);
Object bean;
/**
* 检查缓存中或者实例中是否存在对应的实例
* 为什么要写这段代码呢 ——> 因为在创建单例的bean的时候会存在依赖注入的场景,而在创建依赖的时候为了避免循环依赖,Spring
* 容器在创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提前曝光,即将ObjectFactory加入缓存中,一旦下个bean
* 创建的时候依赖上个bean则直接使用ObjectFactory
*
*/
//先获取一次,若不为null,则会走缓存
Object sharedInstance = getSingleton(beanName);
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 + "'");
}
}
//返回对应的实例,但有时候存在如BeanFactory但情况,并不是直接返回实例本身而是返回指定方法返回但实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//只有单例但setter注入可以解决循环依赖,原型模式但情况下,是不能解决循环依赖但问题,因为原型模式spring是不存入缓存的
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
//若beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则会尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) { //递归到BeanFactory中查找
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//若不是仅仅做类型检查则是创建bean,在此做记录
if (!typeCheckOnly) {
//标记beanName,已创建
markBeanAsCreated(beanName);
}
try {
//将存储在XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//若指定beanName是子Bean的时候同时会合并父类的相关属性
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);
}
}
}
//实例化依赖的bean后可以实例化mbd(RootBeanDefinition)本身了
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()) {
//原型模式下创建一个新的实例
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(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
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);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//检查需要的类型是否符合bean的实际类型
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
看上去比较长,bean的加载经历一个相当长的复杂的过程,中间的各种场景的考虑。在加载的过程中所涉及到的几点:
1)beanName的转换
就是说转换成对应的beanName,有时候传进来的beanName是别名,也有可能是FactoryBean,因此需要进行转换。
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
BeanFactoryUtils.transformedBeanName(name)的定义如下:
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
/**
* 去除BeanFactory的修饰符,即以 & 开头,例如若name="&TestBean",则首先去除 &
* 从而使得name="TestBean".
*/
//不以 & 开头
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;
});
}
public String canonicalName(String name) {
//如果存在alias即别名,则会使用该别名最终所代表的bean的name
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
2)尝试从缓存中加载单例
Spring容器内的bean默认会被创建一次,之后在使用bean的时候直接从单例缓存中获取。这里只是尝试,如果加载不成功则再次尝试从singletonFactories中加载。在创建单例的时候可能会存在循环依赖的问题,这个问题可以看一下我上一篇博文的介绍:Spring循环依赖。
3)bean的实例化
若是从缓存中得到的bean的原始状态,则还需要对其进行实例化。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
注意:bean在缓存中记录的只是最原始的bean的状态,并不一定是我们最终想要的bean。
4)原型模式的依赖检查
原型模式的情况是无法解决循环依赖的问题,因为在该模式下spring不对bean缓存,因而无法解决循环依赖。另外在说一点,构造器造成的循环依赖Spring也是无法解决的,因为在通过查看单例模式下setter注入解决循环依赖的前提条件是,对bean的提前曝光,提前曝光是通过bean的空参构造器来实现的。
5)检测parentBeanFactory
判断条件:parentBeanFactory != null && !containsBeanDefinition(beanName)
!containsBeanDefinition(beanName) 是在检测若当前加载的xml配置文件中不包含beanName所有的配置,就只能到parentBeanFactory去尝试了,然后在递归调用getBean.
6)将XML文件的GernericBeanDefinition转换为RootBeanDefinition。
7)寻找依赖
8)针对不同的scope创建bean。
9)类型转换
在本文最初的getBean的几个方法中就可以看出,当需要做类型转换的时候会传入requiredType。如返回的bean其实是个String,但是requiredType传入的却是Integer类型,这个时候该步骤就起到作用了。
至此,bean的加载就算完成了。