spring源码3 -- ioc加载的整体流程

markdown 复制代码
可以学习到什么?
0. spring ioc整体脉络
1. 描述BeanFactory
2. BeanFactory和ApplicationContext的区别
3. 简述SpringIoC的加载过程
4. 简述Bean的生命周期
5. Spring中有哪些扩展接口及调用机制

之前我们知道了spring ioc的加载过程, 具体如下图. 下面我们就来对照下图, 看看ioc加载的源代码.

下面在用装修类比, 看看个个组件都是怎么工作的.

接下来是源码分析的整体结构图. 对照上面的思路梳理出来的

一、源码分析的入口

通常,我们的入口都是从main方法进入. 这里我们也来定义一个main方法

java 复制代码
public class MainStarter {
    public static void main(String[] args) {
        // 第一步: 通过AnnotationConfigApplicationContext读取一个配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainStarter.class);
        context.scan("package name");
        Car car = (Car) context.getBean("car");
        System.out.println(car.getName());
        context.close();
    }
}

顺便再来看看还有哪些相关的类

java 复制代码
/**
 * 这是一个配置类,
 * 在配置类里面定义了扫描的包路径com.lxl.www.iocbeanlifecicle
 * 这是会将这个包下配置了注解的类扫描到ioc容器里面,成为一个成熟的bean
 */
@Configuration
@ComponentScan(basePackages = {"com.lxl.www.iocbeanlifecicle"})
public class MainConfig {
}

这个类有一个注解@Configuration, 这样这个类会被扫描成bean

还有一个注解@ComponentScan(backPackage = {"com.lxl.www.iocbeanlifecicle"}) 他表示, 请扫描com.lxl.www.iocbeanlifecicle包下所有的类.

com.lxl.www.iocbeanlifecicle 这个包下还有哪些类呢? 我们来看看项目结构

这是这个包下完整的项目结构.

下面会逐渐说明, 每个类的用途

二、最重要的类BeanFactory

我们知道在将一个class加载为bean的过程中BeanFactory是最最重要的, 那么他是何时被加载的呢?

我们来跟踪一下带有一个参数的构造方法AnnotationConfigApplicationContext

java 复制代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    // 进入构造函数, 首先调用自身的构造方法this();
    // 调用自身的构造方法之前, 要先调用父类的构造方法
    this();
    // retister配置注册类
    register(componentClasses);
    // ioc容器刷新接口--非常重要
    refresh();
}

这就是AnnotationConfigApplicationContext初始化的时候做的三件事

第一件事: this(); //调用自身的无参构造方法. 调用之前先调用父类的构造方法

第二件事: register(componentClasses); // 调用注册器, 这里会加载两个BeanDefinitionReader和BeanDefinitionScanner. 这两位的角色是什么呢? 可以回忆一下之前的框架图

第三件事: refresh(); // 这是ioc容器刷新, 非常重要. 无论是spring boot还是spring mvc都有这个方法. 这个方法包含了整个spring ioc加载的全生命流程. 也是我们要重点学习的方法

下面来看看BeanFactory是何时被加载进来的呢?

在初始化方法的时候调用了自身的无参构造函数, 在调用自身无参构造函数的时候, 同时会调用父类的无参构造函数.

java 复制代码
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
  ......
} 

父类是GenericApplicationContext, 其无参构造函数就做了一件事

java 复制代码
public GenericApplicationContext() {
    // 构造了一个BeanFactory.
    // 在调用GenericApplicationContext父类构造函数, 为ApplicationContext spring上下文对象初始化beanFactory
    // 为什么初始化的是DefaultListableBeanFactory呢?
    // 我们在看BeanFactory接口的时候发现DefaultListableBeanFactory是最底层的实现, 功能是最全的.
    // 查看
    this.beanFactory = new DefaultListableBeanFactory();
}

初始化DefaultListableBeanFactory.

问题: BeanFactory有很多, 为什么初始化的时候选择DefaultListableBeanFactory呢?

我们来看看DefaultListableBeanFactory的结构. 快捷键option + command + u --> Java Class Diagrams

通过观察, 我们发现, DefaultListableBeanFactory实现了各种各样的BeanFactory接口, 同时还实现了BeanDefinitionRegistry接口.

也就是说, DefaultListableBeanFactory不仅仅有BeanFactory的能力, 同时还有BeanDefinitionRegistry的能力. 它的功能是最全的.

所以, 我们使用的是一个功能非常强大的类Bean工厂类.

