回顾上篇
上篇文章《注册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的获取。