Spring IoC 源码刨析

目录

  • 一、源码前准备
    • 1、刨析源码的好处
    • 2、源码刨析原则
      • 1)定焦原则
      • 2)宏观原则
    • 3、读源码的方法和技巧
      • 1)断点
      • 2)反调
      • 3)经验
    • 4、Spring 源码构建
    • 5、Spring IoC 容器体系
    • 6、Bean 生命周期关键时机点
      • 1)LagouBean 类
      • 2)BeanPostProcessor 接口实现类
      • 3)BeanFactoryPostProcessor 接口实现类
      • 4)applicationContext.xml
      • 5)IoC 容器源码分析用例
      • 6)分析调用情况
    • 7、Spring IoC 容器初始化主流程
  • 二、BeanFactory 创建流程
    • 1、获取 BeanFactory 子流程
    • 2、BeanDefinition 加载解析及注册子流程
      • 1)该子流程涉及到如下几个关键步骤:
      • 2)过程分析
      • 3)时序图
  • 三、Bean 创建流程
    • 1、起始点
    • 2、过程
  • 四、 lazy-init 延迟加载机制原理
    • 1、分析
    • 2、总结

一、源码前准备

1、刨析源码的好处

提高培养代码架构思维、深入理解框架。

2、源码刨析原则

1)定焦原则

抓主线。

2)宏观原则

站在上帝视角,关注源码结构和业务流程(淡化具体某行代码的编码细节)。

3、读源码的方法和技巧

1)断点

观察调用栈。

2)反调

Find Usages。

3)经验

spring 框架中 doXXX,做具体处理的地方。

4、Spring 源码构建

  1. 下载源码(github)。
  2. 安装 gradle 5.6.3(类似于maven) Idea 2019.1 Jdk 11.0.5
  3. 导入(耗费一定时间)
  4. 编译工程(顺序:core - oxm - context - beans - aspects - aop)
    点击:工程 —> tasks —> compileTestJava

5、Spring IoC 容器体系

  • IoC 容器是 Spring 的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。
  • Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的 ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等一系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。
  • Spring IoC 容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的。

BeanFactory 顶级接口方法栈如下:

Spring IoC 源码刨析_第1张图片

BeanFactory 容器继承体系:

Spring IoC 源码刨析_第2张图片

通过其接口设计,我们可以看到我们一贯使用的 ApplicationContext 除了继承 BeanFactory 的子接口,还继承了 ResourceLoader、MessageSource 等接口,因此其提供的功能也就更丰富了。
下面我们以 ClasspathXmlApplicationContext 为例,深入源码说明 IoC 容器的初始化流程。

6、Bean 生命周期关键时机点

1)LagouBean 类

public class LagouBean implements InitializingBean {

    public LagouBean(){
       System.out.println("LagouBean 构造器...");
    }

   /**
    * InitializingBean 接口实现
    */
   @Override
   public void afterPropertiesSet() throws Exception {
      System.out.println("LagouBean afterPropertiesSet...");
   }

   public void print() {
      System.out.println("print方法业务逻辑执行");
   }
}

2)BeanPostProcessor 接口实现类

public class MyBeanPostProcessor implements BeanPostProcessor {

   public MyBeanPostProcessor() {
      System.out.println("BeanPostProcessor 实现类构造函数...");
   }

   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if("lagouBean".equals(beanName)) {
         System.out.println("BeanPostProcessor 实现类 postProcessBeforeInitialization 方法被调用中......");
      }
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      if("lagouBean".equals(beanName)) {
         System.out.println("BeanPostProcessor 实现类 postProcessAfterInitialization 方法被调用中......");
      }
      return bean;
   }
}

3)BeanFactoryPostProcessor 接口实现类

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   public MyBeanFactoryPostProcessor() {
      System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
   }

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
           throws BeansException {
      System.out.println("BeanFactoryPostProcessor的实现方法调用中......");
   }
}

4)applicationContext.xml


<beans xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
        ">
    
    <bean id="lagouBean" class="com.lagou.LagouBean"/>
    <bean id="myBeanFactoryPostProcessor" class="com.lagou.MyBeanFactoryPostProcessor"/>
    <bean id="myBeanPostProcessor" class="com.lagou.MyBeanPostProcessor"/>
beans>

5)IoC 容器源码分析用例

@Test
public void testIoC() {
    ApplicationContext applicationContext = 
            new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    LagouBean lagouBean = applicationContext.getBean(LagouBean.class);
    System.out.println(lagouBean);
}