AnnotationConfigApplicationContext继承了GenericApplicationContext

而GenericApplicationContext 实现了AnnotationConfigRegistry接口.

所以AnnotationConfigApplicationContext有AnnotationConfigRegistry的能力.

接着上面, 第一步调用的是this(). 也就是AnnotationConfigApplicationContext的无参构造函数.

在这个无参构造函数里一共做了两件事情:

1. 初始化AnnotatedBeanDefinitionReader.

2. 初始化ClassPathBeanDefinitionScanner

java 复制代码
public AnnotationConfigApplicationContext() {
   StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
   /**
    *  创建了一个Bean定义的读取器.
    *  完成了spring内部BeanDefinition的注册(主要是后置处理器)
    *  读取了很多spring自定义的配置(主要是后置处理器). 这些类都是spring的原始类.
    */
   this.reader = new AnnotatedBeanDefinitionReader(this);
   createAnnotatedBeanDefReader.end();
   /**
    *  创建BeanDefinition扫描器
    *  可以用来扫描包或者类, 进而转换为BeanDefinition
    *
    * 
    *  Spring默认的扫描包不是这个scanner对象
    *  而是自己new的一个ClassPathBeanDefinitionScanner
    *  Spring在执行工程后置处理器ConfigurationClassPostProcessor时, 去扫描包时会new一个ClassPathBeanDefinitionScanner
    *
    * 
    *  这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
    *  通过调用context.scan("包名");扫描处理配置类
    *  扫描
    */
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

三、bean定义读取器AnnotatedBeanDefinitionReader

我们先来看看AnnotatedBeanDefinitionReader

在这里的描述中, 我们知道BeanDefinitionReader是要去扫描配置或者注解, 如果理解为销售的话, 就是扫描楼盘. 这里面就有我们的潜在用户. 也就是我们需要将其转换为bean的对象.

那么初始化的时候,AnnotatedBeanDefinitionReader做了什么呢? 重点看这句

java 复制代码
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    // 继续调重载方法
   this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   Assert.notNull(environment, "Environment must not be null");
   this.registry = registry;
   this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
   AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

注册注解类型配置的处理器

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

java 复制代码
/**
 * Register all relevant annotation post processors in the given registry.
 * 在给定的注册表中,注册所有相关的Annotation后置处理器
 */

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   /*todo: 获取到beanFactory : DefaultListableBeanFactory和GenericApplicationContext都是BeanDefinitionRegistry接口的实现类*/
   DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
   /*todo: 判断beanFactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver,没有则添加*/
   /**
    * (1) AnnotationAwareOrderComparator
    * 是OrderComparator的扩展,支持Spring的Ordered接口以及@Order和@Priority注解.Ordered实例提供的order值覆盖静态定义的注解值(如果有)
    * (2) ContextAnnotationAutowireCandidateResolver:
    * 完成AutowireCandidateResolver策略接口的实现,支持限定符注释以及context.annotation包中的lazy注释驱动的惰性解析
    */
   if (beanFactory != null) {
      if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
         beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      }
      if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
         beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      }
   }
   /* todo: BeanDefinitionHolder: 为BeanDefinition设置名字和别名 */
   Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

   /* todo: 1. 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器, 就添加一个 */
   if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   /* todo: 2. 如果registry中, 没有AutowiredAnnotationBeanPostProcessor  Autowired注解bean的后置处理器, 则添加一个 */
   if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   /* todo: 3. 检查对JSR-250的支持, 如果registry中没有CommonAnnotationBeanPostProcessor通用注解后置处理器, 则添加一个 */
   // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
   if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   /* todo: 4. 检查对jpa的支持, 如果不包含internalPersistenceAnnotationProcessor, 持久化注解处理器, 就添加一个 */
   // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
   if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition();
      try {
         def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
               AnnotationConfigUtils.class.getClassLoader()));
      } catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      }
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
   }

   /* todo: 5. 检查对事件监听的支持, 如果不包含事件监听处理器internalEventListenerProcessor, 就添加一个 */
   if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
   }

   /* todo: 6. 如果不包含事件监听工厂处理器internalEventListenerFactory , 就添加一个 */
   if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      def.setSource(source);
      /** 构建BeanDefinitionHolder, 并添加到beanDefs */
      beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
   }

   return beanDefs;
}

在这里注册了6个后置处理器.

四、bean定义扫描器ClassPathBeanDefinitionScanner

