阿里面试官:没看过spring源码,简历上竟然敢写精通,早点回家吧!

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: springmvc,springboot,springcloud以及他们很多配套框架,比如各种stater,springsecurity等所有的基础是spring,作为spring家族的源码分析最基础的部分,这篇文章把spring给大家尽量用最简单的方法,把主要流程讲清楚。为后续的springboot,springcloud,以及其他相关框架分析打下基础。

前言

springmvc,springboot,springcloud以及他们很多配套框架,比如各种stater,springsecurity等所有的基础是spring,作为spring家族的源码分析最基础的部分,这篇文章把spring给大家尽量用最简单的方法,把主要流程讲清楚。为后续的springboot,springcloud,以及其他相关框架分析打下基础。

spring框架简单的例子

引入依赖:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.3.11.RELEASE</version>
</dependency>

定义一个接口:

public interface DemoService {    
  String getData();
}

定义接口实现类:

public class DemoServiceImpl implements DemoService {     
  public String getData() {        
    return "hello world";    
  }
}

接下来,我们在 resources 目录新建一个配置文件,文件随意,这里命名成application.xml:

<?xml version="1.0" encoding="UTF-8" ?>
  <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       
  xmlns="http://www.springframework.org/schema/beans"       
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" 
  default-autowire="byName">     
  <bean id="demoService" class="com.wang.example.DemoServiceImpl"/>
</beans>

这样,我们就可以跑起来了:

public class App {    
  public static void main(String[] args) {  
    // 用我们的配置文件来启动一个 ApplicationContext
    ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");         
    System.out.println("context 启动成功");         
    // 从 context 中取出我们的 Bean,这是spring的方式,不用去new DemoServiceImpl       
    DemoService demoService = context.getBean(demoService.class);        
    // 这句将输出: hello world        
    System.out.println(demoService.getData());   
  }
}

这就是一个最简单使用spring的例子,可能很多直接用springboot开发的人都已经不了解这个了,但是如果想要分析spring源码首先要知道它怎么用,如果不知道怎么用,源码分析就无从谈起了。

接下来以这个例子为入口,一起分析下spring的流程。

分析之前我先简单说下流程,后续验证下spring源码的整体流程是不是这样:

会扫描指定的配置文件“classpath:application.xml”,然后扫描解析xml文件,按照里面的节点信息比如“”,实例化对应的对象,对象信息就是节点定义的信息,最后放入到map集合中,叫做“_容器”。_
后续“context.getBean(demoService.class)”方法其实就是从容器(前面的map集合)中获取到的实例。
这里的map集合其实就是spring容器,对应spring中FactoryBean这个类,看名字就知道它是管理bean的一个类。

看一下FactoryBean的部分源码:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    ...
}

关注公众号:麒麟改bug,分享一份170多页的spring核心学习笔记。

可以看到它是一个接口,里面定义了获取bean的各种方法,其实就是从map集合中获取的。上面例子中ApplicationContext和FactoryBean什么关系呢?

答案:FactoryBean是ApplicationContext的父类,所以ApplicationContext属于容器

上图是BeanFactory和ApplicationContext类继承关系,以及主要的BeanFactory子类,后续分析会涉及到这张类图,后续说到类图记得回到这里啊。

FileSystemXmlApplicationContext 构造函数需要一个 xml 配置文件在系统中的路径和ClassPathXmlApplicationContext功能差不多,都是扫描xml文件生成实例的容器。

AnnotationConfigApplicationContext 是用于扫描注解生成实例的容器,目前springboot都是用的这个,等到后续分析springboot源码的时候就可以看到了。

知道了类的大体继承关系后,下面开始分析代码:

ClassPathXmlApplicationContext:

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {
   super(parent);
   // 把配置文件的路径设置到ApplicationContext,供后续调用解析使用
   setConfigLocations(configLocations);
   if (refresh) {
      // spring解析的核心方法
      refresh();
   }
}

AbstractApplicationContext

