前言

在《spring中FactoryBean是什么bean》一文中,带着小伙伴学习了spring中的FactoryBean,了解了到了FactoryBean其实是一种生产Bean的bean,也就是FactroyBean的前世是Bean,今生还是Bean,小伙伴要疑惑了都是Bean,但是此Bean非彼Bean。今天带着小伙伴从源码的角度来分析下FactoryBean,重点是getObjectForBeanInstance方法的分析。

前世

在前面说到FactoryBean的前世是一个Bean,是指是一个FactoryBean的实例。先来看下getObjectForBeanInstance方法,

/**
* Get the object for the given bean instance, either the bean
* instance itself or its created object in case of a 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.
//1、判断name是否以&开头
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
if (!(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.
//beanInstance不是FactoryBean的实例或name以&开头
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
} Object object = null;
//mbd即beanDefinition为空,从缓存中取
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
//缓存中没有,则调用FactoryBean的getObject方法,返回其对象
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

看该方法上的注释,

Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.

用我蹩脚的英语翻译过来大概是这个意思,

返回给定的bean Instance的一个对象,该对象可能是bean instance或者是由bean instance(是一个FactoryBean)创建的一个对象。

意思很明白了,该方法有可能返回的是一个FactoryBean的实例,也可能是由FactroyBean生产的实例,关键看方法参数中的前两个,

Object beanInstance  spring容器中的一个bean

String name   可能含有&前缀的名称

String beanName  bean的规范名称

RootBeanDefintion mbd  BeanDefinition

看下面的表格更容易理解该方法在各种情况下的返回值,

beanInstance name 返回值
FactoryBean的实例 带有& beanInstance
不是FactoryBean的实例 带有& beanInstance
FactoryBean的实例 不带& beanInstance生产的对象
不是FactoryBean的实例 不带& beanInstance

通过上面得表格再结合代码就很容易理解,只要是返回beanInstance对象,那么就是FactroyBean的前世,下面看FactoryBean的今生。

今生

这里有两个方法需要分析,分别是getCachedObjectForFactoryBean和getObjectFromFactoryBean。第一个方法是从缓存中获取,也就是说使用FactoryBean生产的bean会单独放在缓存中,非singletonObjects中,这点务必要注意。

getCachedObjectForFactoryBean

先看下该方法的定义,

@Nullable
protected Object getCachedObjectForFactoryBean(String beanName) {
return this.factoryBeanObjectCache.get(beanName);
}

可以看到很简单就是通过名称从factoryBeanObjectCache中取对象。factoryBeanObjectCache肯定是个map了

/** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

getObjectFromFactoryBean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
//把生产的实例对象放到factoryBeanObjectCache缓存中
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//调用getObject方法
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}

该方法就比较复杂了,主要有doGetObjectFromFactoryBean、beforeSingletonCreation、postProcessObjectFromFactoryBean、afterSingletonCreation方法,重要的一个是doGetFromFactroyBean,也就是真正干活生产bean的方法。其定义如下,其余方法可自行查看

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException { Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//调用FactoryBean中的getObject方法,返回其实例对象
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
} // Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}

在上文中的注释部分已经看到最终调用了getObject方法,也就是返回的是FactoryBean中getObject方法的返回值。

总结

主要分析了FactoryBean的底层源码,判断是返回FactoryBean的实例还是返回其生产的实例,主要看bean的类型是否为FactoryBean和名称中是否带&。

推荐:《spring中FactoryBean是什么bean

一次性讲清楚spring中bean的生命周期之一:getSingleton方法 》

一次性讲清楚spring中bean的生命周期之二:FactoryBean的前世今生的更多相关文章

  1. 一次性讲清楚spring中bean的生命周期之三:bean是如何实例化的

    在前面的两篇博文<一次性讲清楚spring中bean的生命周期之一:getSingleton方法>和<一次性讲清楚spring中bean的生命周期之二:FactoryBean的前世今 ...

  2. 一次性讲清楚spring中bean的生命周期之一:getSingleton方法

    要想讲清楚spring中bean的生命周期,真的是不容易,以AnnotationConfigApplicationContext上下文为基础来讲解bean的生命周期,AnnotationConfigA ...

  3. JAVA面试题:Spring中bean的生命周期

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  4. 深入理解Spring中bean的生命周期

    [Spring中bean的生命周期] bean的生命周期 1.以ApplocationContext上下文单例模式装配bean为例,深入探讨bean的生命周期: (1).生命周期图: (2).具体事例 ...

  5. Spring中Bean的生命周期及其扩展点

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6106456.html Spring中Bean的管理是其最基本的功能,根据下面的图来了解Spr ...

  6. 简:Spring中Bean的生命周期及代码示例

    (重要:spring bean的生命周期. spring的bean周期,装配.看过spring 源码吗?(把容器启动过程说了一遍,xml解析,bean装载,bean缓存等)) 完整的生命周期概述(牢记 ...

  7. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  8. 一分钟掌握Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean 的别名只能维持 ...

  9. Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

随机推荐

  1. 项目展示$\alpha$

    项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求 强制转会与项目展示 我们在这个课程的目标是 提升团队管理及合作能力,开发一项满意的工程项目 这个作业在哪个具体方面帮助我们实现目标 ...

  2. Jsp授课

    2.1 JSP基础 2.1.1 JSP简介 JSP全称是Java Server Page,是一种动态网页技术标准.它和Servlet一样,也是sun公司推出的一套开发动态web资源的技术,称为JSP/ ...

  3. 如何使用ghost备份系统?

    如何使用ghost备份系统? 如何使用ghost工具电脑系统备份?需要具体的详细步骤 关注者 11 被浏览 13,197 关注问题写回答 ​邀请回答 ​添加评论 ​分享 ​     1 个回答 默认排 ...

  4. STM32自己的封装库

    以前一直使用STM32的标准库,需要一步步地将代码加进去,将编译选项设置好,然后再编译整个工程. 这个编译过程是一个相当慢的过程!完全编译大约需要一支烟的时间.每次建立工程都这么编译,是一个相当浪费时 ...

  5. Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息。

    Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息.   本文链接:https://blog.csdn.net/qq_38161040/art ...

  6. python做反被爬保护的方法

    python做反被爬保护的方法 网络爬虫,是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成.但是当网络爬虫被滥用后,互联网上就出现太多同质的东西,原创得不到保护.于是,很 ...

  7. Go语言练习---判断闰年以及根据现在的秒数求现在的年月日

    package main import ( "fmt" "math" "time" ) /* @闰年判断 ·封装一个函数判断某一个年份是不是 ...

  8. Error attempting to get column from result set

    当使用mybatis plus3.2.0+springboot2.1.1 报错 Error attempting to get column from result set 1.一般出现这种问题,最简 ...

  9. Linux下Flash-LED的处理

    Linux下Flash-LED的处理 一些LED设备提供两种模式-torch和flash.在LED子系统中,LED类(参见Linux下的LED处理)和LED Flash类,分别支持这些模式.torch ...

  10. TOF摄像机可以替代Flash激光雷达吗?

    TOF摄像机可以替代Flash激光雷达吗? 一.基于ToF技术的Flash激光雷达 基本成像原理上ToF Camera与LiDAR相同,都采用飞行时间测距技术(包括利用APD或SPAD的直接测距法,和 ...