在前面我们分析Spring IOC 容器实例化Bean 并进行依赖注入过程的源码时,提到在getBean()方法触发容器实例化Bean 的时候会调用AbstractBeanFactory 的doGetBean()方法来进行实例化的过程,源码如下:

//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖//如果指定的是别名,将别名转换为规范的Bean名称final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.//先从缓存中取是否已经有被创建过的单态类型的Bean//对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建Object sharedInstance = getSingleton(beanName);//IOC容器创建单例模式Bean实例对象if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {//如果指定名称的Bean在容器中已有单例模式的Bean被创建//直接返回已经创建的Beanif (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 + "'");}}//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理//注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是//创建创建对象的工厂Bean,两者之间有区别bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.//缓存没有正在创建的单例模式Bean//缓存中已经有已经创建的原型模式Bean//但是由于循环引用的问题导致实例化对象失败if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.//对IOC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否//能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找BeanFactory parentBeanFactory = getParentBeanFactory();//当前容器的父级容器存在,且当前容器中不存在指定名称的Beanif (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.//解析指定Bean名称的原始名称String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else 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);}}//创建的Bean是否需要进行类型验证,一般不需要if (!typeCheckOnly) {//向容器标记指定的Bean已经被创建markBeanAsCreated(beanName);}try {//根据指定Bean名称获取其父级的Bean定义//主要解决Bean继承时子类合并父类公共属性问题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();//如果当前Bean有依赖Beanif (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}//递归调用getBean方法,获取当前Bean的依赖BeanregisterDependentBean(dep, beanName);//把被依赖Bean注册给当前依赖的BeangetBean(dep);}}// Create bean instance.//创建单例模式Bean的实例对象if (mbd.isSingleton()) {//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象sharedInstance = getSingleton(beanName, () -> {try {//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义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.//显式地从容器单例模式Bean缓存中清除实例对象destroySingleton(beanName);throw ex;}});//获取给定Bean的实例对象bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}//IOC容器创建原型模式Bean实例对象else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.//原型模式(Prototype)是每次都会创建一个新的对象Object prototypeInstance = null;try {//回调beforePrototypeCreation方法,默认的功能是注册当前创建的原型对象beforePrototypeCreation(beanName);//创建指定Bean对象实例prototypeInstance = createBean(beanName, mbd, args);}finally {//回调afterPrototypeCreation方法,默认的功能告诉IOC容器指定Bean的原型对象不再创建afterPrototypeCreation(beanName);}//获取给定Bean的实例对象bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}//要创建的Bean既不是单例模式,也不是原型模式,则根据Bean定义资源中//配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中//比较常用,如:request、session、application等生命周期else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);//Bean定义资源中没有配置生命周期范围,则Bean定义不合法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的实例对象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.//对创建的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.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;
}
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.//容器已经得到了Bean实例对象,这个实例对象可能是一个普通的Bean,//也可能是一个工厂Bean,如果是一个工厂Bean,则使用它创建一个Bean实例对象,//如果调用本身就想获得一个容器的引用,则指定返回这个工厂Bean实例对象//如果指定的名称是容器的解引用(dereference,即是对象本身而非内存地址),//且Bean实例也不是创建Bean实例对象的工厂Beanif (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.//如果Bean实例不是工厂Bean,或者指定名称是容器的解引用,//调用者向获取对容器的引用,则直接返回当前的Bean实例if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//处理指定名称不是容器的解引用,或者根据名称获取的Bean实例对象是一个工厂Bean//使用工厂Bean创建一个Bean的实例对象Object object = null;if (mbd == null) {//从Bean工厂缓存中获取给定名称的Bean实例对象object = getCachedObjectForFactoryBean(beanName);}//让Bean工厂生产给定名称的Bean对象实例if (object == null) {// Return bean instance from factory.FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.//如果从Bean工厂生产的Bean是单态模式的,则缓存if (mbd == null && containsBeanDefinition(beanName)) {//从容器中获取指定名称的Bean定义,如果继承基类,则合并基类相关属性mbd = getMergedLocalBeanDefinition(beanName);}//如果从容器得到Bean定义信息,并且Bean定义信息不是虚构的,//则让工厂Bean生产Bean实例对象boolean synthetic = (mbd != null && mbd.isSynthetic());//调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法,//实现工厂Bean生产Bean对象实例的过程object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;
}

在上面获取给定Bean 的实例对象的getObjectForBeanInstance() 方法中, 会调用FactoryBeanRegistrySupport 类的getObjectFromFactoryBean()方法,该方法实现了Bean 工厂生产Bean 实例对象。

