上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC容器是怎样实例化对象的。

  我们都使用过以下代码:

 FileSystemXmlApplicationContext  context=new FileSystemXmlApplicationContext("bean.xml");
User user=context.getBean("user",User.class);

  这样我们就能获取到user对象了,所以,不难想象,这个getBean方法就是实例化对象的入口。接下来我们就以这个方法为切入点,来探究IOC容器中bean的实例化过程。getBean方法是在FileSystemXmlApplicationContext的基类AbstractApplicationContext中定义的,代码如下:

 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name, requiredType);
}

  里面有很多重载方法,里面有调用了某个beanFactory的getBean方法。AbstractApplicationContext中并没有定义getBeanFactory这个方法,那一定是在FileSystemXmlApplicatio

—ntext的某个父类中定义的,我们再回过头看一下它的UML图:

  经过查找之后,是在AbstractRefreshableApplicationContext中定义的,且这个beanFactory是DefaultListableBeanFactory类型的:

 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {

     private Boolean allowBeanDefinitionOverriding;

     private Boolean allowCircularReferences;

     /** Bean factory for this context */
private DefaultListableBeanFactory beanFactory; /** Synchronization monitor for the internal BeanFactory */
private final Object beanFactoryMonitor = new Object();

  直接进入DefaultListableBeanFactory中,查看它的getBean方法:

public <T> T getBean(Class<T> requiredType) throws BeansException {
return getBean(requiredType, (Object[]) null);
}
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
if (namedBean != null) {
return namedBean.getBeanInstance();
}
BeanFactory parent = getParentBeanFactory();
if (parent != null) {
return parent.getBean(requiredType, args);
}
throw new NoSuchBeanDefinitionException(requiredType);
}

  发现里面只有这两个重载方法,其他getBean方法,包括例子中使用的那个重载方法没有看到,我们看一下DefaultListableBeanFactory类的UML图:

  经查找,发现在父类AbstractBeanFactory中定义了其他的getBean方法,如下:

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

  里面都调用了doGetBean方法,那么进入继续跟踪:

 protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//将bean的name进行转换,比如将name前面的“&”符去掉,带“&”的name,获取的是beanFactory本身,而不是
//beanFactory生成出来的bean实例
final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
//看缓存中是否已经有该bean
Object sharedInstance = getSingleton(beanName);
//如果缓存中有
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//如果sharedInstance是FactoryBean类型,则返回它生产的对象,否则,返回它本身
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//如果缓存中没有,第一次创建的时候
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // Check if bean definition exists in this factory.
//获取父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果父容器存在,且在当前容器中没有找到该名称的bean的数据
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//则到父容器中进行处理
// Not found -> check parent.
//将name前加上“&”
String nameToLookup = originalBeanName(name);
//分别对是否有参数的情况进行处理
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
//将数据封装成RootBeanDefinition对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查是否为抽象类
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
//获取当前创建的bean的依赖的bean
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 + "'");
}
//为当前bean和它的依赖对象建立映射关系
registerDependentBean(dep, beanName);
try {
//递归调用getBean方法,创建依赖对象,直到没有依赖对象为止
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
} // Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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()) {
// It's a prototype -> create a new instance.
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();
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, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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;
}
} // Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

  可以看到对不同scope域的bean的创建过程,其中会进行递归创建,现在进入createBean方法中,其实现是在AbstractAutowireCapableBeanFactory类中,代码如下:

 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//判断需要创建的bean是否可以实例化,是否可以通过类装载其进行装载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
} // Prepare method overrides.
try {
//这里是对overrides属性和look-up属性的处理
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
} try {
//AOP就是这里操作的,如果配置了postProcessor,则生成一个proxy返回,即代理类
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
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);
}
//创建bean的方法调用
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}

  进入doCreateBean方法:

 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException { // Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//如果是单例,先把缓存中的同名Bean清除
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如果缓存中没有
if (instanceWrapper == null) {
//则创建一个实例
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType; // Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//使用后置处理器进行处理
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
} // Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//这里是对单例的循环引用的处理
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
} //这里是对bean的初始化,依赖注入往往是在这里进行的,这个exposedObject在初始化完成之后会作为依赖注入完成之后的Bean
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性的填充
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
} if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
} // Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
} return exposedObject;
}

  这里要说一下,当在创建bean时,IOC会将该bean的名字存一份到singletonsCurrentlyInCreation这个map中,然后每次创建的时候都会到里面进行检查当前bean是否正在被创建。为了避免发生循环引用(A依赖B,B依赖C,C依赖A)引起是循环,在第一次创建bean时,IOC容器会把用于创建这个bean的工厂对象放入singletonFactories这个map中,key是这个正在被创建的bean的名字。这样发生循环依赖的时候,就不再调用getBean方法了,而是直接使用工厂创建一个bean给被依赖的对象。比如第一次创建A时,将A的名称存入了singletonsCurrentlyInCreation这个map中,并且调用addSingletonFactory方法,将创建A的工厂放到singletonFactories中了,然后递归调用getBean创建依赖对象B、C,创建C时,要先创建它的依赖对象A,此时,IOC容器检查到singletonsCurrentlyInCreation中已经有这个A了,说明它已经在创建的过程中,只是还没有完成创建,此时,IOC容器直接就使用这个工厂将A创建出来赋给C了,然后再往回完成B和A的创建。可以看一下addSingletonFactory方法的实现:

 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
 public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从缓存中获取该bean的实例,已经填充了属性值的实例