@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符。不是
      // 核心逻辑,知道就行了
      prepareRefresh();

      // 这个是核心逻辑的第一步,
      // 1. new DefaultListableBeanFactory() 这是核心的容器BeanFactory,都是通过它
      //    获取对应的实例对象的
      // 2. loadBeanDefinitions,解析配置文件application.xml中的实例对象,并生成
      //    一个一个的BeanDefinition,放入Map<String, BeanDefinition> 的一个map中,
      //    其中string是bean的名字,BeanDefinition是描述了一个bean类。
      // 这个时候还没有开始实例化的操作,只是把类的信息解析到了BeanDefinition中。
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 做一些准备工作给Beanfactory,其实就是给beanFactory进行了一系列的配置工作,为
      // 后续操作做准备。比如:ClassLoader 和post-processors等
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         // 这里主要提供给子类的一个扩展点,主要是添加BeanPostProcessor,供子类使用,在
         // 后续finishBeanFactoryInitialization方法中完成实例化后会调用
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 后续会在finishBeanFactoryInitialization中触发
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // 初始化 ApplicationContext 的事件广播器,spring中的publicEvent核心方法就是它,
         // 用来发送事件通知的,监听器可以监听到发出的事件,这个在实际工作中是有用到的。
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 钩子函数,供子类扩展使用的.
         // --------------------------------------------------------
         // springboot中,就是有子类实现了这个方法,进而创建
         // 出内嵌了tomcat容器,创建了WebServerStartStopLifecycle,供tomcat启动
         // 这块会在我后续文章中说明
         onRefresh();

         // Check for listener beans and register them.
         // 注册各种Listeners,上面initApplicationEventMulticaster方法注册了广播器
         // 最后发出的广播事件,都是被这里的监听器来监听的。
         // --------------------------------------------------------
         // springboot启动的时候,会通它做各种的初始化操作,关注我后面的文章
         registerListeners();

         // 这个是最重要的了,也是核心逻辑实例并初始化所有的singleton beans
         finishBeanFactoryInitialization(beanFactory);

         // 调用LifecycleProcessor的onRefresh()方法,并发送ContextRefreshedEvent事件。
         // 收尾工作了属于。
         // --------------------------------------------------------
         // 对于springboot在上面的onRefresh方法中创建了WebServerStartStopLifecycle,
         // 在这一步会调用WebServerStartStopLifecycle的onRefresh方法,完成springboot内嵌
         // tomcat容器的启动。
         // 后面我会单独开一篇文章来讲springboot源码会提到这块,请关注我。
         finishRefresh();
      }
            ....
   }
}

这是主要流程了,里面我都加了注释,和springboot相关的代码我也加了注释。为后续分析springboot源码的文章做准备,希望大家多多关注我后续的文章。

这里只分析spring相关的核心代码:

obtainFreshBeanFactory

finishBeanFactoryInitialization

obtainFreshBeanFactory流程分析

主要完成了创建bean容器,并注册对应的BeanDefinition到容器中

AbstractApplicationContext:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 创建新的 BeanFactory,加载 Bean 定义、注册 Bean
   refreshBeanFactory();
   return getBeanFactory();
}

AbstractRefreshableApplicationContext:

