前言

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

前世

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

  1. /**
  2. * Get the object for the given bean instance, either the bean
  3. * instance itself or its created object in case of a FactoryBean.
  4. */
  5. protected Object getObjectForBeanInstance(
  6. Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
  7.  
  8. // Don't let calling code try to dereference the factory if the bean isn't a factory.
    //1、判断name是否以&开头
  9. if (BeanFactoryUtils.isFactoryDereference(name)) {
  10. if (beanInstance instanceof NullBean) {
  11. return beanInstance;
  12. }
  13. if (!(beanInstance instanceof FactoryBean)) {
  14. throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
  15. }
  16. }
  17.  
  18. // Now we have the bean instance, which may be a normal bean or a FactoryBean.
  19. // If it's a FactoryBean, we use it to create a bean instance, unless the
  20. // caller actually wants a reference to the factory.
    //beanInstance不是FactoryBean的实例或name以&开头
  21. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
  22. return beanInstance;
  23. }
  24.  
  25. Object object = null;
    //mbd即beanDefinition为空,从缓存中取
  26. if (mbd == null) {
  27. object = getCachedObjectForFactoryBean(beanName);
  28. }
    //缓存中没有,则调用FactoryBean的getObject方法,返回其对象
  29. if (object == null) {
  30. // Return bean instance from factory.
  31. FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
  32. // Caches object obtained from FactoryBean if it is a singleton.
  33. if (mbd == null && containsBeanDefinition(beanName)) {
  34. mbd = getMergedLocalBeanDefinition(beanName);
  35. }
  36. boolean synthetic = (mbd != null && mbd.isSynthetic());
  37. object = getObjectFromFactoryBean(factory, beanName, !synthetic);
  38. }
  39. return object;
  40. }

看该方法上的注释,

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

先看下该方法的定义,

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

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

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

getObjectFromFactoryBean

  1. protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
  2. if (factory.isSingleton() && containsSingleton(beanName)) {
  3. synchronized (getSingletonMutex()) {
  4. Object object = this.factoryBeanObjectCache.get(beanName);
  5. if (object == null) {
  6. object = doGetObjectFromFactoryBean(factory, beanName);
  7. // Only post-process and store if not put there already during getObject() call above
  8. // (e.g. because of circular reference processing triggered by custom getBean calls)
  9. Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
  10. if (alreadyThere != null) {
  11. object = alreadyThere;
  12. }
  13. else {
  14. if (shouldPostProcess) {
  15. if (isSingletonCurrentlyInCreation(beanName)) {
  16. // Temporarily return non-post-processed object, not storing it yet..
  17. return object;
  18. }
  19. beforeSingletonCreation(beanName);
  20. try {
  21. object = postProcessObjectFromFactoryBean(object, beanName);
  22. }
  23. catch (Throwable ex) {
  24. throw new BeanCreationException(beanName,
  25. "Post-processing of FactoryBean's singleton object failed", ex);
  26. }
  27. finally {
  28. afterSingletonCreation(beanName);
  29. }
  30. }
    //把生产的实例对象放到factoryBeanObjectCache缓存中
  31. if (containsSingleton(beanName)) {
  32. this.factoryBeanObjectCache.put(beanName, object);
  33. }
  34. }
  35. }
  36. return object;
  37. }
  38. }
  39. else {
    //调用getObject方法
  40. Object object = doGetObjectFromFactoryBean(factory, beanName);
  41. if (shouldPostProcess) {
  42. try {
  43. object = postProcessObjectFromFactoryBean(object, beanName);
  44. }
  45. catch (Throwable ex) {
  46. throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
  47. }
  48. }
  49. return object;
  50. }
  51. }

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

  1. private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
  2. throws BeanCreationException {
  3.  
  4. Object object;
  5. try {
  6. if (System.getSecurityManager() != null) {
  7. AccessControlContext acc = getAccessControlContext();
  8. try {
  9. object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
  10. }
  11. catch (PrivilegedActionException pae) {
  12. throw pae.getException();
  13. }
  14. }
  15. else {
    //调用FactoryBean中的getObject方法,返回其实例对象
  16. object = factory.getObject();
  17. }
  18. }
  19. catch (FactoryBeanNotInitializedException ex) {
  20. throw new BeanCurrentlyInCreationException(beanName, ex.toString());
  21. }
  22. catch (Throwable ex) {
  23. throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
  24. }
  25.  
  26. // Do not accept a null value for a FactoryBean that's not fully
  27. // initialized yet: Many FactoryBeans just return null then.
  28. if (object == null) {
  29. if (isSingletonCurrentlyInCreation(beanName)) {
  30. throw new BeanCurrentlyInCreationException(
  31. beanName, "FactoryBean which is currently in creation returned null from getObject");
  32. }
  33. object = new NullBean();
  34. }
  35. return object;
  36. }

在上文中的注释部分已经看到最终调用了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. Redis数据持久化—RDB持久化与AOF持久化

    目录 Redis数据持久化-RDB持久化与AOF持久化 RDB持久化 RDB文件的创建 RDB文件的载入 自动间隔性保存 检查保存条件是否满足 AOF持久化 AOF持久化的实现 AOF文件的载入与数据 ...

  2. slickgrid ( nsunleo-slickgrid ) 8 区域选择与复制粘贴

    区域选择 区域选择是通过插件CellRangeSelector实现的,默认不支持跨冻结列进行选择,修正了选择,支持跨冻结列,代码如下,通过判断选择的起点和终点所落在的冻结范围进行计算,如从左往右进行复 ...

  3. 1.7 Systemd初始化进程

    1.7 Systemd初始化进程 Linux操作系统的开机过程是这样的,即从BIOS开始,然后进入Boot Loader,再加载系统内核,然后内核进行初始化,最后启动初始化进程.初始化进程作为Linu ...

  4. Java 程序流程控制语句

    顺序语句 语句:使用分号分隔的代码称作为一个语句 注意:没有写任何代码只是一个分号的时候,也是一条语句,称作空语句 顺序语句就是按照从上往下的顺序执行的语句 Scanner scanner = new ...

  5. STM32串口编程易错点

    注意   串口发送函数 使用STM官方的LIB 中的库函数发送之后 加一点延时   否则会错误  接收数据不正常 正确做法是  加上等待发送完成

  6. STM32 KEIL 下的 printf 函数

    1 //加入以下代码,支持printf函数,而不需要选择use MicroLIB 2 #if 1 3 #pragma import(__use_no_semihosting) 4 //标准库需要的支持 ...

  7. python 交换变量值为何不需要中间变量

    python 元组解包unpacking,同一语句中多重赋值 cpython 认为几种变量的交换是比较常见的,提供了专门的优化指令,像[-5,256]预先放到了整数池中一样,

  8. 第6讲 | 交换机与VLAN:办公室太复杂,我要回学校

    第6讲 | 交换机与VLAN:办公室太复杂,我要回学校 拓扑结构是怎么形成的? 一个交换机肯定不够用,需要多台交换机,交换机之间连接起来,就形成一个稍微复杂的拓扑结构. 如何解决常见的环路问题? 包转 ...

  9. Linux将一个文件夹或文件夹下的所有内容复制到另一个文件夹

    Linux将一个文件夹或文件夹下的所有内容复制到另一个文件夹     1.将一个文件夹下的所有内容复制到另一个文件夹下 cp -r /home/packageA/* /home/cp/packageB ...

  10. celery 简单示例

    目录结构 第一步  celery_task 里面的celery文件 import time from celery import Celery # celery from celery.schedul ...