likes
comments
collection
share

Spring 容器源码分析(东北话版本)

作者站长头像
站长
· 阅读数 17

最近手写了Spring框架,嗯,,怎么说呢,写完的第一感受吧,辞职回家,这个行业可能真的不适合我,被Spring当中的各种继承各种设计模式搞蒙,感觉这个东西你没有个几年经验你不仔细看个几次,你是没有办法领悟Spring的精髓的(想想也是这么牛逼的一个框架,要是让你一俩遍看明白了,那不白活了吗),但是怎么说呢,通过我的不断努力,也是跟着写完了。这两天又看了很多技术大佬对于Spring源码级的讲解,感觉已经有点入门了,趁着这个机会赶紧赶紧赶紧总结一下。省的过两天忘了。

首先我先声明一下,本文只是个人对于Spring的一些理解,为了方便大家以及我个人理解我尽量用大白话来讲,同时也真的希望各位大佬看这篇文章的时候能够提出小弟的不足之处。废话不多说!!开始肝!! 正式开始之前,首先介绍Spring当中几个重要的基础概念,为了下文源码分析的时候做点铺垫。

基础概念 

这里只是个人的一点总结,主要是分了下文源码分析做铺垫,有兴趣的同学可以在深入一些

BeanFactory和FactoryBean

首先,Spring里面的核心功能是IOC容器,所谓IOC容器本身就是一个Bean的容器或者是一个Bean的工厂。而BeanFactory是所有Spring Bean容器的顶级接口,它为Spring的容器定义了一条获取Bean实例的规范,例如getBean方法等。BeanFactory在产生Bean的同时,还提供了解决Bean之间的依赖注入的能力。

而FactoryBean是一个工厂Bean,它也是一个接口,主要功能是动态生成某一个类型的Bean实例,也就是说我们可以自定义一个Bean并且加载到IOC容器里面 。其中FactoryBean里面有一个重要方法叫getObject()。 这个方法就是用来实现构建Bean的过程。MyBatis 就是实现了一个 MapperFactoryBean 类,在 getObject 方法中提供 SqlSession 对执行 CRUD 方法的操作 。

BeanDefinition

BeanDefinition表示Bean定义,Spring根据BeanDefinition来创建Bean对象。Spring容器启动过程中会从xml文件中加载Bean的相关信息,存储中BeanDefinition中,然后在创建Bean对象。

BeanDefintion中有一些重要的属性

  • beanClass,beanClass表示bean的类型,比如UserService.class。Spring在创建Bean的过程中会根据此属性来实例化得到对象。
  • Scope表示一个bean的作用域,比如scope等于singleton,则该Bean就是一个单例Bean。
  • isLazy表示一个bean是不是需要懒加载,
  • dependoOn表示一个bean在创建之前所依赖的其他bean,在一个bean创建之前,它做依赖的这些bean得全部创建好,
  • initMethodName表示一个bean的初始化方法,spring在初始化时会调用这个方法,初始化逻辑由程序员自己控制。

我们在程序中使用@Bean、@Component使用的注解标注的对象Spring容器在启动过程中都会首先加载成BeanDefinition。

BeanFactoryPostProcessor

是由Spring框架组件提供的容器扩展机制,允许在Bean对象注册后但未实例化之前,对Bean的定义信息BeanDefinition执行修改操作。void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;

BeanPostProcessor

也是 Spring 提供的扩展机制,不过 BeanPostProcessor 是在 Bean 对象实例化之后修改 Bean 对象。

postProcessBeforeInitialization - Bean 对象执行初始化方法之前,执行此方法

postProcessAfterInitialization -  Bean 对象执行初始化方法之后,执行此方法

Aware

Aware接口在Spring框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象,也就是通过这个接口,向具体的实现类中提供容器服务,Aware只是一个标记接口,里面并没有什么方法,常见的有BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware。这些接口都继承了aware。举个例子假如我们的类实现了BeanFactoryAware接口,通过setBeanFactory方法就可以获得当前容器的BeanFactory的信息了

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口是Spring框架中的一个扩展点,用于在Bean实例化过程中的不同阶段进行自定义处理操作。它定义了一组方法,可以在Bean实例化、属性赋值、初始化等过程中对Bean进行自定义的处理。

