Spring创建单例Bean关键源码分析

在上一篇文章中,我一步步分析了使用 BeanFactory 获取并创建 Bean 的过程,并且解释了 Spring 是如何解决循环依赖的?

类继承结构

  • DefaultSingletonBeanRegistry 负责单例的注册
  • AbstractAutowireCapableBeanFactory 自动装配工厂

创建Bean核心过程简化

其中,橙色为 protected 方法,绿色为 public 方法

  1. getBean 获取并创建 Bean
  2. doGetBean 具体的获取方法
  3. doCreateBean 具体的创建 Bean 的方法
  4. populateBean 填充属性
  5. 填充属性时,有可能需要获取并创建新的 Bean,再次回到第 1 步

接口 BeanFactory 中的 getBean 方法有 5 个:

其中 2 个以对象类型为参数的 getBean 方法是由 DefaultListableBeanFactory 实现的。

// 返回与给定对象类型唯一匹配的bean实例(如果有)
public <T> T getBean(Class<T> requiredType) throws BeansException { // ...(省略) }
// 返回指定bean的实例,该实例可以是共享的,也可以是独立的。
// 允许指定显式构造函数参数/工厂方法参数,并覆盖bean定义中指定的默认参数(如果有)
public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException { // ...(省略) }

剩下 3 个由 AbstractBeanFactory 实现,并且都调用了 doGetBean 方法

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

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

Spring 创建俯瞰图


这个是我自己画的一张Spring 创建单例 Bean 的流程图,看不懂先别着急,让我接下来细细分说。

getSingleton

获取单例的两个方法都是在 DefaultSingletonBeanRegistry 中实现的。

getSingleton(beanName, singletonFactory)

首先介绍的是参数为 ObjectFactory 的getSingle方法:

/**
 * 返回以给定名称注册的(原始)单例对象,
 * 如果尚未注册,则创建并注册一个新的。
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {  // ...(省略) }

该方法内的重要方法如图所示:

beforeSingletonCreation(String beanName)afterSingletonCreation(String beanName) 一个标识创建开始,一个标识创建结束,与之相关的还有一个方法

/**
 * 返回指定的单例bean当前是否正在创建中
 */
public boolean isSingletonCurrentlyInCreation(String beanName) {
	return this.singletonsCurrentlyInCreation.contains(beanName);
}

其中,singletonsCurrentlyInCreation 是保存正在创建中的单例bean的集合。

我们知道,调用该 getSingleton 方法是在 doGetBean 中,且其匿名内部类调用的是 createBean 方法,该方法被 AbstractAutowireCapableBeanFactory 覆写。源码如下

// AbstractBeanFactory.class
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
      // ... 省略
      // Create bean instance.
      if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
                  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);
      }
      // ... 省略
}
// 需要 AbstractBeanFactory 的子类覆写,最终由 AbstractAutowireCapableBeanFactory 实现
protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException;

addSingleton(String beanName, Object singletonObject) 方法将给定的单例对象添加到该工厂的单例缓存中。
即添加到singletonObjects 单例池中。

getSingleton(beanName, allowEarlyReference)

/**
 * 返回以给定名称注册的(原始)单例对象。
 * 检查已经实例化的单例,并且还允许对当前创建的单例的早期引用(解决循环引用)。
 */
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

这个方法涉及到 DefaultSingletonBeanRegistry 的三个集合:

  • singletonObjects 是单例的缓存,可以避免重复创建单例
  • earlySingletonObjects 是未完成单例的缓存,用来解决循环依赖
  • singletonFactories 是单例工厂集,也是用来解决循环依赖的,当方法参数 allowEarlyReference 为 true 时才会取出对应的单例工厂,执行创建,并且将单例的早期引用放入未完成单例集中。


如图所示,getSingleton(String beanName) 方法是目前唯一允许创建单例的早期引用的方法。

@Override
@Nullable
public Object getSingleton(String beanName) {
      return getSingleton(beanName, true);
}

doCreateBean

接下来,我们关注到实际负责创建 Bean 的方法 doCreateBeancreateBean 是由 AbstractAutowireCapableBeanFactory 覆写的,doCreateBean 也是该类的方法

  • createInstance 实例化Bean
  • addSingletonFactory 是在发生循环依赖的情况下,添加 ObjectFactory 到单例工厂集singletonFactories
  • populateBean 填充属性
  • initializeBean 初始化Bean

初始化Bean