Dereference(解引用):一个在C/C++中应用比较多的术语,在C++中,”*”是解引用符号,而”&”是引用符号,解引用是指变量指向的是所引用对象的本身数据,而不是引用对象的内存地址。

AbstractBeanFactory 的getBean()方法调用FactoryBean相关推荐

  1. spring getBean()方法解析概述

    1.getBean(beanName) 整体概述 1.transformedBeanName(name) name可能是别名,将别名(alias)解析成真正的beanName 截取&beanN ...

  2. 详解Spring中getBean()方法

    我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean.那么,getBean()方法是怎么一步步完成从spring容器中获取bean的呢? 下面我们就通过源码分析一下. 一 ...

  3. Sonar问题解决:普通方法调用静态属性

    问题:普通方法调用静态属性时,Sonar会认为有问题 这是我们经常用的,实现Spring的Bean工厂,写一个工具类, 开放一个静态方法:获取实体类 public class BeanHelper i ...

  4. spring声明式事务 同一类内方法调用事务失效

    一 宏观说明 [问题] Spring的声明式事务,我想就不用多介绍了吧,一句话"自从用了Spring AOP啊,事务管理真轻松啊,真轻松:事务管理代码没有了,脑不酸了,手不痛了,一口气全配上 ...

  5. Spring service本类中方法调用另一个方法事务不生效问题

    前些日子一朋友在需要在目标对象中进行自我调用,且需要实施相应的事务定义,且网上的一种通过BeanPostProcessor的解决方案是存在问题的.因此专门写此篇帖子分析why. 1.预备知识 aop概 ...

  6. Spring源码讲解之 getBean 方法

    getBean 方法是用来进行获取 bean 实例对象的,是我们进行 spring 程序开发从 bean 工厂获取结果的.那这个方法的执行过程是什么样的,下面我们就去揭开它的面纱. 样例代码 Appl ...

  7. 关于Bean标签的一些属性以及getBean()方法

    id属性: Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成,就相当于给 它起一个名字,到时候调用的时候就通过id来调用 class属性: 该属性指定了 Bean ...

  8. Spring事务内方法调用自身事务

    Spring事务内方法调用自身事务 增强的三种方式 ServiceA.java文件: 查看Spring Tx的相关日志: 可以看到只创建了一个事物ServiceA.service方法的事务,但是cal ...

  9. springboot 调用方法事物_SpringBoot 内部方法调用,事务不起作用的原因及解决办法...

    在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景 ...

最新文章

  1. Python中常用的数据分析工具(模块)有哪些?
  2. 计算机科学界至今未解决的四大难题
  3. 二叉搜索树的最近祖先
  4. Python程序设计题解【蓝桥杯官网题库】 DAY6-基础练习
  5. ASP.NET MVC4 微信公众号开发之网页授权(一):搭建基础环境
  6. 如何指南:Apache Drill入门
  7. 【JavaWeb】HTML+CSS
  8. 信息学奥赛一本通 1022:整型与布尔型的转换 | OpenJudge NOI 1.2 09
  9. Java 算法 质因数2
  10. linux i查看o性能度量,在linux系统中I/O 调度的选择
  11. ARM、DSP、FPGA的区别
  12. java位原子_Java原子操作AtomicInteger的用法
  13. [置顶] 原来JAVA对象转JSON格式的字符串如此简单,返回来暂时不会做,留下纪念下
  14. swift PickerView
  15. 【Matlab免费安装】
  16. 高频课程实验:无线传输系统设计
  17. 连接上局域网打开计算机卡,win7怎么玩局域网游戏,win7怎么玩局域网游戏卡
  18. curl上传文件到服务器命令,linux curl上传文件到服务器
  19. cta 音频测试_CTA测试介绍.pdf
  20. 非洲大陆自贸区正式启动,非洲电商迎来新一轮高速发展期

热门文章

  1. Linux下安装并破解StarUML
  2. 【转】Android 4.4前后版本读取图库图片和拍照完美解决方案
  3. C# 版本设计模式(Design Pattern)---------------总序
  4. 诗歌rails之 Logger
  5. 【css3】旋转倒计时
  6. NOKIA Update for Windows Phone
  7. lucene升级至5.x版本出现 :IllegalStateException: IllegalStateException: unexpected docvalues type NONE...
  8. CentOS5.6 安装RabbitMQ
  9. 养殖者运送猫狗过河问题(面向对象)
  10. 美!视差滚动在图片滑块中的应用【附源码下载】