InstantiationAwareBeanPostProcessor接口的方法执行时机如下:

  1. postProcessBeforeInstantiation:在Bean实例化之前调用。可以通过该方法返回一个自定义的Bean实例,从而绕过正常的实例化过程。
  2. postProcessAfterInstantiation:在Bean实例化之后、属性赋值之前调用。可以在这个方法中对已实例化的Bean进行进一步的自定义处理。
  3. postProcessPropertyValues:在Bean属性赋值之后调用。可以在这个方法中对已赋值的属性进行修改或校验。

源码分析

首先我个人认为Spring启动主要分为俩部分初始化Spring容器获取Bean对象(当然啦Spring最核心的肯定是IOC和AOP),但是这俩部分不是分开的,并不是说Spring容器初始化完了以后才能获取Bean对象。Spring容器在初始化过程中,由于一些必要的Bean对象,以及一些依赖。一些Bean对象也会随之进行初始化。这里为了更好的理解就分开来讲解了。

容器初始化

众所周知Spring容器启动最核心的方法就是AbstractApplicationContext抽象类里面的refresh()方法,简单点来说这是一个模版方法,用来控制Spring容器的整体流程,里面的各个方法再由相应的子类来实现。本文也是直接从这个方法开始(正常来讲应该从ClassPathXmlApplicationContext这个类开始,但这个类主要是加载Spring文件的这里就不多阐述了)。废话不多说上源码。

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 1.准备工作,记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
      prepareRefresh();

      // 2.这块比较重要一些,总结一下就是将配置文件中的信息解析出来生成一个个BeanDefintion
      // 并存入BeanDefintionMap中。
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 3.设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         //  4.为容器的某些子类指定特殊的BeanPost事件处理器
         postProcessBeanFactory(beanFactory);

         //  5.调用所有注册的BeanFactoryPostProcessor的Bean
         invokeBeanFactoryPostProcessors(beanFactory);

         //  6.注册 BeanPostProcessor 的实现类,
         registerBeanPostProcessors(beanFactory);

         // 7.初始化当前 ApplicationContext 的 MessageSource,
         initMessageSource();

         // 8.初始化当前 ApplicationContext 的事件广播器
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 9.调用子类的某些特殊Bean初始化方法
         onRefresh();

         // Check for listener beans and register them.
         // 10.注册事件监听器,监听器需要实现 ApplicationListener 接口。
         registerListeners();

         // 11.初始化所有的 singleton beans
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 12.初始化容器的生命周期事件处理器,并发布容器的生命周期事件
         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.
         // 14.销毁以创建的单态Bean
         destroyBeans();
         // 15.取消refresh操作,重置容器的同步标识.
         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();
      }
   }
}

整个refresh()方法的步骤如上所示,并且每个步骤已经填写了一些主要注释,refresh()方法主要就是为Ioc容器Bean的生命周期管理提供条件,Spring IOC容器载入Bean定义资源文件,进行加载,启动IOC容器。refresh()方法的作用就是在创建IOC容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证refresh()之后使用的是新建立起来的IoC容器。refresh的作用类似于对IoC容器的重启,在新建立好的容器中对容器进行初始化,对Bean定义资源进行载入。

接下来就将几个主要步骤分析一下。

首先我们看到方法刚一进来就加了一个synchronized锁,这里就是保证同一个时刻只能有一个Spring容器启动。(仔细想一下如果没加锁的话,你这个refresh容器启动一半,又来一个方法启动,那不就乱套了嘛)。

obtainFreshBeanFactory()方法解析

这块是全文最重要的部分之一,这里会初始化BeanFactroy容器,解析配置文件,加载BeanDefintion到容器中。

> AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
   refreshBeanFactory();
   // 返回刚刚创建的 BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

