Spring源码解析(5)——获取bean

回顾上篇

上篇文章《注册BeanDefinition》我们已经分析到,xml配置文件解析完成转化成了一个BeanDefinition,并且这个BeanDefinition存放在了一个beanDefinitionMap里,key就是我们在xml中配置的class属性的值。

<bean id="myTestBean" class="com.guiji.bean.MyTestBean"></bean>

接下来就可以获取注册的bean了,我们看到我们自己写的测试类BeanFactoryTest ,获取bean的这行代码。

MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");

通过beanFactory.getBean(“myTestBean”)就可以获得MyTestBean对象。现在解析配置文件,注册到beanDefinitionMap中的只是一个BeanDefinition,Spring是怎么实现的呢?下面我们就分析beanFactory.getBean(“myTestBean”)这个方法都做了些什么。

分析源码实现

跟进beanFactory.getBean方法,我们来到AbstractBeanFactory这个类的getBean方法中。

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

这个方法又继续调用了doGetBean方法。

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

		final String beanName = transformedBeanName(name);
		Object bean;
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}else {
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}
			BeanFactory parentBeanFactory = getParentBeanFactory();
			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) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}else if (requiredType != null) {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
				String[] dependsOn = mbd.getDependsOn();
				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);
						}
					}
				}
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							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 {
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					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 ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}
		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的这块逻辑。先看下面这一部分代码。

//
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
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);
		}
	}
}
if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

这里主要做了三件事。
1、将我们之前注册到beanDefinitionMap中的BeanDefinition转换成RootBeanDefinition,并且合并父类的相关属性。
2、判断是否是单例,是的话通过getSingleton方法来获取一个实例。spring默认bean就是单例,这里我们就以单例来分析。
3、通过getObjectForBeanInstance来返回bean。一般来说,getSingleton方法返回的这个实例就是我们需要的bean了,但是有的时候我们可能会在xml文件中配置一个FactoryBean,那这个时候2中返回的就是FactoryBean了,但是这个FactoryBean并不是我们想要的这个bean,我们想要的是FactoryBean.getObject()方法中返回的这个bean。而getObjectForBeanInstance这个方法就是来处理这两种情况的,根据不同的情况来返回不同的bean。

下面我们重点看看2中,getSingleton里面的逻辑是怎么样的。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}catch (IllegalStateException ex) {
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

这段代码的主要内容是
1、根据beanName从缓存中获取实例。this.singletonObjects.get(beanName)。因为是单例,所以这边如果已经创建了就无需再重复创建实例,直接用之前创建的就可以。
2、如果缓存中不存在,记录bean加载状态。beforeSingletonCreation(beanName)。在这个方法里面调用了this.singletonsCurrentlyInCreation.add(beanName)这个方法,将beanName添加到了singletonsCurrentlyInCreation中来表示这个bean正在加载中。
3、通过调用singletonFactory的getObject()方法来加载实例。singletonObject = singletonFactory.getObject();稍后我们重点分析。
4、删除bean加载状态。afterSingletonCreation(beanName);就是将这个beanName从singletonsCurrentlyInCreation中移除。
5、将实例放到缓存,并将singletonFactories和earlySingletonObjects中的记录移除。这两个记录主要是为了解决循环依赖的,后面会详细说明。

下面我们主要看看3中调用singletonFactory的getObject()方法来加载实例的逻辑。

sharedInstance = getSingleton(beanName, () -> {
	try {
		return createBean(beanName, mbd, args);
	}catch (BeansException ex) {
		destroySingleton(beanName);
		throw ex;
	}
});

singletonFactory是通过getSingleton这个方法一参数的形式传入的,singletonFactory.getObject()这个方法执行的逻辑就是createBean(beanName, mbd, args)。我们进到createBean这个方法里面。

@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		RootBeanDefinition mbdToUse = mbd;
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		try {
			mbdToUse.prepareMethodOverrides();
		}catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}
		try {
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			return beanInstance;
		}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			throw ex;
		}catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

这里面创建实例的代码主要在doCreateBean(beanName, mbdToUse, args)里面。
在doCreateBean里面也没有真正的创建逻辑,最终的创建逻辑是在BeanUtils.instantiateClass(Constructor ctor, Object… args)方法里面创建的。

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
			ReflectionUtils.makeAccessible(ctor);
			if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
				return KotlinDelegate.instantiateClass(ctor, args);
			}
			else {
				Class<?>[] parameterTypes = ctor.getParameterTypes();
				Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
				Object[] argsWithDefaultValues = new Object[args.length];
				for (int i = 0 ; i < args.length; i++) {
					if (args[i] == null) {
						Class<?> parameterType = parameterTypes[i];
						argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
					}
					else {
						argsWithDefaultValues[i] = args[i];
					}
				}
				return ctor.newInstance(argsWithDefaultValues);
			}
		}
	}

这段代码的内容主要为
1、通过构造器来获取构造函数的参数类型。这里的构造器是通过Class.getDeclaredConstructor()方法获取到的,而Class则是调用ClassUtils.forName(className, classLoader);这个方法来生成的。className这个参数的值就是BeanDefinition中classBean这个字段的值,也就是我们xml配置文件中class属性的值。
2、给构造函数的参数赋值。
3、通过反射创建实例对象。(当然不是所有的情况都是通过反射来创建实例对象,有时需要通过CGLIB来创建一个代理对象)

到这里bean就已经创建出来了,创建bean的主要逻辑就是通过beanName获取BeanDefinition,然后通过BeanDefinition中classBean这个字段用反射来去创建这个bean。最终将这个bean返回,就实现了bean的获取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值