java 复制代码
public AnnotationConfigApplicationContext() {
   StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
   /**
    *  创建了一个Bean定义的读取器.
    *  完成了spring内部BeanDefinition的注册(主要是后置处理器)
    *  读取了很多spring自定义的配置(主要是后置处理器). 这些类都是spring的原始类.
    */
   this.reader = new AnnotatedBeanDefinitionReader(this);
   createAnnotatedBeanDefReader.end();
   /**
    *  创建BeanDefinition扫描器
    *  可以用来扫描包或者类, 进而转换为BeanDefinition
    *
    * 
    *  Spring默认的扫描包不是这个scanner对象
    *  而是自己new的一个ClassPathBeanDefinitionScanner
    *  Spring在执行工程后置处理器ConfigurationClassPostProcessor时, 去扫描包时会new一个ClassPathBeanDefinitionScanner
    *
    * 
    *  这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法
    *  通过调用context.scan("包名");扫描处理配置类
    *  扫描
    */
   this.scanner = new ClassPathBeanDefinitionScanner(this);
}

这部分初始化了BeanDefinition扫描器. 这里的这个scanner不是spring默认的扫描包.

Spring默认的扫描包不是这个scanner对象, 而是自己new的一个ClassPathBeanDefinitionScanner,

Spring在执行后置处理器ConfigurationClassPostProcessor时, 去扫描包时会new一个ClassPathBeanDefinitionScanner,

这里的scanner仅仅是为了程序员可以手动调用AnnotationConfigApplicationContext对象的scan方法,通过调用context.scan("package name");扫描处理配置类

java 复制代码
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
   // 向下调用重载方法 useDefaultFilters默认给的true
   this(registry, true);
}

// 继续向下调用重载方法...

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      Environment environment, @Nullable ResourceLoader resourceLoader) {

   Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
   this.registry = registry;

   if (useDefaultFilters) {
      registerDefaultFilters();
   }
   setEnvironment(environment);
   setResourceLoader(resourceLoader);
}

首先调用了ClassPathBeanDefinitionScanner(this) 构造方法, 然后调用registerDefaultFilter注册默认的过滤器, 这里面默认的过滤器有两种: javax.annotation.ManagedBean 和 javax.inject.Named. 同时隐含的会注册所有带有@Component @Repository @Controller关键字的注解

java 复制代码
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
   this.includeFilters.add(new AnnotationTypeFilter(Component.class));
   ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
   try {
      this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
   }
   catch (ClassNotFoundException ex) {
      // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
   }
   try {
      this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
   }
   catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
   }
}

在ClassPathBeanDefinitionScanner中, 有一个非常重要的方法, 就是doScan(String ...beanPackages). 用来扫描传入的配置文件.

五、注册配置方法

java 复制代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   /* todo: 调用自身的构造方法之前, 要先调用父类的构造方法 ---> this.beanFactory = new DefaultListableBeanFactory(); */
   /* todo: 然后调用自身的构造方法this() ---> 一共做了两件事情*/
   this();
   // 调用注册器, 这里会加载两个BeanDefinitionReader和BeanDefinitionScanner. 这两位的角色是什么呢? 可以回忆一下之前的框架图
   register(componentClasses);
   refresh();
}

这是AnnotationConfigApplicationContext方法的构造函数, 里面第二步调用了register()方法.

java 复制代码
@Override
public void register(Class<?>... componentClasses) {
   Assert.notEmpty(componentClasses, "At least one component class must be specified");
   StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register")
         .tag("classes", () -> Arrays.toString(componentClasses));
   /**继续往里走,一直找到doRegisterBean*/
   this.reader.register(componentClasses);
   registerComponentClass.end();
}
java 复制代码
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
      @Nullable BeanDefinitionCustomizer[] customizers) {

   /*todo:将入参beanClass构建成AnnotatedGenericBeanDefinition对象*/
   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
   }

   abd.setInstanceSupplier(supplier);
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

   /*todo:处理通用定义注解*/
   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   if (qualifiers != null) {
      for (Class<? extends Annotation> qualifier : qualifiers) {
         if (Primary.class == qualifier) {
            abd.setPrimary(true);
         }
         else if (Lazy.class == qualifier) {
            abd.setLazyInit(true);
         }
         else {
            abd.addQualifier(new AutowireCandidateQualifier(qualifier));
         }
      }
   }
   if (customizers != null) {
      for (BeanDefinitionCustomizer customizer : customizers) {
         customizer.customize(abd);
      }
   }

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);用来加载bean元数据中的注解

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);用来注册bean定义. 经过一系列的校验, 没有问题, 然后将其让入到this.beanDefinitionMap.put(beanName, beanDefinition);中