> AbstractRefreshableApplicationContext.java
@Override
protected final void refreshBeanFactory() throws BeansException {
   // 这里就是判断一下如果ApplicationContext已经加载了BeanFactory了,销毁所有bean,关闭BeanFactory
   // 这里判断的是当前ApplicatonContext是否有BeanFactory,(应用中BeanFactory本来是可以有多个)
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      // 初始化一个 DefaultListableBeanFactory 
      // 这个BeanFactory将用于Spring容器中整个过程,用于存储BeanDefintion
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      // 用于 BeanFactory 的序列化
      beanFactory.setSerializationId(getId());
      // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
      customizeBeanFactory(beanFactory);
      // 将配置文件中的资源解析成一个个BeanDefintion 存入到BeanFactory中
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
> AbstractRefreshableApplicationContext.java
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding != null) {
      // 是否允许Bean定义覆盖
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      // 是否允许Bean间的循环依赖
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

可能有的小伙伴对于是否允许Bean覆盖这个问题有点懵,但其实这个问题我们初学Spring的时候就遇到过了,就是在配置文件中定义 bean 时使用了相同的 id 或 name,默认情况下,allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。

至于是否允许Bean间的循环依赖问题老生常谈了,Spring是允许循环依赖的这里下文会详细介绍。

refreshBeanFactory()方法中还有一个重要的方法就是loadBeanDefinitions(beanFactory);这里就是解析配置文件,将配置文件中的资源解析成一个个BeanDefinition 存入到BeanFactory中。这块也用到了策略模式,根据不同的配置文件选择不同的策略进行解析,这里本文就不重要讲了,有兴趣的同学可以深入研究一下。

到这里第二步ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();执行完,我们就可以说Bean容器实例化完成了,这个时候容器里面存放的就是所有BeanDefinition。

准备 Bean 容器: prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   // 设置 BeanFactory 的类加载器,为ApplicationContext的类加载器
   beanFactory.setBeanClassLoader(getClassLoader());
   // 设置 BeanExpressionResolver
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   // 添加一个 BeanPostProcessor。实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
   // 它不仅仅回调 ApplicationContextAware,
   // 还会负责回调 EnvironmentAware、ResourceLoaderAware 等
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
   // 下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
   // Spring 会通过其他方式来处理这些依赖。
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

   // 为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个,会注入这边相应的值,
   // MessageSource registered (and found for autowiring) as a bean.
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   // 这里涉及到特殊的 bean,名为:loadTimeWeaver。是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样,这里就不详细解释了
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   //  这里就是Spring帮我们默认注册一些游泳的bean

   // 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   // 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   // 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
      beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}

从refresh()放的的4到10步,主要就是注册各种事件和各种监听器,本文就不一一阐述了,但这里有个点需要注意的就是第五步invokeBeanFactoryPostProcessors(beanFactory);调用所有实现的BeanFactoryPostProcessor接口的Bean,这与最开始我们介绍的基础知识里相呼应上了,当一个类(也就是一个Bean)如果实现了BeanFactoryPostProcessor接口就需要实现postProcessBeanFactory()方法,这里就会调用这个方法,也就是上文我们描述的允许在Bean对象注册后但未实例化之前,对Bean的定义信息BeanDefinition执行修改操作。注意这里是调用,而不是注册。

走到这里其实我们就可以认为Spring容器已经启动完成了,但是现在Spring容器中除了一些必须的Bean以外,如果我们自定义的Bean没有被调用的话,还是以BeanDefinition存在Spring容器中。

获取Bean

初始化所有的 singleton beans--finishBeanFactoryInitialization(beanFactory);

我们的重点就是finishBeanFactoryInitialization(beanFactory),这里就是负责初始化所有的singleton beans。简单点来说就是将Spring中所有单例、非懒加载的bean。从BeanDefintion解析出来,初始化完成。成为一个真正的Bean。finishBeanFactoryInitialization方法中主要就是一些判断,例如判断如果是单例、非懒加载的Bean就是开始初始化,如果是property(这里简称非单例)就跳过,并且个如果是FactoryBean,就在Bean的名字起那面加一个&符号(这里主要就是将FactoryBean和普通Bean区分开)。最核心的方法就是doGetBean()这个方法就是创建Bean的最终方法。

doGetBean源码解析

protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException {
   // 处理beanName 主要处理前面FactoryBean设置的'&',和 别名问题
   // 因为我们可以Bean设置其他的名称,这块主要是处理Bean名称的问题
   final String beanName = transformedBeanName(name);
   // 这个是返回值
   Object bean;

   // 检查是否已经创建过了,单例bean只需要创建一次即可
   Object sharedInstance = getSingleton(beanName);
   // 这里判断一下,如果sharedInstance不等于空的话就代表Bean已经创建好了,则不需要重复创建了
   // args传惨其实就是null,如果不是null的话 那么意味着调用方不是希望获取 Bean,而是创建 Bean
   if (sharedInstance != null && args == null) {
      if (logger.isDebugEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      // 如果是普通bean的话 不做任何处理,直接将sharedInstance复制给Bean
      // 如果是FactoryBean 返回它创建的实例 简单来说就是调用了FactoryBean的getObject方法;
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // 检查一下这个BeanDefinition在容器中是否存在
      BeanFactory parentBeanFactory = getParentBeanFactory();
      if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
         // 如果当前容器不存在这个 BeanDefinition,试试父容器中有没有
         String nameToLookup = originalBeanName(name);
         if (args != null) {
            // 返回父容器的查询结果
            return (T) parentBeanFactory.getBean(nameToLookup, args);
         }
         else {
            // No args -> delegate to standard getBean method.
            return parentBeanFactory.getBean(nameToLookup, requiredType);
         }
      }

      if (!typeCheckOnly) {
         // typeCheckOnly 为 false,将当前 beanName 放入一个 alreadyCreated 的 Set 集合中。
         markBeanAsCreated(beanName);
      }
      // 正式开始创建Bean,对于单例Bean来说,容器中还没创建过此Bean
      // 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 先初始化依赖的所有Bean
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dependsOnBean : dependsOn) {
               if (isDependent(beanName, dependsOnBean)) {
                  throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
               }
               // 注册一下依赖关系
               registerDependentBean(dependsOnBean, beanName);
               // 先初始化被依赖项
               getBean(dependsOnBean);
            }
         }

         // 如果是 singleton scope 的,创建 singleton 的实例
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  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);
         }
         // 如果是 prototype scope 的,创建 prototype 的实例
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               // 执行创建 Bean
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }
         // 如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理
         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, new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     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;
      }
   }

   // 最后,检查一下类型对不对,不对的话就抛异常,对的话就返回了
   if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
      try {
         return getTypeConverter().convertIfNecessary(bean, requiredType);
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type [" +
                  ClassUtils.getQualifiedName(requiredType) + "]", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

简单总结一下,doGetBean方法首先主要做的就是处理Bean名称,然后判断一下这个单例Bean有没有创建好,如果已经创建好了就不需要重复创建了。但是会在getObjectForBeanInstance方法中判断一下是不是FactoryBean,如果不是的话直接返回。如果是的话直接执行getObject方法执行自定义创建Bean逻辑。如果为空就代表这个bean还没有创建。就获取一下BeanDefinition。然后判断一下Bean的类型。单例还是多例。然后进入真正创建Bean的逻辑。--createBean()。这里我们直接进入createBean方法的重头戏doCreateBean,创建bean。

doCreateBean源码解析

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
   // 封装被创建的Bean对象
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      // 单态模式的Bean,先从容器中缓存中获取同名Bean--注意这里获取的是FactoryBean
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      //  说明不是 FactoryBean,这里实例化 Bean
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
   Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

   // Allow post-processors to modify the merged bean definition.
   // 这块主要处理Bean合并操作(这块太难了,还没搞懂,先跳过)
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   // 下面这块代码是为了解决循环依赖的问题
   // Spring通过三级缓存和bean的提前暴露解决循环依赖问题,稍后详细讲
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      // 解决循环依赖
      //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
      addSingletonFactory(beanName, new ObjectFactory<Object>() {
         @Override
         public Object getObject() throws BeansException {
            return getEarlyBeanReference(beanName, mbd, bean);
         }
      });
   }

   // Initialize the bean instance.
   //Bean对象的初始化,依赖注入在此触发
   //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
   Object exposedObject = bean;
   try {
      // 填充属性
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) {
         // 还记得 init-method 吗?还有 InitializingBean 接口?还有 BeanPostProcessor 接口?
         // 这里就是处理 bean 初始化完成后的各种回调
         // 初始化Bean对象
         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);
      }
   }

   if (earlySingletonExposure) {
      //获取指定名称的已注册的单态模式Bean对象
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         //根据名称获取的以注册的Bean和正在实例化的Bean是同一个
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         }
         //当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            //获取当前Bean所依赖的其他Bean
            for (String dependentBean : dependentBeans) {
               //对依赖Bean进行类型检查  
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   //注册完成依赖注入的Bean  
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

这个方法有点长,但是其实总结起来就三点,实例化Bean对象,填充属性,初始化。这三点是这个方法的精髓,也是Spring容器获取Bean对象的精髓,同时解决循环依赖,以及AOP也都是在这里面处理的。接下来让我们逐步分析一下

> AbstractAutowireCapableBeanFactory.java 
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
   // 确保已经加载了此 class
   Class<?> beanClass = resolveBeanClass(mbd, beanName);
   // 校验一下这个类的访问权限
   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }
   // 采用工厂方法实例化,注意,不是 FactoryBean
   if (mbd.getFactoryMethodName() != null)  {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   // 如果不是第一次创建,比如第二次创建 prototype bean。
   // 这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
   boolean resolved = false;
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   if (resolved) {
      if (autowireNecessary) {
         //配置了自动装配属性,使用容器的自动装配实例化
         //容器的自动装配是根据参数类型匹配Bean的构造方法
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         //使用默认的无参构造方法实例化
         return instantiateBean(beanName, mbd);
      }
   }

   // Need to determine the constructor...
   // 判断是否采用有参构造函数
   //使用Bean的构造方法进行实例化
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // 如果指定了显式构造函数参数值,将所有剩余参数与 Bean 工厂中的 bean 匹配 判断使用哪个构造函数
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // No special handling: simply use no-arg constructor.
   // 调用无参构造函数
   return instantiateBean(beanName, mbd);
}

