Spring refresh函数(1)——Spring的BeanFactory和BeanDefinition

后续的Spring内容在我的公众号《魔法师和ta的南瓜小屋》或其他文章详细介绍。

Spring中最重要的函数实现refresh()函数,Spring中两项核心——控制反转(IoC)和面向切面编程(AOP)——就是在这里实现完成的。BeanFactory和BeanDefinition在Spring和Spring Boot中作用是完全相同的。下面源代码选自Spring 5.2.2.RELEASE版本,以Spring xml文件配置Bean为示例(Spring Boot依赖注解)。由于目前Spring Boot已经逐渐取代原来基于xml配置的Spring,渐渐成为各大互联网或软件公司的主力框架。为了贴合实际应用,会插入Spring Boot区别的地方。

BeanFactory

BeanFactory顾名思义就是“生成Bean的工厂”,Spring通过BeanFactory对Bean进行创建。
refresh()函数中调用obtainFreshBeanFactory()获取BeanFactory实例。

// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

抽象类AbstractRefreshableApplicationContext具体实现refreshBeanFactory()函数,默认的BeanFactory对象为DefaultListableBeanFactory类。

//Spring
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
    }
    try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(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);
    }
}

而在Spring Boot中虽然也经过了函数obtainFreshBeanFactory(),但是调用的是类GenericApplicationContext refreshBeanFactory()函数。此时BeanFactory对象实际已经创建完成,仅仅设置SerializationId。BeanFactory对象的创建在GenericApplicationContext的无参数构造函数中。

//Spring Boot
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
    if (!this.refreshed.compareAndSet(false, true)) {
      throw new IllegalStateException(
          "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
    }
    this.beanFactory.setSerializationId(getId());
}

这是Spring Boot相较于Spring的一个改动,Spring Boot将BeanFactory对象的创建提前到了上下文创建时。相同的是默认的BeanFactory对象都是DefaultListableBeanFactory类。


图片选自我的公众号

BeanDefinition

BeanDefinition是“Bean在Spring中的描述”。Spring解析配置文件、注解等获取需要注入的Bean信息,使用BeanDefinition结构存储这些Bean的信息,包括Bean的名字,是否是单例,属性值,构造方法等等。之后从这些BeanDefinition获取需要的信息对Bean进行实例化。

Spring在函数obtainFreshBeanFactory()中完成xml配置信息向BeanDefinition转化。

调用AbstractApplicationContext类中的函数obtainFreshBeanFactory()。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

类AbstractRefreshableApplicationContext中的refreshBeanFactory()函数。

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
    }
    try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(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);
    }
}

从loadBeanDefinitions()函数开始,按照如下路径找到类XmlBeanDefinitionReader中的函数doLoadBeanDefinitions()。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
    try {
      Document doc = doLoadDocument(inputSource, resource);
      int count = registerBeanDefinitions(doc, resource);
      if (logger.isDebugEnabled()) {
        logger.debug("Loaded " + count + " bean definitions from " + resource);
      }
      return count;
    }
    catch (BeanDefinitionStoreException ex) {
      throw ex;
    }
    catch (SAXParseException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
          "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
    }
    catch (SAXException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
          "XML document from " + resource + " is invalid", ex);
    }
    catch (ParserConfigurationException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
          "Parser configuration exception parsing XML from " + resource, ex);
    }
    catch (IOException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
          "IOException parsing XML document from " + resource, ex);
    }
    catch (Throwable ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
          "Unexpected exception parsing XML document from " + resource, ex);
    }
}

获取Document实例,注册BeanDefinition信息。

Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);

走到类XmlBeanDefinitionReader中的函数registerBeanDefinitions()。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

然后类DefaultBeanDefinitionDocumentReader中的registerBeanDefinitions()。

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    doRegisterBeanDefinitions(doc.getDocumentElement());
}

类DefaultBeanDefinitionDocumentReader中的doRegisterBeanDefinitions()。创建delegate对象是用于解析xml文件中Bean的定义,parseBeanDefinitions()函数具体执行xml配置到BeanDefinition结构的转换。

protected void doRegisterBeanDefinitions(Element root) {
    // Any nested  elements will cause recursion in this method. In
    // order to propagate and preserve  default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
      if (StringUtils.hasText(profileSpec)) {
        String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        // We cannot use Profiles.of(...) since profile expressions are not supported
        // in XML config. See SPR-12458 for details.
        if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
          if (logger.isDebugEnabled()) {
            logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                "] not matching: " + getReaderContext().getResource());
          }
          return;
        }
      }
    }

    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    postProcessXml(root);

    this.delegate = parent;
}

类DefaultBeanDefinitionDocumentReader中函数parseBeanDefinitions(),由于是默认标签,之后调用parseDefaultElement()方法。自定义标签则调用delegate.parseCustomElement()。

在parseDefaultElement()方法中依据标签的不同注册为对应的BeanDefinition结构。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
    }
}

Spring Boot中,BeanDefinition的注册是在函数invokeBeanFactoryPostProcessors()中完成的。公众号中其他文章会详细介绍Spring Boot的invokeBeanFactoryPostProcessors()函数以及Spring Boot。

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

你可能感兴趣的:(Spring refresh函数(1)——Spring的BeanFactory和BeanDefinition)