具体做了哪些工作, 可以看看上面的结构图

六、Refresh() -- spring ioc容器刷新方法

java 复制代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
   /* todo: 调用自身的构造方法之前, 要先调用父类的构造方法 ---> this.beanFactory = new DefaultListableBeanFactory(); */
   /* todo: 然后调用自身的构造方法this() ---> 一共做了两件事情*/
   this();
   // 调用注册器, 这里会加载两个BeanDefinitionReader和BeanDefinitionScanner. 这两位的角色是什么呢? 可以回忆一下之前的框架图
   register(componentClasses);
   /*todo:ioc容器刷新接口--非常重要*/
   refresh();
}

refresh()方法, spring有很多衍生品, 比如spring mvc ,spring boot, 都有这个方法. refresh()里面定义了spring ioc中bean加载的全过程.

java 复制代码
@Override
public void refresh() throws BeansException, IllegalStateException {
   // 为了避免refresh()还没结束,再次发起启动或者销毁容器引起的冲突
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.做一些准备工作,记录容器的启动时间、标记"已启动"状态、检查环境变量等
      /*todo: 1.准备刷新上下文环境*/
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      // 乍一看这个方法也没几行代码,但是这个方法负责了BeanFactory的初始化、Bean的加载和注册等事件
      /*todo: 2.获取告诉子类初始化bean工厂, 不同工厂不同实现*/
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      // 这个方法主要会设置BeanFactory的类加载器、添加几个 BeanPostProcessor、手动注册几个特殊的bean
      /*todo: 3.对bean工厂进行填充属性*/
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         /**
          * 这个比较简单,又是Spring的一个扩展点
          * 如果有Bean实现了BeanFactoryPostProcessor接口,
          * 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。
          * 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
          */
         /*todo: 4.Spring开放接口 留给子类去实现该接口*/
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // Invoke factory processors registered as beans in the context.
         // 调用BeanFactoryPostProcessor各个实现类的postProcessBeanFactory(factory) 方法
         /*todo: 5.调用我们的bean工厂的后置处理器:  (1) 会再次class扫描成BeanDefinition*/
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         /**
          * 又是一个扩展点
          * 注册 BeanPostProcessor 的实现类,注意不是BeanFactoryPostProcessor
          * 此接口有两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization分别会在Bean初始化之前和初始化之后得到执行
          */
         /*todo: 6.注册我们bean后置处理器*/
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();

         // Initialize message source for this context.
         // 初始化当前 ApplicationContext 的 MessageSource,有想了解国际化的相关知识可以深入研究一下
         /*todo: 7.初始化国际化资源处理器*/
         initMessageSource();

         // Initialize event multicaster for this context.
         // 这个方法主要为初始化当前 ApplicationContext 的事件广播器
         /*todo: 8.初始化事件多播放器*/
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 又是一个扩展点,子类可以在这里来搞事情
         /*todo: 9.这个方法同样也是留个子类实现,其中springboot也是从这个方法进行tomcat的启动*/
         onRefresh();

         // Check for listener beans and register them.
         // 注册事件监听器
         /*todo: 10.把我们的事件监听器注册到多播器上*/
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons. 实例化剩余的单实例bean
         // 刚才我们提到了bean还没有初始化。这个方法就是负责初始化所有的没有设置懒加载的singleton bean
         /*todo: 11.实例化所有的非懒加载的单实例bean*/
         /**
          * 这个方法就是循环遍历BeanDefinitionMap, 调用getBean, 去生产bean
          */
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 最后一步: 发布相应的事件
         /*todo: 12.最后刷新容器 发布刷新事件(Spring cloud eureka也是从这里启动的)*/
         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();
         contextRefresh.end();
      }
   }
}

这是refresh()的源码, 在refresh()中做了很多很多事情, 我们这次主要看和ioc中beanFactory创建bean有关的部分.

一个是: invokeBeanFactoryPostProcessors(beanFactory);

另一个是: finishBeanFactoryInitialization(beanFactory);

1、invokeBeanFactoryPostProcessors(beanFactory) 调用BeanFactory的后置处理器

在**AnnotatedBeanDefinitionReader**这里扫描了所有后置处理器, 将其解析到beanDefinitionMap, 在这里调用后置处理器

2、finishBeanFactoryInitialization 实例化剩余的单实例bean

这个方法就是循环遍历BeanDefinitionMap, 调用getBean, 去生产bean

