Spring创建单例Bean关键源码分析
在上一篇文章中,我一步步分析了使用 BeanFactory 获取并创建 Bean 的过程,并且解释了 Spring 是如何解决循环依赖的?
- 上一篇博客:Spring是如何解决循环依赖的?
类继承结构
- DefaultSingletonBeanRegistry 负责单例的注册
- AbstractAutowireCapableBeanFactory 自动装配工厂
创建Bean核心过程简化
其中,橙色为 protected 方法,绿色为 public 方法
- getBean 获取并创建 Bean
- doGetBean 具体的获取方法
- doCreateBean 具体的创建 Bean 的方法
- populateBean 填充属性
- 填充属性时,有可能需要获取并创建新的 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 的方法 doCreateBean。createBean 是由 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 方法中,请看下图
结论:在发生循环依赖时,无论你在 postProcessBeforeInitialization 和 postProcessAfterInitialization 做何种后置处理,最终暴露给 BService 对象使用的引用,以及最后 getBean 返回的都将是 getEarlyBeanReference 后置处理后的 AService 对象。