这个方法就是执行bean的实例化操作,Java实例化一个类三个步骤:1.分配内存空间2.初始化对象,调用构造函数3.返回对象引用。这里也是。主要就是判断使用哪种方式进行实例化,然后将实例化完成的对象返回。这块有个重要的点就是instantiateUsingFactoryMethod这个方法就是我们学习Spring的时候,有几种实例化Bean对象的方式,构造函数实例化、静态工厂方法实例化、实例工厂方法实例化。其中实例工厂方法实例化就是在这块单独处理的。至此一个Bean对象的实例化已经完成。

接下来有个步骤我个人认为特别重要,同时也就是Spring解决循环依赖的精髓所在,上面注释上也标注了,Spring通过三级缓存和Bean的提前暴露解决循环依赖问题。这里最主要的就是addSingletonFactory方法和匿名内部类returen中的getEarlyBeanReference方法。首先我们先知道Spring三级缓存都是啥,每一级缓存存放的都是什么内容。首先Spring的三级缓存就是三个Map集合。

循环依赖的核心功能实现主要包括 DefaultSingletonBeanRegistry 提供三级缓存:singletonObjects、earlySingletonObjects、singletonFactories,分别存放成品对象、半成品对象和工厂对象。同时包装三个缓存提供方法:getSingleton、registerSingleton、addSingletonFactory,这样使用方就可以分别在不同时间段存放和获取对应的对象了。

> AbstractAutowireCapableBeanFactory.java
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
   if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            if (exposedObject == null) {
               return exposedObject;
            }
         }
      }
   }
   return exposedObject;
}

这个方法我们就是遍历当前这个bean实现的所有的BeanPostProcessor。如果实现了SmartInstantiationAwareBeanPostProcessor接口,则返回SmartInstantiationAwareBeanPostProcessor接口中getEarlyBeanReference方法自定义的Bean实例。否则不做任何处理。直接返回。

> DefaultSingletonBeanRegistry.java
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized(this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }

    }
}