第一个是: 冻结配置类, 意思是说, 我马上就要开始制造bean了, bean配置文件不能再修改了, 所以被冻结

原理是有一个变量标记, 设为true标记冻结

java 复制代码
@Override
public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

第二个是实例化创建bean

java 复制代码
@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;

   // 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.
   // 确保 BeanDefinition 中的 Class 被加载
   // 确保此时的bean已经被解析了
   Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   // 准备方法覆写,如果bean中定义了 <lookup-method /> 和 <replaced-method />
   try {
      /**
       * 验证和准备覆盖方法(近在xml方式中)
       * lookup-method 和 replace-method
       * 这两个配置存放在BeanDefinition中的methodOverrides(仅在XML方式中)
       * 在XML方式中, bean实例化的过程中如果检测到存在methodOverrides
       * 则会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理
       * 具体的实现我们后续分析. 现在先看mbdToUse.prepareMethodOverrides()代码块
       */
      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.
      // 如果有代理的话直接返回
      /**
       * 初始化之前的解析
       * 第一次调用bean后置处理器
       * 通过bean的后置处理器来进行后置处理生成代理对象, 一般情况下在此处不会生成代理对象
       * 为什么不能生成代理对象? 不管是我们的JDK还是cglib代理都不会在此处进行代理, 因为我们的真实对象没有生成,
       * 所以在这里不会生成代理对象
       * 这一步是aop和事务的关键, 因为在这解析我们的aop切面信息进行缓存.
       */
      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, 这里就是执行创建bean的三个步骤
       * 1. 实例化
       * 2. 填充属性, @Autowired @Value
       * 3. 初始化  初始化initMethod方法和初始化destroy方法
       */
      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);
   }
}

创建bean的三个步骤

java 复制代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   //如果是.factoryBean则从缓存删除
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      // 实例化 Bean,这个方法里面才是终点,下面说
      /**
       * 第一步: 实例化
       * 这里面的调用链非常深, 后面再看
       * bean实例化有两种方式
       * 1. 使用反射:  使用反射也有两种方式,
       *         a. 通过无参构造函数 (默认的方式)
       *             从beanDefinition中可以得到beanClass,
       *             ClassName = BeanDefinition.beanClass
       *             Class clazz = Class.forName(ClassName);
       *             clazz.newInstance();
       *             这样就可以实例化bean了
       *
       *         b. 通过有参函数.
       *            ClassName = BeanDefinition.beanClass
       *             Class clazz = Class.forName(ClassName);
       *             Constructor con = class.getConstructor(args....)
       *             con.newInstance();
       *
       * 2. 使用工厂
       *         我们使用@Bean的方式, 就是使用的工厂模式, 自己控制实例化过程
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   /*todo:这里使用了装饰器的设计模式*/
   Object bean = instanceWrapper.getWrappedInstance();
   // bean类型
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   /*todo:允许后置处理器修改已经合并的beanDefinition*/
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            // 循环调用实现了MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法
            // Spring对这个接口有几个默认的实现,其中大家最熟悉的一个是操作@Autowired注解的
            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");
      }
      //当正在创建A时,A依赖B,此时通过(将A作为ObjectFactory放入单例工厂中进行early expose,此处B需要引用A,但A正在创建,从单例工厂拿到ObjectFactory,从而允许循环依赖
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   Object exposedObject = bean;
   try {
      /*todo:第二步:填充属性, 给属性赋值(调用set方法)  这里也是调用的后置处理器*/
      populateBean(beanName, mbd, instanceWrapper);
      // 这里是处理bean初始化完成后的各种回调,例如init-method、InitializingBean 接口、BeanPostProcessor 接口
      /*todo:第三步: 初始化.*/
      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) {
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               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 " +
                           "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   // 把bean注册到相应的Scope中
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   } catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

具体结构如下:

相关推荐
程序员-珍25 分钟前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
徐*红33 分钟前
springboot使用minio(8.5.11)
java·spring boot·spring
海里真的有鱼34 分钟前
好文推荐-架构
后端
骆晨学长1 小时前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
AskHarries1 小时前
利用反射实现动态代理
java·后端·reflect
Flying_Fish_roe2 小时前
Spring Boot-Session管理问题
java·spring boot·后端
hai405872 小时前
Spring Boot中的响应与分层解耦架构
spring boot·后端·架构
哈喽,树先生3 小时前
1.Seata 1.5.2 seata-server搭建
spring·springcloud
Adolf_19934 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
叫我:松哥4 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap