zoukankan      html  css  js  c++  java
  • 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 对象。

  • 相关阅读:
    【转】关于char * 与 char[]
    网页打印js代码
    无法用排他锁锁定该数据库,以执行该操作。 (Microsoft SQL Server,错误: 5030)
    CKEditor使用笔记
    FormView作为单独编辑页笔记
    用WindowsMediaPlayer控件写个WinForm播放器
    ListView搭配DataPager控件实现分页笔记
    如何禁用ViewState
    C#获取本机IP搜集整理7种方法
    ListView高效率分页笔记
  • 原文地址:https://www.cnblogs.com/kendoziyu/p/spring-create-singleton-bean.html
Copyright © 2011-2022 走看看