protected final void refreshBeanFactory() throws BeansException {
   // 如果已经加载过 BeanFactory了,并销毁BeanFactory中所有 Bean,关闭 BeanFactory
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      // 创建BeanFactory,创建的子类是DefaultListableBeanFactory,为什么用这个子类?
      // 下面说
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
      customizeBeanFactory(beanFactory);
      // 加载 Bean 到 BeanFactory 中
      loadBeanDefinitions(beanFactory);
      //把容器设置给当前的ApplicationContext
      this.beanFactory = beanFactory;
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

为什么用DefaultListableBeanFactory子类呢?再看下这个类图

DefaultListableBeanFactory几乎继承了所有的BeanFactory相关的类,它把祖祖辈辈的功能都继承下来了,它最牛逼了,所以就创建它了。

前面代码中也提到BeanDefinition,它是spring中很重要的一个类,保存了xml中bean类的定义信息,英文翻译过来也是这个意思“bean定义”,看下它的代码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
   // spring中创建类的方式
   // singleton 只有一个实例,也即是单例模式。
   // prototype访问一次创建一个实例,相当于new。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
   ...
 
   // 设置父 BeanName
   void setParentName(String parentName);
 
   // 获取父 BeanName
   String getParentName();
 
   // 设置 Bean 的类名称
   void setBeanClassName(String beanClassName);
 
   // 获取 Bean 的类名称
   String getBeanClassName();
 
 
   // 设置 bean 的 scope
   void setScope(String scope);
 
   String getScope();
 
   // 设置是否懒加载
   void setLazyInit(boolean lazyInit);
 
   boolean isLazyInit();
 
   // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
   // 是 depends-on="" 属性设置的值。
   void setDependsOn(String... dependsOn);
 
   // 返回该 Bean 的所有依赖
   String[] getDependsOn();
 
   // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
   // 如果根据名称注入,即使这边设置了 false,也是可以的
   void setAutowireCandidate(boolean autowireCandidate);
 
   // 该 Bean 是否可以注入到其他 Bean 中
   boolean isAutowireCandidate();
 
   // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
   void setPrimary(boolean primary);
 
   // 是否是 primary 的
   boolean isPrimary();
 
   // 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
   void setFactoryBeanName(String factoryBeanName);
   // 获取工厂名称
   String getFactoryBeanName();
   // 指定工厂类中的 工厂方法名称
   void setFactoryMethodName(String factoryMethodName);
   // 获取工厂类中的 工厂方法名称
   String getFactoryMethodName();
 
   // 构造器参数
   ConstructorArgumentValues getConstructorArgumentValues();
 
   // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
   MutablePropertyValues getPropertyValues();
 
   // 是否 singleton
   boolean isSingleton();
 
   // 是否 prototype
   boolean isPrototype();
 
   // 如果这个 Bean 原生是抽象类,那么不能实例化
   boolean isAbstract();
 
   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}

可以看到BeanDefinition定义了bean的所有信息,通过它就能把一个bean实例化出来。

接着分析上面的代码:

主要就是如下两个方法了

customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory)
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding != null) {
      // 设置是否允许用一个同名的bean name覆盖bean类定义,来替换前面的一个。
      // 如果允许就替换了,如果不允许就会抛个异常。
      // spring中默认是true,允许。
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      // 设置是否允许循环依赖,并自动解决这个问题。默认是true。
      // 循环依赖就是类A依赖B,B里面通过依赖A,这就是循环依赖了。
      // spring解决这个问题,思路就是用单例(好多教程叫缓存,无所谓了),就是第一次
      // A实例化的时候会放到map容器中,因为依赖B,所以会再实例化B去,实例化
      // B的时候发现B又依赖A,所有又去实例化A,这个时候发现A已经在map容器中存在了,
      // 所以就直接返回,这样就不会再继续循环下去了。
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

继续分析loadBeanDefinitions,它是最主要的,解析了xml,并注册了BeanDefinition到容器中。

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // 给BeanFactory实例化一个 XmlBeanDefinitionReader,看名字就知道
   // 就是解析xml用的
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // 不重要,跳过
   initBeanDefinitionReader(beanDefinitionReader);
   // 继续跟进它,主线逻辑
   loadBeanDefinitions(beanDefinitionReader);
}

loadBeanDefinitions调用最终会把beanDefinition注册到容器中

调用比较多,这个流程我用时序图画出来。

最后调用了这个方法,把BeanDefinition注册到容器中了。下面列出了核心方法。

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

      ...
      
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   // 如果已经存在了这个BeanDefinition
   if (existingDefinition != null) {
      // 检查是否允许覆盖
      if (!isAllowBeanDefinitionOverriding()) {
         // 如果不允许覆盖就抛出异常,前面分析过这个属性了
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      // 注册到容器中,这样就覆盖了原来的bean。
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      // 不存在该bean
      if (hasBeanCreationStarted()) {
         //已经开始创建流程了,用锁锁住,避免冲突
         // Cannot modify startup-time collection elements anymore (for stable iteration)
         synchronized (this.beanDefinitionMap) {
            // 放到容器中
            this.beanDefinitionMap.put(beanName, beanDefinition);
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions;
            removeManualSingletonName(beanName);
         }
      }
      else {
         // 注册beanDefinition到容器中
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }
   ...
}

至此,终于把obtainFreshBeanFactory流程讲完了。

接下来继续finishBeanFactoryInitialization核心流程,把类实例化出来,代码如下:

AbstractApplicationContext

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // 实例化名字为 conversionService 的 Bean。
   // 这块挺常用,后面单独说下,beanFactory.getBean这个方法会触发实例化操作。
   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));
   }
   ...
 
   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);
 
   // 冻结beanDefinition信息,这个时候要开始实例化了,不期望再修改这些信息了。
   // 主要就是设置了一个冻结标示
   beanFactory.freezeConfiguration();
 
   // 实例化bean流程
   beanFactory.preInstantiateSingletons();
}