6)分析调用情况

通过在关键时机节点打断点,观察调用栈,查看主要关键代码在哪。
我们发现 Bean 对象创建的几个关键时机点代码层级的调用都在 AbstractApplicationContext 类的 refresh 方法中。

关键点 触发代码
构造器 refresh#finishBeanFactoryInitialization(beanFactory)
InitializingBean 方法调用 refresh#finishBeanFactoryInitialization(beanFactory)
BeanFactoryPostProcessor 初始化 refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanFactoryPostProcessor 方法调用 refresh#invokeBeanFactoryPostProcessors(beanFactory)
BeanPostProcessor 初始化 refresh#registerBeanPostProcessors(beanFactory)
BeanPostProcessor 方法调用 refresh#finishBeanFactoryInitialization(beanFactory)

7、Spring IoC 容器初始化主流程

由上分析可知,Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() 方法中,我们查看 refresh 方法来俯瞰容器创建的主体流程,主体流程下的具体子流程我们后面再来讨论。

@Override
public void refresh() throws BeansException, IllegalStateException {
   // 对象锁加锁
   synchronized (this.startupShutdownMonitor) {
      /*
         Prepare this context for refreshing.
         第一步:刷新前的预处理
             表示在真正做 refresh 操作之前需要准备做的事情:
             设置 Spring 容器的启动时间,
            开启活跃状态,撤销关闭状态
            验证环境信息里一些必须存在的属性等
       */
      prepareRefresh();

      /*
         Tell the subclass to refresh the internal bean factory.
         第二步:
             获取 BeanFactory;默认实现是 DefaultListableBeanFactory
             加载 BeanDefition 并注册到 BeanDefitionRegistry
       */
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      /*
         Prepare the bean factory for use in this context.
         第三步:
             BeanFactory 的预准备工作
             (BeanFactory 进行一些设置,比如 context 的类加载器等)
       */
      prepareBeanFactory(beanFactory);

      try {
         /*
            Allows post-processing of the bean factory in context subclasses.
            第四步:BeanFactory 准备工作完成后进行的后置处理工作
          */
         postProcessBeanFactory(beanFactory);

         /*
            Invoke factory processors registered as beans in the context.
            第五步:实例化实现了 BeanFactoryPostProcessor 接口的 Bean,并调用接口方法
          */
         invokeBeanFactoryPostProcessors(beanFactory);

         /*
            Register bean processors that intercept bean creation.
            第六步:注册 BeanPostProcessor(Bean 的后置处理器),在创建 bean 的前后等执行
          */
         registerBeanPostProcessors(beanFactory);

         /*
            Initialize message source for this context.
            第七步:初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析);
          */
         initMessageSource();

         /*
            Initialize event multicaster for this context.
            第八步:初始化事件派发器
          */
         initApplicationEventMulticaster();

         /*
            Initialize other special beans in specific context subclasses.
            第九步:子类重写这个方法,在容器刷新的时候可以自定义逻辑;
                如创建 Tomcat,Jetty 等 WEB 服务器
          */
         onRefresh();

         /*
            Check for listener beans and register them.
            第十步:注册应用的监听器。就是注册实现了 ApplicationListener 接口的监听器 bean
          */
         registerListeners();

         /*
            Instantiate all remaining (non-lazy-init) singletons.
            第十一步:
            初始化所有剩下的非懒加载的单例 bean
            初始化创建非懒加载方式的单例 Bean 实例(未设置属性)
            填充属性
            初始化方法调用(比如调用 afterPropertiesSet 方法、init-method 方法)
            调用 BeanPostProcessor(后置处理器)对实例 bean 进行后置处理
          */
         finishBeanFactoryInitialization(beanFactory);

         /*
            Last step: publish corresponding event.
            第十二步:
            完成 context 的刷新。主要是调用 LifecycleProcessor 的 onRefresh() 方法,
            并且发布事件(ContextRefreshedEvent)
          */
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + ex);
         }

         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // Propagate exception to caller.
         throw ex;
      }

      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

二、BeanFactory 创建流程

1、获取 BeanFactory 子流程

过程比较简单,直接上时序图:

Spring IoC 源码刨析_第3张图片

2、BeanDefinition 加载解析及注册子流程

1)该子流程涉及到如下几个关键步骤:

Resource 定位:指对 BeanDefinition 的资源定位过程。通俗讲就是找到定义 Javabean 信息的 XML 文件,并将其封装成 Resource 对象。
BeanDefinition 载入:把用户定义好的 Javabean 表示为 IoC 容器内部的数据结构,这个容器内部的数据结构就是 BeanDefinition。
注册 BeanDefinition 到 IoC 容器

