IoC容器的依赖注入
前面的两篇博客对IoC容器的初始化进行了详细的分析,这个初始化过程完成的主要的工作是在IoC容器中建立BeanDefinition数据映射,在这个过程中并没有看到IoC容器对Bean依赖关系进行注入,接下来分析一下IoC容器是怎么样对Bean的依赖关系进行注入的。
假设当前IoC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,注意到依赖注入的过程是用户第一次向IoC容器所要Bean的时候触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过lazy-init属性来让容器完成对Bean的预实例化。
这个预实例化实际上也是一个完成依赖注入的过程,但是它是在初始化的过程中完成的。BeanFactory的getBean就是触发依赖注入发生的地方。
下面从DefaultListableBeanFactory的基类AbstractBeanFactory入手去看看getBean的实现。
//这里是对BeanFactory接口的实现,比如getBean接口方法
//这些getBean接口方法最终是通过调用doGetBean来实现的。
public Object getBean(String name) throws BeansException
{
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return this.doGetBean(name, requiredType, (Object[])null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
return this.doGetBean(name, (Class)null, args, false);
}
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return this.doGetBean(name, requiredType, args, false);
}
//这里是实际获取Bean的地方,也是触发依赖注入发生的地方
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException
{
final String beanName = this.transformedBeanName(name);
//先从缓存中取得Bean,处理那些已经被创建过的单例模式的Bean,对这种Bean的请求不需要重复的创建
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null)
{
if (this.logger.isDebugEnabled())
{
if (this.isSingletonCurrentlyInCreation(beanName))
{
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
}
else
{
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//这里的getObjectForBeanInstance完成的是FactoryBean的相关处理,以取得FactoryBean的生产关系
//BeanFactory和FactoryBean的区别在前面讲过,这个过程在后面还会详细的分析。
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
}
else
{
if (this.isPrototypeCurrentlyInCreation(beanName))
{
throw new BeanCurrentlyInCreationException(beanName);
}
//这里对IoC的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取得需要的Bean,如果在当前的工厂中
//取不到,则到双亲BeanFactory中去取,如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链向上查找。
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName))
{
String nameToLookup = this.originalBeanName(name);
if (args != null)
{
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
if (!typeCheckOnly)
{
this.markBeanAsCreated(beanName);
}
try
{
//这里根据Bean的名字取得BeanDefinition
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
//获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有任何依赖的Bean为止
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null)
{
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13)
{
String dep = var11[var13];
if (this.isDependent(beanName, dep))
{
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
this.getBean(dep);
}
}
//这里通过调用createBean方法创建Singleton bean的实例,这里有一个回调函数getObject,会在getSingleton中
//调用ObjectFactory的createBean
//下面进入到createBean中进行详细分析
if (mbd.isSingleton())
{
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>()
{
public Object getObject() throws BeansException
{
try
{
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
}
catch (BeansException var2)
{
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//这里是创建prototype bean的地方
else if (mbd.isPrototype())
{
var11 = null;
Object prototypeInstance;
try
{
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
}
finally
{
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else
{
String scopeName = mbd.getScope();
Scope 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, new ObjectFactory<Object>()
{
public Object getObject() throws BeansException
{
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
Object var1;
try
{
var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
}
finally
{
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException var21)
{
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", var21);
}
}
}
catch (BeansException var23)
{
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
//这里对创建对bean进行类型检查,如果没有问题,就返回这个新建的bean,这个bean已经是包含了依赖关系的Bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass()))
{
try
{
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException var22)
{
if (this.logger.isDebugEnabled())
{
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
else
{
return bean;
}
}
getSingleton实现
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
//具体实现
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//在已经注册了的单例map集合(singletonObjects)中获取特定beanName的bean
Object singletonObject = this.singletonObjects.get(beanName);
//检查这个bean是不是null,并且这个bean不在正在创建中的bean的map缓存(singletonsCurrentlyInCreation)中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从已经缓存了的单利对象集合中获取beanName对应的Bean
singletonObject = this.earlySingletonObjects.get(beanName);
//如果不存在,并且允许早期引用当前创建的对象
if (singletonObject == null && allowEarlyReference) {
//根据beanName获取在可以在调用时返回单例Object实例)的工厂。
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果返回的工厂不为空就把对应的beanName放到earlySingletonObjects中,并移除singletonFactories中的值
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
//如果获取到的对象是空,就返回null
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。我们都知道,对于IoC容器的使用,Spring提供了许多的参数配置,每一个参数配置代表了一个IoC容器的实现特性,这些实现特性很多需要在依赖注入的过程中或者对Bean进行生命周期管理中完成,尽管可以用最简单的方式来描述IoC容器,将它看成一个hashMap,但是只能说这个hashMap是容器的最基本的数据结构,而不是IoC容器的全部,SpringIoC容器作为一个产品,其价值体现在一系列相关的产品特性上,这些产品特性以依赖反转模式的实现为核心,为用户更好的使用依赖反转提供便利,从而实现一个完整的IoC容器。
下面的图可以看成是依赖注入的一个大致的过程
重点来说,getBean是依赖注入的起点,之后会调用createBean,下面通过createBean代码来了解这个过程,在这个过程中,Bean对象会根据BeanDefinition定义的要求生成,在AbstractAutowireCapableBeanFactory实现了这个createBean,createBean不但生产了需要的Bean,还对Bean初始化进行了处理,比如实现了BeanDefinition中的init-method属性定义,Bean后置处理器等。
AbstractAutowireCapableBeanFactory中的createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException
{
if (this.logger.isDebugEnabled())
{
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null)
{
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//这里判断需要创建的Bean是否可以实例化,这个类是否可以通过类装载器载入
try
{
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException var7)
{
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var7);
}
Object beanInstance;
try
{
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null)
{
return beanInstance;
}
}
catch (Throwable var8)
{
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
}
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isDebugEnabled())
{
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}