关于后端:spring源码之refresh第二篇

38次阅读

共计 3783 个字符,预计需要花费 10 分钟才能阅读完成。

大家好,我是程序员田同学

上篇文章对 spring 外围启动办法 refresh 做了整体的解读,然而只是泛泛而谈,接下来会出一零碎文章对每个办法的源码进行粗浅解读。

第一篇文章见 spring 源码之办法概览

首先,第一个办法是 prepareRefresh() 办法,这个办法做的事很简略,也不是本文的重点。该办法记录容器的启动工夫,初始化监听容器。

protected void prepareRefresh() {
        // Switch to active
        // 纪录启动工夫
        this.startupDate = System.currentTimeMillis();
        System.out.println("spring 启动工夫为 --------------------" + this.startupDate);
        this.closed.set(false);
        System.out.println("spring 标记为未敞开 --------------------" + this.closed);
        this.active.set(true);
        System.out.println("spring 以后激活状态 --------------------" + this.active);
 
        if (logger.isDebugEnabled()) {if (logger.isTraceEnabled()) {logger.trace("Refreshing" + this);
            } else {logger.debug("Refreshing" + getDisplayName());
            }
        }
        // Initialize any placeholder property sources in the context environment.
        // 空办法
        initPropertySources();
 
        // Validate that all properties marked as required are resolvable:
        // see ConfigurablePropertyResolver#setRequiredProperties
        // 校验 xml 配置文件
        getEnvironment().validateRequiredProperties();
 
        // Store pre-refresh ApplicationListeners...
        // 初始化 applicationListeners 监听容器
        if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>              (this.applicationListeners);
        } else {
            // Reset local application listeners to pre-refresh state.
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }
 
        // Allow for the collection of early ApplicationEvents,
        // to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<>();}
    

读者大抵搂一眼即可,对这个办法整体就能很快把握。

接下来才是明天的重头戏——obtainFreshBeanFactory() 办法,是 refresh() 办法中的第二个办法,也是整个 refresh() 办法中外围办法之一。

该办法次要的作用是,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。(Bean 并没有实现初始化)

点进去 obtainFreshBeanFactory() 办法咱们一探到底。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {// 敞开旧的 BeanFactory ( 如果有),创立新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
   refreshBeanFactory();

   // 返回刚刚创立的 BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {logger.debug("Bean factory for" + getDisplayName() + ":" + beanFactory);
   }
   return beanFactory;
}

refreshBeanFactory() 应该是这个办法的重头戏,咱们再深刻进去。

@Override
protected final void refreshBeanFactory() throws BeansException {
   // 如果 ApplicationContext 中曾经加载过 BeanFactory 了,销毁所有 Bean,敞开 BeanFactory
   // 留神,利用中 BeanFactory 原本就是能够多个的,这里可不是说利用全局是否有 BeanFactory,而是以后 ApplicationContext 是否有 BeanFactory
   if (hasBeanFactory()) {destroyBeans();
      closeBeanFactory();}
   try {
      // 初始化一个 DefaultListableBeanFactory,为什么应用这个 BeanFactory?因为这是最牛的 BeanFactory。DefaultListableBeanFactory beanFactory = createBeanFactory();
      // 用于 BeanFactory 的序列化
      beanFactory.setSerializationId(getId());

      // 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用
      customizeBeanFactory(beanFactory);

      // 加载 Bean 到 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);
   }
}

简略提一句,DefaultListableBeanFactory 为什么是最牛的 BeanFactory 看下这个继承图大略就明了。

  // 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用
  customizeBeanFactory(beanFactory);

这个形式只是一个设置,设置是否容许循环依赖,至于什么是循环依赖呢?也就是 A-B- C 之间他们相互依赖,spring 有一套本人的机制去解决循环依赖,当前文章为进行剖析,这一步仅仅是配置是否容许循环依赖,读者分明就能够了。

   // 这个办法将依据配置,加载各个 Bean,而后放到 BeanFactory 中
  loadBeanDefinitions(beanFactory);

通过下面一系列的步骤,一个 beandefintion 就造成,beandefintion 就是咱们常说的 bean,也就是一个对象的加强版。

接下来就须要把这个 bean 退出到 beanfactory 中了,这一步交给 loadBeanDefinitions() 办法去执行。

spring 办法命名的确精妙,只看看办法名大略也晓得每个办法干了什么!

创立一个 beanDefinitionReader(bean 阅读器)去读取 xml 中的 bean, 尽管 xml 很少用了,然而用它来举例还是很经典的。

真正干活的是 loadBeanDefinitions(beanDefinitionReader),往下走很漫长漫长,把咱们 xml 中的 bean 解析成 BeanDefinition,并调用 registerBeanDefinition() 办法把它注册到注册核心,发送注册事件。

总结一下,到这里曾经初始化了 Bean 容器,<bean /> 配置也相应的转换为了一个个 BeanDefinition,而后注册了各个 BeanDefinition 到注册核心,并且发送了注册事件。

到此 obtainFreshBeanFactory() 办法也就正式完结了。

spring 的调用过程链路十分十分的长,一步步点进去没一会你就迷了,田同学认为比拟好的一个方法就是,先站在办法体外看这个办法干了什么,而后逐渐拆分进入到每一个办法中。

站在 refresh() 外看这两个办法,prepareRefresh() 筹备一下刷新要做的事,obtainFreshBeanFactory() 注册好 bean 并退出到 beanfactory 中。

好啦,明天的 spring 源码剖析就到这里了。

正文完
 0