likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 30
可以学习到什么?
0. 一起找spring ioc源码
1. 认识bean定义读取器: AnnotatedBeanDefinitionReader
2. 认识bean定义扫描器: ClassPathBeanDefinitionScanner
3. 一起分析注册配置方法:register(componentClasses);
4. 源码第一关: 概括refresh()
5. 拆开refresh(): 第一课BeanFactory创建bean

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

spring源码3 -- ioc加载的整体流程 下面在用装修类比, 看看个个组件都是怎么工作的.

spring源码3 -- ioc加载的整体流程 接下来是源码分析的整体结构图. 对照上面的思路梳理出来的

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

一、源码分析的入口

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

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();
    }
}

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

/**
 * 这是一个配置类,
 * 在配置类里面定义了扫描的包路径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 这个包下还有哪些类呢? 我们来看看项目结构

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

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

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

二、最重要的类BeanFactory

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

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

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是何时被加载进来的呢?

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

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
  ......
} 

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

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

初始化DefaultListableBeanFactory.

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

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

spring源码3 -- ioc加载的整体流程 通过观察, 我们发现, DefaultListableBeanFactory实现了各种各样的BeanFactory接口, 同时还实现了BeanDefinitionRegistry接口.

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

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

AnnotationConfigApplicationContext继承了GenericApplicationContext

而GenericApplicationContext 实现了AnnotationConfigRegistry接口.

所以AnnotationConfigApplicationContext有AnnotationConfigRegistry的能力.

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

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

1. 初始化AnnotatedBeanDefinitionReader.

2. 初始化ClassPathBeanDefinitionScanner

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

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

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

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);

/**
 * 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个后置处理器.

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

四、bean定义扫描器ClassPathBeanDefinitionScanner

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");扫描处理配置类

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

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关键字的注解

@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). 用来扫描传入的配置文件.

五、注册配置方法

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

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

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

@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();
}
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容器刷新方法

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加载的全过程.

@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标记冻结

@Override
public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

第二个是实例化创建bean

@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的三个步骤

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;
}

具体结构如下:

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

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