初始化 Bean 又分为3个步骤:

  • applyBeanPostProcessorsBeforeInitialization 在执行初始化方法之前,进行前置操作
  • invokeInitMethods 执行初始化方法
    最常见的就是实现 InitializingBean 接口:
public interface InitializingBean {
	/**
	 * 此方法允许Bean实例在设置所有Bean属性后执行其整体配置的验证和最终初始化。
	 */
	void afterPropertiesSet() throws Exception;
}
  • applyBeanPostProcessorsAfterInitialization 在执行初始化方法之后,执行后置操作

以下是一个简单的代码示例:

// 实现初始化方法的类
public class MessageList implements InitializingBean {

    private List<String> messages = new ArrayList<>();

    public MessageList() {
        messages.add("createInstance");
    }

    public void addMessage(String msg) {
        messages.add(msg);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        messages.add("afterPropertiesSet");
    }

    public void printAllMessages() {
        for (String message : messages) {
            System.out.println(message);
        }
    }
}

测试类:

public class BeanFactoryTest {

    @Test
    public void messageListTest() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof MessageList) {
                    ((MessageList) bean).addMessage("postProcessBeforeInitialization");
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof MessageList) {
                    ((MessageList) bean).addMessage("postProcessAfterInitialization");
                }
                return bean;
            }
        });
        RootBeanDefinition def = new RootBeanDefinition(MessageList.class);
        factory.registerBeanDefinition("messageList", def);
        MessageList bean = factory.getBean(MessageList.class);
        bean.printAllMessages();
    }
}

输出结果:

循环依赖的后置处理

假设 AService 和 BService 构成循环依赖

public class AService {
    private BService bService;

    public BService getBService() {
        return bService;
    }
    public void setBService(BService bService) {
        this.bService = bService;
    }
}

public class BService {
    private AService aService;

    public AService getAService() {
        return aService;
    }

    public void setAService(AService aService) {
        this.aService = aService;
    }
}

然后我们写出测试类

public class ABServiceBeanFactoryTest {

    @Test
    public void test() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        factory.addBeanPostProcessor(new SmartInstantiationAwareBeanPostProcessor() {
            @Override
            public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
                if (bean instanceof AService) {
                    return new AService$Proxy((AService) bean);
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                return bean;
            }
        });
        {
            RootBeanDefinition definition = new RootBeanDefinition(AService.class);
            definition.setPropertyValues(new MutablePropertyValues().add("bService", new RuntimeBeanReference(BService.class)));
            factory.registerBeanDefinition("aService", definition);
        }
        {
            RootBeanDefinition definition = new RootBeanDefinition(BService.class);
            definition.setPropertyValues(new MutablePropertyValues().add("aService", new RuntimeBeanReference(AService.class)));
            factory.registerBeanDefinition("bService", definition);
        }
        AService bean = factory.getBean(AService.class);
        Assert.assertEquals(bean, bean.getBService().getAService());
    }

    public static class AService$Proxy extends AService {

        private AService aService;

        public AService$Proxy(AService aService) {
            this.aService = aService;
        }

        @Override
        public BService getBService() {
            return aService.getBService();
        }
    }
}

BeanPostProcessor 接口对循环依赖不起作用

第一个值得注意的点,对于循环依赖 aService 而言,只有 SmartInstantiationAwareBeanPostProcessor 才能够后置处理 AService 的未完成实例,原因在 getEarlyBeanReference 方法中

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
                        // 只有 SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference 才能后置处理未完成的实例
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
	}
	return exposedObject;
}

为什么 postProcessAfterInitialization 对循环依赖对象不起作用?

第二点,如果增加了 postProcessBeforeInitialization(Object bean, String beanName)postProcessAfterInitialization(Object bean, String beanName) 后置处理方法,bean对象都是 AService 而不是 AService$Proxy ,但是最后 getBean 返回的结果是 AService$Proxy。

如图所示,postProcessAfterInitialization 传入的 Bean 对象是 AService。

如图所示,最终返回的是 AService$Proxy 对象,这是怎么做到的?
答案就在 AbstractAutowireCapableBeanFactory#doCreateBean 方法中,请看下图

结论:在发生循环依赖时,无论你在 postProcessBeforeInitializationpostProcessAfterInitialization 做何种后置处理,最终暴露给 BService 对象使用的引用,以及最后 getBean 返回的都将是 getEarlyBeanReference 后置处理后的 AService 对象。

原文地址:https://www.cnblogs.com/kendoziyu/p/spring-create-singleton-bean.html