Object singletonObject = this.singletonObjects.get(beanName);
//创建bean时,IOC会在this.singletonsCurrentlyInCreation中存一个该bean的名称,表示正在创建这个bean
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//也是从缓存中获取实例,但是这个缓存中的实例是没有经过填充的实例
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//获取生成该bean的beanFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//获取这个bean的实例
singletonObject = singletonFactory.getObject();
//将这个还未经填充属性的bean存入新生代缓存中(自己取的名字,类似于JVM)
this.earlySingletonObjects.put(beanName, singletonObject);
//将这个生产bean的工厂移除
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

  在进行递归调用getBean方法创建依赖对象之前,getSignal方法是先调用的,前面的代码,doGetBean方法中可以看到,可以多看几遍就能理解。另外,对于原型实例,不允许循环引用。循环引用只针对单例。下一篇跟踪bean的属性的填充。

spring源码解析之IOC容器(三)——依赖注入的更多相关文章

  1. spring源码解析之IOC容器(一)

    学习优秀框架的源码,是提升个人技术水平必不可少的一个环节.如果只是停留在知道怎么用,但是不懂其中的来龙去脉,在技术的道路上注定走不长远.最近,学习了一段时间的spring源码,现在整理出来,以便日后温 ...

  2. spring源码解析之IOC容器(二)------加载和注册

    上一篇跟踪了IOC容器对配置文件的定位,现在我们继续跟踪代码,看看IOC容器是怎么加载和注册配置文件中的信息的.开始之前,首先我们先来了解一下IOC容器所使用的数据结构-------BeanDefin ...

  3. spring源码解析之IOC容器(四)——属性注入

    上一篇跟踪了bean的创建过程,接下来,我们继续跟踪bean的属性填充的过程.先回到doCreateBean方法,代码如下: protected Object doCreateBean(final S ...

  4. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  5. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

  6. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  7. 转 Spring源码剖析——核心IOC容器原理

    Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...

  8. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  9. 【spring源码分析】IOC容器初始化(七)

    前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...

随机推荐

  1. matlab 中使用 GPU 加速运算

    为了提高大规模数据处理的能力,matlab 的 GPU 并行计算,本质上是在 cuda 的基础上开发的 wrapper,也就是说 matlab 目前只支持 NVIDIA 的显卡. 1. GPU 硬件支 ...

  2. VSCode 小鸡汤 第00期 —— 安装和入门

    简介 这将是一个新的系列,将会以 Visual Studio Code(后文都简称为 VSCode 啦)的操作,环境配置,插件介绍为主,为大家不定期的介绍 VSCode 的一些操作技巧,所以取名 VS ...

  3. HDU 1867 A + B for you again KMP解决问题的方法

    这是一个典型问题KMP申请书. 结果求增加两个字符串.该法的总和是相同的前缀和后缀也是字符串的字符串,您将可以合并本节. 但是,这个问题是不是问题非常明确的含义,因为不是太清楚,外观这两个字符串的顺序 ...

  4. Oracle 11g系统分区表中的新功能

    在11g有一个新的特点是分区表系统.下面做一个实验: SQL> select * from v$version; BANNER --------------------------------- ...

  5. WPF使用DynamicDataDisplay.dll显示CPU及内存使用曲线

    原文:WPF使用DynamicDataDisplay.dll显示CPU及内存使用曲线 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/wangshub ...

  6. WPF 窗体中获取键盘和鼠标无操作时的超时提示

    原文:WPF 窗体中获取键盘和鼠标无操作时的超时提示 通过调用Windows API中的GetLastInputInfo来获取最后一次输入的时间 , , );            timer.Tic ...

  7. 在Windows系统上以C++打印出当前活动用户的环境变量

    在Windows系统上以C++打印出当前活动用户的环境变量,代码如下(QT环境): void getEnvironmentVariables() { DWORD sessionId = WTSGetA ...

  8. JS表格各行变色

    <head>    <title></title>    <script type="text/javascript">      ...

  9. WPF 流打印

    原文:WPF 流打印 PrintDialog printDialog = new PrintDialog(); if (printDialog.ShowDialog() == true) { Syst ...

  10. vs2015 cordova环境安装【个人遇到的几个问题】

    原文:vs2015 cordova环境安装[个人遇到的几个问题] 问题1: vs2015,设置  Debug  Android 设备[真机调试] Exception in thread "m ...