addSingletonFactory就是判断一下当前这个bean实例是否在singletonObjects一级缓存中,如果不在的话就将其加入到三级缓存中,并将其从二级缓存中删除(这块相当于一个预防,正常情况到这步二级缓存都是没有的)。并且加入到registeredSingletons集合中,表示当前这个Bean对象正在创建中

至此我们还是重复上面那句话Spring例如三级缓存和提前暴露解决循环依赖问题,但是这仅仅是解决循环依赖的第一步。同时我个人认为也是最精髓的一步。到这里为止,当前这个Bean已经实例化完成,并且已经过标记成了正在创建的状态(因为加入到了registeredSingletons集合中,这个集合保存的就是所有正在创建中的Bean)。

填充属性--populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
   // bean 实例的所有属性都在这里了
   PropertyValues pvs = mbd.getPropertyValues();

   if (bw == null) {
      if (!pvs.isEmpty()) {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
         // Skip property population phase for null instance.
         return;
      }
   }

   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   boolean continueWithPropertyPopulation = true;
   // bean 实例化完成(通过工厂方法或构造方法),但是还没开始属性设值,
   // InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改,
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   if (!continueWithPropertyPopulation) {
      return;
   }
   //依赖注入开始,首先处理autowire自动装配的注入
   if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

      // Add property values based on autowire by name if applicable.
      // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
      // 对autowire自动装配的处理,根据Bean名称自动装配注入
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
         autowireByName(beanName, mbd, bw, newPvs);
      }

      //根据Bean类型自动装配注入
      if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
         autowireByType(beanName, mbd, bw, newPvs);
      }

      pvs = newPvs;
   }
   // 检查容器是否持有用于处理单态模式Bean关闭时的后置处理器
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   //Bean实例对象没有依赖,即没有继承基类
   boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
   if (hasInstAwareBpps || needsDepCheck) {
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
               // 这里有个非常有用的 BeanPostProcessor 进到这里: AutowiredAnnotationBeanPostProcessor
               // 对采用 @Autowired、@Value 注解的依赖进行设值
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
         //为要设置的属性进行依赖检查
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }
   // 设置 bean 实例的属性值
   applyPropertyValues(beanName, mbd, bw, pvs);
}

populateBean方法就是填充属性,首先先获取Bean实例中所有的属性,这里面有个地方要注意一下就是在获取所有属性之后会判断一下该bean有没有实现InstantiationAwareBeanPostProcessor接口。如果实现了该接口就会调用postProcessAfterInstantiation方法(和上文最开始我们介绍的基础知识呼应上了吧)。然后就是解析autowire属性。如果当前bean对象有被@Autowire注解注入的类,会在这里进行注入。这个被标注的类没有被实例化就会重新进行getBean方法的操作。最后applyPropertyValues方法就是获取配置文件中我们自定义的属性的值进行填充(这块就不详细介绍了,里面包括了很多例如类型转换等)。

initializeBean

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
         @Override
         public Object run() {
            invokeAwareMethods(beanName, bean);
            return null;
         }
      }, getAccessControlContext());
   }
   else {
      // 如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      // BeanPostProcessor 的 postProcessBeforeInitialization 回调
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      // 处理 bean 中定义的 init-method,
      // 或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
      invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
      throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   }

   if (mbd == null || !mbd.isSynthetic()) {
      // BeanPostProcessor 的 postProcessAfterInitialization 回调
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
}

initializeBean方法主要就是执行各种方法的回调,包括实现了BeanPostProcessor的接口postProcessBeforeInitialization和postProcessAfterInitialization方法的回调操作。其中invokeInitMethods方法也比较重要这块就是执行我们类中自定的init-method方法和如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法。这个方法源码比较简单,有兴趣的同学可以看一下。

同时这里有一个很重要的点。Spring的AOP就是在applyBeanPostProcessorsAfterInitialization方法中BeanPostProcessor 的 postProcessAfterInitialization 回调实现的。首先我们知道Spring实现AOP最核心的类就是DefaultAdvisorAutoProxyCreator,它能实现自动将所有的advisor生效。首先让我们看一下类的继承结构。