2)过程分析

Step 1:子流程入口地址
AbstractRefreshableApplicationContext#refreshBeanFactory

@Override
protected final void refreshBeanFactory() throws BeansException {
   // 判断是否已有 bean factory
   if (hasBeanFactory()) {
      // 销毁 beans
      destroyBeans();
      // 关闭 bean factory
      closeBeanFactory();
   }
   try {
      // 实例化 DefaultListableBeanFactory
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      // 设置序列化 id
      beanFactory.setSerializationId(getId());
      // 自定义 bean 工厂的一些属性(是否覆盖、是否允许循环依赖)
      customizeBeanFactory(beanFactory);
      // 加载应用中的 BeanDefinitions
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         // 赋值当前 bean facotry
         this.beanFactory = beanFactory;
      }
   } catch (IOException ex) {
      throw new ApplicationContextException(
          "I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

其上第 18 行调用 loadBeanDefinitions 正是入口所在。

Step 2:依次调用多个类的 loadBeanDefinitions 方法
AbstractXmlApplicationContext -> AbstractBeanDefinitionReader -> XmlBeanDefinitionReader -> 最后到达的 XmlBeanDefinitionReader#doLoadBeanDefinitions

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {

   try {
      // 读取 xml 信息,将 xml 中信息保存到 Document 对象
      Document doc = doLoadDocument(inputSource, resource);
      // 解析 document 对象,封装 BeanDefinition 对象并进行注册
      int count = registerBeanDefinitions(doc, resource);
      if (logger.isDebugEnabled()) {
         logger.debug("Loaded " + count + " bean definitions from " + resource);
      }
      return count;
   }
   catch (Throwable ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            "Unexpected exception parsing XML document from " + resource, ex);
   }
}

Step 3:我们重点观察 XmlBeanDefinitionReader 类的 registerBeanDefinitions 方法。

public int registerBeanDefinitions(Document doc, Resource resource) 
        throws BeanDefinitionStoreException {
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   // 获取已有 BeanDefinition 的数量
   int countBefore = getRegistry().getBeanDefinitionCount();
   // 注册 BeanDefinition
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   // 返回新注册的 BeanDefinition 数量
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

此处我们关注两个地方:

  1. createRederContext 方法。
  2. DefaultBeanDefinitionDocumentReader 类的
    registerBeanDefinitions 方法,

a. 先进入 createRederContext 方法看看:

XmlBeanDefinitionReader#createRederContext

public XmlReaderContext createReaderContext(Resource resource) {
   return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
         this.sourceExtractor, this, getNamespaceHandlerResolver());
}

XmlBeanDefinitionReader#getNamespaceHandlerResolver

public NamespaceHandlerResolver getNamespaceHandlerResolver() {
   if (this.namespaceHandlerResolver == null) {
      this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
   }
   return this.namespaceHandlerResolver;
}

XmlBeanDefinitionReader#createDefaultNamespaceHandlerResolver

protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
   ClassLoader cl = (getResourceLoader() != null ? 
           getResourceLoader().getClassLoader() : getBeanClassLoader());
   return new DefaultNamespaceHandlerResolver(cl);
}

我们可以看到,此处 Spring 首先完成了 NamespaceHandlerResolver 的初始化。

b. 再进入 registerBeanDefinitions 方法中追踪:

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   doRegisterBeanDefinitions(doc.getDocumentElement());
}

DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

protected void doRegisterBeanDefinitions(Element root) {
   BeanDefinitionParserDelegate parent = this.delegate;
   this.delegate = createDelegate(getReaderContext(), root, parent);
   if (this.delegate.isDefaultNamespace(root)) {
      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
      if (StringUtils.hasText(profileSpec)) {
         String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
               profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
         if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
            if (logger.isDebugEnabled()) {
               logger.debug("Skipped XML bean definition file due to specified profiles [" 
                       + profileSpec + "] not matching: " 
                       + getReaderContext().getResource());
            }
            return;
         }
      }
   }
   preProcessXml(root);
   // 重点是 parseBeanDefinitions 方法
   // preProcessXml 和 postProcessXml 都是钩子方法
   parseBeanDefinitions(root, this.delegate);
   postProcessXml(root);

   this.delegate = parent;
}

DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
               // 解析默认标签元素
               parseDefaultElement(ele, delegate);
            } else {
               // 解析自定义标签元素
               delegate.parseCustomElement(ele);
            }
         }
      }
   } else {
      delegate.parseCustomElement(root);
   }
}

DefaultBeanDefinitionDocumentReader#parseDefaultElement

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   // import 元素处理
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
   // alias 元素处理
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
   }
   // bean 元素处理
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      // 解析 bean 元素
      processBeanDefinition(ele, delegate);
   }
   // 嵌套 beans 处理
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

DefaultBeanDefinitionDocumentReader#processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   // 解析 bean 元素为 BeanDefinition,但是此时使用 BeanDefinitionHolder 
   // 又包装成了 BeanDefinitionHolder 对象
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      /*
          
             
             
             
          
          如果有自定义标签,则处理自定义标签
       */
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // 完成 BeanDefinition 的注册
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, 
                 getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error("Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

至此,注册流程结束,我们发现,所谓的注册就是把封装的 XML 中定义的 Bean 信息封装为 BeanDefinition 对象之后放入一个 Map 中,BeanFactory 是以 Map 的结构组织这些 BeanDefinition 的。

DefaultListableBeanFactory 中相关的代码:

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {
    // 其他代码省略,
    // Still in startup registration phase
    this.beanDefinitionMap.put(beanName, beanDefinition);
    this.beanDefinitionNames.add(beanName);
    removeManualSingletonName(beanName);
}

3)时序图

Spring IoC 源码刨析_第4张图片

三、Bean 创建流程

1、起始点

通过最开始的关键时机点分析,我们知道 Bean 创建子流程入口在 AbstractApplicationContext#refresh() 方法的 finishBeanFactoryInitialization(beanFactory) 处。

/*
   Instantiate all remaining (non-lazy-init) singletons.
   初始化所有剩下的非懒加载的单例bean
   初始化创建非懒加载方式的单例Bean实例(未设置属性)
       填充属性
       初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)
       调用 BeanPostProcessor(后置处理器)对实例bean进行后置处理
 */
finishBeanFactoryInitialization(beanFactory);

2、过程

进入 AbstractApplicationContext#finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> 
              getEnvironment().resolvePlaceholders(strVal));
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering 
   // their transformers early.
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, 
           false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();

   // Instantiate all remaining (non-lazy-init) singletons.
   // 实例化所有立即加载的单例bean
   beanFactory.preInstantiateSingletons();
}

进入 DefaultListableBeanFactory#preInstantiateSingletons

@Override
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register 
   // new bean definitions.
   // While this may not be part of the regular factory bootstrap,
   // it does otherwise work fine.
   // 所有 bean 的名字
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   // 触发所有非延迟加载单例 bean 的初始化,主要步骤为 getBean
   for (String beanName : beanNames) {
      // 合并父 BeanDefinition 对象
      // map.get(beanName)
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 判断是否是懒加载单例 bean,如果是单例的并且不是懒加载的则在容器创建时初始化
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // 判断是否是 FactoryBean
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            // 如果是 FactoryBean 则加 &
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof 
                       SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                              ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            // 实例化当前 bean
            /*
             如果是普通 bean 则进行初始化并依赖注入,此 getBean(beanName) 接下来触发的逻辑
             和懒加载时 context.getBean("beanName") 所触发的逻辑是一样的
             */
            getBean(beanName);
         }
      }
   }

   // 代码略...
}

AbstractBeanFactory#getBean

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

AbstractBeanFactory#doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

   // 解析 beanName 如果以&开头去掉&开头,如果是别名获取到真正的名字
   final String beanName = transformedBeanName(name);
   Object bean;

   // 单纯理解尝试从缓存中获取 bean
   Object sharedInstance = getSingleton(beanName);
   // 如果已经存在则返回
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         } else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 针对 FactoryBean 的处理
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   } else {
       
      // 如果是 prototype 类型且开启允许循环依赖,则抛出异常
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      // 检查父工厂中是否存在该对象
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                  nameToLookup, requiredType, args, typeCheckOnly);
         } else if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         } else if (requiredType != null) {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         } else {
            return (T) parentBeanFactory.getBean(nameToLookup);
         }
      }

      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         // 合并父子bean 属性
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // Guarantee initialization of beans that the current bean depends on.
         // 处理dependsOn配置
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dep : dependsOn) {
               if (isDependent(beanName, dep)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName 
                        + "' and '" + dep + "'");
               }
               registerDependentBean(dep, beanName);
               try {
                  getBean(dep);
               } catch (NoSuchBeanDefinitionException ex) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
               }
            }
         }

         // 创建单例bean
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, () -> {
               try {
                  // 创建 bean
                  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);
            
         } else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               // 创建原型 bean 之前添加标记
               beforePrototypeCreation(beanName);
               // 创建原型 bean
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               // 创建原型 bean 之后删除标记
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         } else {
             
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" 
                       + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName, () -> {
                  beforePrototypeCreation(beanName);
                  try {
                     return createBean(beanName, mbd, args);
                  }
                  finally {
                     afterPrototypeCreation(beanName);
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            } catch (IllegalStateException ex) {
               throw new BeanCreationException(beanName,
                     "Scope '" + scopeName + "' is not active for the current thread; consider " +
                     "defining a scoped proxy for this bean if you intend to refer to" 
                     + " it from a singleton", ex);
            }
         }
      } catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // 代码略...
   return (T) bean;
}