DefaultListableBeanFactory:

@Override
public void preInstantiateSingletons() throws BeansException {
   if (this.logger.isDebugEnabled()) {
      this.logger.debug("Pre-instantiating singletons in " + this);
   }
 
   List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
 
   // 触发所有的非懒加载的singleton beans 的初始化操作
   for (String beanName : beanNames) {
 
      // 合并父 Bean 中的配置,注意 <bean id="" class="" parent="" /> 中的 parent,
      // 后面会有文章专门讲解
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
 
      // 非抽象、非懒加载的 singletons单例。
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         // 处理 FactoryBean,注意FactoryBean和BeanFactory的区别,后面单独
         // 写文章讲解
         if (isFactoryBean(beanName)) {
            // FactoryBean 的话,在 beanName 前面加上 ‘&’ 符号,然后再调用 getBean,
            // getBean方法最核心方法了会实例化bean,因为前面加上了‘&’符号,所以
            // 获取的就是FactoryBean类型的对象了。
            // --------------------------------------------------
            // 这里简单普及下你定义一个类实现了FactoryBean中的getObject方法,getBean的时候
            // 如果名字前加‘&’会获取这个对象本身,比如Demo类实现了FactoryBean,然后你
            // getBean("&demo"),获取的就是Demo本身。
            // --------------------------------------------------
            // 所以源码中的这个getBean会把你实现了FactoryBean
            // 的类实例化,并放到spring容器中。
            // 后续当你在程序中调用getBean(‘demo’),名字中不加的时候‘&’符号,进而
            // 就会发现容器中已经存在了你的实例对象了(比如上面例子中的Demo),
            // 因为这次你没有加“&”符号,流程会有所不同,它会调用demo实例的getObject方法。
            // 当然这里只是把实现了FactoryBean的类实例化,并放入容器了
            final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
            ...
         }
         else {
            // 对于普通的 Bean,只要调用 getBean(beanName) 这个方法就可以进行初始化了
            getBean(beanName);
         }
      }
   }
 
 
   // 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化
   // 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在这里得到回调,忽略
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
               @Override
               public Object run() {
                  smartSingleton.afterSingletonsInstantiated();
                  return null;
               }
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

接下来分析getBean,会调用doGetBean方法,分析它:

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

   String beanName = transformedBeanName(name);
   Object bean;

   // 检查对象是否已经实例化过了,如果实例化过了,直接从缓存取出来。
   // 如果没有注册过,这里返回肯定就是null了。里面的涉及到三级缓存(很多文章都这样叫)。
   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 + "'");
         }
      }
      // 这个方法里面会判断bean是否实现了FactoryBean,如果是就调用它的getObject方法,
      // 如果不是就直接返回实例。
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
      ....
      try {
         RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd, beanName, args);

         // 检查当前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);
               }
            }
         }

         // 创建单例对象,主要逻辑.
         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);
         }
         // 如果不是单例,创建非单例对象
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName, mbd, args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
         }

         else {
           ...省去不重要代码
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // 如果传入了requiredType,检查requiredType和bean类型是否匹配,它也会尝试转换一下,
   // finishBeanFactoryInitialization方法的最开始有提到conversionService,就是
   // 在这里会尝试做转换,这块平时工作用的也比较多,比如日期格式转换相关的,就是在这里
   // 转换的。
   if (requiredType != null && !requiredType.isInstance(bean)) {
      try {
         T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
         if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
         return convertedBean;
      }
      catch (TypeMismatchException ex) {
         if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                  ClassUtils.getQualifiedName(requiredType) + "'", ex);
         }
         throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
      }
   }
   return (T) bean;
}

关注公众号:麒麟改bug,分享一份170多页的spring核心学习笔记。