Spring 容器源码分析(东北话版本) 从DefaultAdvisorAutoProxyCreator类的继承结构上我们可以很直接的看出它的最顶层接口就是BeanPostProcessor。所以也就验证了上文SpringAOP代理生成的时机。DefaultAdvisorAutoProxyCreator 的继承结构中,postProcessAfterInitialization() 方法在其父类 AbstractAutoProxyCreator 这一层被覆写了:

    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

如果符合条件wrapIfNecessary这个方法将返回代理类

> AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   // 返回匹配当前 bean 的所有的 advisor、advice、interceptor
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 为这个类创建代理
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}  

这块最主要的方法就是createProxy创建代理对象,这块源码就不带大家继续往下看了,有兴趣的可以自己跟源码看一下,总结一下就是如果被代理的目标类实现了一个或多个自定义的接口,那么就会使用 JDK 动态代理,如果没有实现任何接口,会使用 CGLIB 实现代理,如果设置了 proxy-target-class="true",那么都会使用 CGLIB。

至此一个完整的Bean对象已经创建成功了。Spring在事件监听器回调中将这个Bean对象通过registerSingleton存入到singletonObjects一级缓存中。

紧接着再讲一下Spring循环依赖的问题。首先什么是循环依赖,简单举个例子吧

@Component
public class A {

    private B b;

    public void setB(B b) {
        this.b = b;
    }
}
@Component
public class B {

    private A a;

    public void setA(A a) {
        this.a = a;
    }
}

Spring循环依赖概述

这里就简单分析一下Spring循环依赖的问题。首先Spring尝试通过ApplicationContext.getBean()方法获取A对象的实例,由于Spring容器中还没有A对象实例,因而其会创建一个A对象,通过上面讲解我们知道,创建A对象实例时,会把这个A实例标记成正在创建的状态,Spring通过提前暴露将A实例放入到第三级缓存中。然后进行属性填充,填充时发现A属性又依赖了B,就开始创建B实例,这时候B实例也放入到了三级缓存中,紧接着B属性中又依赖A对象,然后又去创建A对象实例,但是通过上面代码描述我们知道在每个实例创建之前会调用Object sharedInstance = getSingleton(beanName);这个方法判断一下这个实例有没有创建好,让我们看一下这个方法

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        synchronized(this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }

    return singletonObject;
}

这个方法特别简单其实就是依次从Spring的一、二、三级缓存中去找是否有当前名称为beanName的Bean。如果有的话直接返回。没有的话返回NULL,走重新创建的逻辑, 目前状态就是在创建B实例的时候又去创建A了,但是在创建A实例的时候通过getSingleton方法直接返回了A实例。这个时候B就会默认A实例已经注入成功了就去走下面的创建逻辑。直到B实例创建完成,然后回去继续创建A实例。由于A实例中依赖的B实例已经创建完成,则继续走下面的创建逻辑。直到A实例创建完成。所以这也就是为什么说Spring解决循环依赖最关键的点就是提前暴露和三级缓存。(这里只是大概给大家讲一下,有兴趣的同学可以仔细研究一下。)这块还有一个点就是在getSingleton方法中我们可以看到如果是从三级缓存中获取到了Bean对象的话,会将这个Bean对象从三级缓存中删除然后存入到二级缓存中。这块也是一个扩展点。简单说一下这里个人的理解,在DefaultAdvisorAutoProxyCreator提供的切面中也需要实现接口InstantiationAwareBeanPostProcessor新增的getEarlyBeanReference,便于把依赖的切面对象也能存放到三级缓存中,处理对应的循环依赖。(同时有人也会问为什么Spring需要用三级缓存才能解决循环依赖,只有一级缓存不行吗,或者只有俩级缓存不行吗?这块大家自己可以百度下,哈哈哈哈哈哈哈)

Spring 容器源码分析(东北话版本)

至此本章节内容已经介绍完毕了。但这篇文章仅仅是一个开始,文章的bug还很多。随着每一次对Spring源码的阅读,都会有一个新的体会和总结。后续也都会更新在这边文章里。有兴趣的同学可以收藏一下本文章哦!!后续有更新也会标记出来。加深印象。

转载自:https://juejin.cn/post/7234449760337985592
评论
请登录