AbstractAutowireCapableBeanFactory#createBean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   if (logger.isTraceEnabled()) {
      logger.trace("Creating instance of bean '" + beanName + "'");
   }
   // 拿到 Bd
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point, and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   // 获得类信息
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   } catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {
         return bean;
      }
   } catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
            "BeanPostProcessor before instantiation of bean failed", ex);
   }

   try {
      // 进入,真真正正创建bean
      Object beanInstance = doCreateBean(beanName, mbdToUse, args);
      if (logger.isTraceEnabled()) {
         logger.trace("Finished creating instance of bean '" + beanName + "'");
      }
      return beanInstance;
   } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
      // A previously detected exception with proper bean creation context already,
      // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
      throw ex;
   } catch (Throwable ex) {
      throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, 
                    "Unexpected exception during bean creation", ex);
   }
}

AbstractAutowireCapableBeanFactory#doCreateBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, 
        final @Nullable Object[] args) throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 创建 Bean 实例,仅仅调用构造方法,但是尚未设置属性
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   final Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         } catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // 初始化 bean 实例
   Object exposedObject = bean;
   try {
      // Bean属性填充
      populateBean(beanName, mbd, instanceWrapper);
      // 调用初始化方法,应用 BeanPostProcessor 后置处理器
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   } catch (Throwable ex) {
      if (ex instanceof BeanCreationException 
              && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      } else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }

   // 代码略...
   return exposedObject;
}

四、 lazy-init 延迟加载机制原理

1、分析

  • 普通 Bean 的初始化是在容器启动初始化阶段执行的,而被 lazy-init=true 修饰的 bean 则是在从容器里第一次进行 context.getBean() 时进行触发。
  • Spring 启动的时候会把所有 bean 信息(包括 XML 和注解)解析转化成 Spring 能够识别的 BeanDefinition 并存到 Hashmap 里供下面的初始化时用,然后对每个 BeanDefinition 进行处理,
  • 如果是懒加载的则在容器初始化阶段不处理,其他的则在容器初始化阶段进行初始化并依赖注入。

重看代码 DefaultListableBeanFactory#preInstantiateSingletons

@Override
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register 
   // new bean definitions.
   // While this may not be part of the regular factory bootstrap,
   // it does otherwise work fine.
   // 所有 bean 的名字
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
   // 触发所有非延迟加载单例 bean 的初始化,主要步骤为 getBean
   for (String beanName : beanNames) {
      // 合并父 BeanDefinition 对象
      // map.get(beanName)
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      // 判断是否是懒加载单例 bean,如果是单例的并且不是懒加载的则在容器创建时初始化
      // 懒加载不会进行以下代码
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // 判断是否是 FactoryBean
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            // 如果是 FactoryBean 则加 &
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof 
                       SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                              ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            // 实例化当前 bean
            /*
             如果是普通 bean 则进行初始化并依赖注入,此 getBean(beanName) 接下来触发的逻辑
             和懒加载时 context.getBean("beanName") 所触发的逻辑是一样的
             */
            getBean(beanName);
         }
      }
   }

   // 代码略...
}

2、总结

  • 对于被修饰为 lazy-init 的 bean, Spring 容器初始化阶段不会进行 init 并且依赖注入,当第一次进行 getBean 时候才进行初始化并依赖注入。
  • 对于非懒加载的 bean,getBean 的时候会从缓存里头获取,因为容器初始化阶段 Bean 已经初始化完成并缓存了起来。

文章内容输出来源:拉勾教育Java高薪训练营;

你可能感兴趣的:(温故日志,#,spring,温故日志,spring,java,ioc,源码)