接下来再看createBean方法,它会执行具体的实例化,并把实例化后的对象放到容器中。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
   if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
   RootBeanDefinition mbdToUse = mbd;

   // 确保 BeanDefinition 中的 Class 被加载
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }
  // 准备方法覆盖,不重要
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
            beanName, "Validation of method overrides failed", ex);
   }

   try {
      // 提供BeanPostProcessors接口一个机会来替换当前bean,来返回你自己定义的代理
      // bean。
      // 对应的方法postProcessBeforeInstantiation和postProcessAfterInstantiation.
      // 方法入参是bean,返回的也是bean,给你机会让你在方法中替换下。
      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 {
      // 创建实例的核心方法
      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:

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

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 实例化对象
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   .....

   // 解决循环依赖问题的
   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));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      // 处理依赖注入比如@Autowaried,@Resource,实例对象的属性赋值操作。
      populateBean(beanName, mbd, instanceWrapper);
      // 调用各种回调函数。比如BeanPostProcessor接口的回调,
      // InitializingBean接口的afterPropertiesSet的回调接口,以及各种
      // Aware接口。
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   ....
   
   return exposedObject;
}

这里省去了不必要的代码。

分析到这里大体的情况已经比较清晰了,如果有兴趣可以再深入分析。

这里把initializeBean方法分析下,因为工作中用的比较多。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
      AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
         invokeAwareMethods(beanName, bean);
         return null;
      }, getAccessControlContext());
   }
   else {
      // 调用各Aware子类的接口
      invokeAwareMethods(beanName, bean);
   }

   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) {
      // 调用BeanPostProcessors接口的postProcessBeforeInitialization方法
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
      // 调用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()) {
     // 调用BeanPostProcessors接口的postProcessAfterInitialization方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }

   return wrappedBean;
}

总结

把整体的流程串了一遍,里面也有比较详细的注释。这里面涉及到很多spring给开发者留的口,来让开发者进行扩展回调使用。这些扩展口也是很有用,限于篇幅,我后面会再写一篇文章把这些重要的扩展点配合源码给大家讲明白。

接下来还会跟大家分析springboot,springcloud,mybatis, springAOP等源码分析,spring是基础一定要先看懂这篇文章,可以自己对照着代码,自己跟一遍,这块懂了,后续的分析就都简单了。

喜欢文章记得关注我点赞哟,感谢支持!重要的事情说三遍,转发+转发+转发,一定要记得转发哦!!!

相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
14天前
|
存储 NoSQL 架构师
阿里面试:聊聊 CAP 定理?哪些中间件是AP?为什么?
本文深入探讨了分布式系统中的“不可能三角”——CAP定理,即一致性(C)、可用性(A)和分区容错性(P)三者无法兼得。通过实例分析了不同场景下如何权衡CAP,并介绍了几种典型分布式中间件的CAP策略,强调了理解CAP定理对于架构设计的重要性。
47 4
|
18天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
存储 NoSQL 算法
阿里面试:亿级 redis 排行榜,如何设计?
本文由40岁老架构师尼恩撰写,针对近期读者在一线互联网企业面试中遇到的高频面试题进行系统化梳理,如使用ZSET排序统计、亿级用户排行榜设计等。文章详细介绍了Redis的四大统计(基数统计、二值统计、排序统计、聚合统计)原理和应用场景,重点讲解了Redis有序集合(Sorted Set)的使用方法和命令,以及如何设计社交点赞系统和游戏玩家排行榜。此外,还探讨了超高并发下Redis热key分治原理、亿级用户排行榜的范围分片设计、Redis Cluster集群持久化方式等内容。文章最后提供了大量面试真题和解决方案,帮助读者提升技术实力,顺利通过面试。
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
64 9
|
1月前
|
SQL 关系型数据库 MySQL
阿里面试:1000万级大表, 如何 加索引?
45岁老架构师尼恩在其读者交流群中分享了如何在生产环境中给大表加索引的方法。文章详细介绍了两种索引构建方式:在线模式(Online DDL)和离线模式(Offline DDL),并深入探讨了 MySQL 5.6.7 之前的“影子策略”和 pt-online-schema-change 方案,以及 MySQL 5.6.7 之后的内部 Online DDL 特性。通过这些方法,可以有效地减少 DDL 操作对业务的影响,确保数据的一致性和完整性。尼恩还提供了大量面试题和解决方案,帮助读者在面试中充分展示技术实力。
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
1月前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
1月前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
58 4