Spring源码分析(2)——IOC 源码深度剖析(上)

7. IOC 源码深度剖析

IOC容器初始化主流程

   public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        TestBean testBean = (TestBean) applicationContext.getBean("testBean");
        testBean.print();
    }

第一步,我们肯定要从 ClassPathXmlApplicationContext 的构造方法说起

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
  private Resource[] configResources;

  // 如果已经有 ApplicationContext 并需要配置成父子关系,那么调用这个构造方法
  public ClassPathXmlApplicationContext(ApplicationContext parent) {
    super(parent);
  }
  ...
  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
      throws BeansException {

    super(parent);
    // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
    setConfigLocations(configLocations);
    
      if (refresh) {
      refresh(); // 核心方法
    }
  }
    ...
}

核心方法:refresh();

public void refresh() throws BeansException, IllegalStateException {
        
        //加锁,防止多线程重复启动。
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            //准备刷新
            /*
               【1.准备刷新】
                  (1) 设置容器的启动时间
                  (2) 设置活跃状态为true
                  (3) 设置关闭状态为false
                  (4) 获取Environment对象,并加载当前系统的属性值到Environment对象中
                  (5) 准备监听器和时间的集合对象,默认为空的集合
             */
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            /*
                【2.初始化 新BeanFactory】重点!
                  (1)如果存在旧 BeanFactory,则销毁
                  (2)创建新的 BeanFactory(DefaluListbaleBeanFactory)
                  (3)解析xml/加载 Bean 定义、注册 Bean定义到beanFactory(不初始化)
                  (4)返回新的 BeanFactory(DefaluListbaleBeanFactory)
             */
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            // 【3. bean工厂前置操作】为BeanFactory配置容器特性
            // 例如类加载器、表达式解析器、注册默认环境bean、后置管理器BeanPostProcessor
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                // 【4. bean工厂后置操作】此处为空方法,如果子类需要,自己去实现
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //【5. 调用bean工厂后置处理器】,执行已注册的beanFactoryPostProcessor的实现类,在这里完成了类的扫描、解析和注册
                //目标:
                //调用顺序一:先bean定义 注册后置处理器
                //调用顺序二:后bean工厂后置处理器
                // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                //【6.注册bean后置处理器】只是注册,但是还不会调用
                //逻辑:找出所有实现BeanPostProcessor接口的类,分类、排序、注册
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //【7.初始化消息源】国际化问题i18n
                initMessageSource();

                // Initialize event multicaster for this context.
                //【8、初始化事件广播器】初始化自定义的事件监听多路广播器
                // 如果需要发布事件,就调它的multicastEvent方法
                // 把事件广播给listeners,其实就是起一个线程来处理,把Event扔给listener处理
                // (可以通过 SimpleApplicationEventMulticaster的代码来验证)
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
               // 【9、刷新:拓展方法】这是个protected空方法,交给具体的子类来实现
                //  可以在这里初始化一些特殊的 Bean
                onRefresh();

                // Check for listener beans and register them.
               //【10、注册监听器】,监听器需要实现 ApplicationListener 接口
                // 也就是扫描这些实现了接口的类,给他放进广播器的列表中
                // 其实就是个观察者模式,广播器接到事件的调用时,去循环listeners列表,
                // 挨个调它们的onApplicationEvent方法,把event扔给它们。
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                ///【11、 实例化所有剩余的(非惰性初始化)单例】
                // (1)初始化所有的 singleton beans,反射生成对象/填充
                // (2)调用Bean的前置处理器和后置处理器
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                // 【12、结束refresh操作】
                // 发布事件与清除上下文环境
                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();
            }
        }
    }

【1.准备刷新 】prepareRefresh();

方法概述

为刷新准备新的上下文环境,设置其启动日期和活动标志以及执行一些属性的初始化。主要是一些准备工作(不是很重要的方法)

源码剖析

prepareRefresh();

protected void prepareRefresh() {
   // 记录启动时间,
   // 将 active 属性设置为 true,closed 属性设置为 false,它们都是 AtomicBoolean 类型
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
      logger.info("Refreshing " + this);
   }

   // Initialize any placeholder property sources in the context environment
   initPropertySources();

   // 会创建StandardEnvironment对象 校验 xml 配置文件
   getEnvironment().validateRequiredProperties();

   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

【2.初始化 BeanFactory 】obtainFreshBeanFactory(); 重点!

方法概述

作用:用于获得一个新的 BeanFactory

流程:该方法会解析所有 Spring 配置文件(通常我们会放在 resources 目录下),将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中(只注册,不会进行Bean的实例化)。

常见的,如果解析到<context:component-scan base-package=“com.itheima” /> 注解时,会扫描 base-package 指定的目录,将该目录下使用指定注解(@Controller、@Service、@Component、@Repository)的 bean 定义也同样封装成 BeanDefinition,加载到 BeanFactory 中。

上面提到的“加载到 BeanFactory 中”的内容主要指的是以下3个缓存(map):(Bean并没有实例化)

  • beanDefinitionNames缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 集合。
  • beanDefinitionMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和 BeanDefinition 映射。
  • aliasMap缓存:所有被加载到 BeanFactory 中的 bean 的 beanName 和别名映射。

源码剖析

obtainFreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 1.判断是否已经存在 BeanFactory,如果存在则先销毁、关闭该 BeanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 2.创建一个新的BeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 用于 BeanFactory 的序列化,大部分人应该都用不到
        beanFactory.setSerializationId(getId());
         // 重要:设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
        customizeBeanFactory(beanFactory);
        // 3.重要:加载 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);
    }
}
代码块1:refreshBeanFactory 方法
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 1.判断是否已经存在 BeanFactory,如果存在则先销毁、关闭该 BeanFactory
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 2.创建一个新的BeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 用于 BeanFactory 的序列化,大部分人应该都用不到
        beanFactory.setSerializationId(getId());
         // 重要:设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用
        customizeBeanFactory(beanFactory);
        // 3.重要:加载 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);
    }
}
BeanDefinition 接口

BeanDefinition 中保存了我们的 Bean 信息,比如这个 Bean 指向的是哪个类、是否是单例的、是否懒加载、这个 Bean 依赖了哪些 Bean 等等。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

   // 我们可以看到,默认只提供 sington 和 prototype 两种,
   // 同学们可能知道还有 request, session, globalSession, application, websocket 这几种,
   // 不过,它们属于基于 web 的扩展。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

   // 比较不重要,直接跳过吧
   int ROLE_APPLICATION = 0;
   int ROLE_SUPPORT = 1;
   int ROLE_INFRASTRUCTURE = 2;

   // 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
   // 一句话就是:继承父 Bean 的配置信息而已
   void setParentName(String parentName);

   // 获取父 Bean
   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 是被设置为 abstract,那么不能实例化,
   // 常用于作为 父bean 用于继承,其实也很少用......
   boolean isAbstract();

   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}

有了 BeanDefinition 的概念以后,我们再往下看 refreshBeanFactory() 方法中的剩余部分:

customizeBeanFactory();

customizeBeanFactory(beanFactory) 比较简单,就是配置是否允许 BeanDefinition 覆盖、是否允许循环引用。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding != null) {
      // 是否允许 Bean 定义覆盖
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      // 是否允许 Bean 间的循环依赖
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

是否允许 Bean 定义覆盖:

allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。

是否允许 Bean 间的循环依赖:

A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A。

默认情况下,Spring 允许循环依赖

3.加载 bean 定义,由 XmlWebApplicationContext 实现,见代码块2详解

代码块2:loadBeanDefinitions
/** 我们可以看到,此方法将通过一个 XmlBeanDefinitionReader 实例来加载各个 Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // 1.为指定BeanFactory创建XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
    
    // 2.使用此上下文的资源加载环境配置 XmlBeanDefinitionReader
   beanDefinitionReader.setEnvironment(this.getEnvironment());
     // resourceLoader赋值为XmlWebApplicationContext
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // 初始化 BeanDefinitionReader,其实这个是提供给子类覆写的,
   initBeanDefinitionReader(beanDefinitionReader);
    
    // 3.加载 bean 定义 重点
   loadBeanDefinitions(beanDefinitionReader);
}

3.加载 bean 定义,见代码块3详解

代码块3:loadBeanDefinitions
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    // 1.获取配置文件路径
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      // 往下看
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
     // 2.根据配置文件路径加载 bean 定义
      reader.loadBeanDefinitions(configLocations);
   }
}
 
// AbstractRefreshableWebApplicationContext.java
@Override
public String[] getConfigLocations() {
    return super.getConfigLocations();
}
 
// AbstractRefreshableConfigApplicationContext.java
protected String[] getConfigLocations() {
    return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
}
 
// XmlWebApplicationContext.java
@Override
protected String[] getDefaultConfigLocations() {
    if (getNamespace() != null) {
        return new String[]{DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
    } else {
        return new String[]{DEFAULT_CONFIG_LOCATION};
    }
}

1.获取配置文件路径:如果 configLocations 属性不为空,则返回 configLocations 的值;否则,调用 getDefaultConfigLocations() 方法。获取到配置文件路径(Spring 默认的配置路径:/WEB-INF/applicationContext.xml。)

2.根据配置文件路径加载 bean 定义,见代码块4详解

代码块4:loadBeanDefinitions
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    // 1.遍历所有的Resource
    for (Resource resource : resources) {
        // 2.根据Resource加载bean的定义,XmlBeanDefinitionReader实现
        counter += loadBeanDefinitions(resource);
    }
    return counter;
}

2.根据 Resource 加载 bean 定义,由 XmlBeanDefinitionReader 实现,见代码块5详解

方法块5:loadBeanDefinitions
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    // 加载 bean 定义
    return loadBeanDefinitions(new EncodedResource(resource));
}
 
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }
 
    // 1.当前正在加载的EncodedResource
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    // 2.将当前encodedResource添加到currentResources
    if (!currentResources.add(encodedResource)) {
        // 如果添加失败,代表当前的encodedResource已经存在,则表示出现了循环加载
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // 3.拿到Resource的inputStream
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // 4.将inputStream封装成org.xml.sax.InputSource
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // 5.加载 bean 定义(方法以do开头,真正处理的方法)
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        } finally {
            inputStream.close();
        }
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    } finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

5.加载 bean 定义,方法以 do 开头,真正处理的方法,见代码块6详解

代码块6:doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
        throws BeanDefinitionStoreException {
    try {
        // 1.根据inputSource和resource加载XML文件,并封装成Document
        Document doc = doLoadDocument(inputSource, resource);
        // 2.根据返回的Document注册Bean信息(对配置文件的解析,核心逻辑)
        return registerBeanDefinitions(doc, resource);
    } 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);
    }
}

1.根据 inputSource 和 resource 加载 XML文件,并封装成 Document,见代码块7详解

2.根据返回的 Document 注册 bean 信息,见代码块8详解

代码块7:doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    // 1.getValidationModeForResource(resource): 获取XML配置文件的验证模式
    // 2.documentLoader.loadDocument: 加载XML文件,并得到对应的 Document
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
            getValidationModeForResource(resource), isNamespaceAware());
}
 
protected int getValidationModeForResource(Resource resource) {
    int validationModeToUse = getValidationMode();
    // 1.1 如果手动指定了XML文件的验证模式则使用指定的验证模式
    if (validationModeToUse != VALIDATION_AUTO) {
        return validationModeToUse;
    }
    // 1.2 如果未指定则使用自动检测
    int detectedMode = detectValidationMode(resource);
    // 1.3 如果检测出的验证模式不为 VALIDATION_AUTO, 则返回检测出来的验证模式
    if (detectedMode != VALIDATION_AUTO) {
        return detectedMode;
    }
    // Hmm, we didn't get a clear indication... Let's assume XSD,
    // since apparently no DTD declaration has been found up until
    // detection stopped (before finding the document's root tag).
    // 1.4 如果最终没找到验证模式,则使用 XSD
    return VALIDATION_XSD;
}
 
protected int detectValidationMode(Resource resource) {
    // 1.2.1 校验resource是否为open stream
    if (resource.isOpen()) {
        throw new BeanDefinitionStoreException(
                "Passed-in Resource [" + resource + "] contains an open stream: " +
                        "cannot determine validation mode automatically. Either pass in a Resource " +
                        "that is able to create fresh streams, or explicitly specify the validationMode " +
                        "on your XmlBeanDefinitionReader instance.");
    }
 
    InputStream inputStream;
    try {
        // 1.2.2 校验resource是否可以打开InputStream
        inputStream = resource.getInputStream();
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
                        "Did you attempt to load directly from a SAX InputSource without specifying the " +
                        "validationMode on your XmlBeanDefinitionReader instance?", ex);
    }
 
    try {
        // 1.2.3 根据inputStream检测验证模式
        return this.validationModeDetector.detectValidationMode(inputStream);
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
                resource + "]: an error occurred whilst reading from the InputStream.", ex);
    }
}
 
public int detectValidationMode(InputStream inputStream) throws IOException {
    // Peek into the file to look for DOCTYPE.
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    try {
        boolean isDtdValidated = false;
        String content;
        // 1.2.3.1 按行遍历xml配置文件,获取xml文件的验证模式
        while ((content = reader.readLine()) != null) {
            content = consumeCommentTokens(content);
            // 如果读取的行是空或者注释则略过
            if (this.inComment || !StringUtils.hasText(content)) {
                continue;
            }
            // 内容包含"DOCTYPE"则为DTD,否则为XSD
            if (hasDoctype(content)) {
                isDtdValidated = true;
                break;
            }
            // 如果content带有 '<' 开始符号,则结束遍历。因为验证模式一定会在开始符号之前,所以到此可以认为没有验证模式
            if (hasOpeningTag(content)) {
                // End of meaningful data...
                break;
            }
        }
        // 1.2.3.2 根据遍历结果返回验证模式是 DTD 还是 XSD
        return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
    } catch (CharConversionException ex) {
        // Choked on some character encoding...
        // Leave the decision up to the caller.
        return VALIDATION_AUTO;
    } finally {
        reader.close();
    }
}
 
// DefaultDocumentLoader.java
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
        ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    // 2.1 创建DocumentBuilderFactory
    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isDebugEnabled()) {
        logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    // 2.2 通过DocumentBuilderFactory创建DocumentBuilder
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    // 2.3 使用DocumentBuilder解析inputSource返回Document对象
    return builder.parse(inputSource);
}

1.获取 XML 配置文件的验证模式。XML 文件的验证模式是用来保证 XML 文件的正确性,常见的验证模式有两种:DTD 和 XSD,以下简单展示下这两种验证模式的配置。

DTD 验证模式(已停止更新)

要使用 DTD 验证模式的时候需要在 XML 文件的头部声明,以下是在 Spring 中使用 DTD 声明方式的代码:

image-20211013182854137

XSD 验证模式

image-20211013182910247

代码块8:registerBeanDefinitions
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // 1.使用DefaultBeanDefinitionDocumentReader实例化BeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // 2.记录统计前BeanDefinition的加载个数
    int countBefore = getRegistry().getBeanDefinitionCount();
    // 3.createReaderContext:根据resource创建一个XmlReaderContext
    // 4.registerBeanDefinitions:加载及注册Bean定义
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // 5.返回本次加载的BeanDefinition个数
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

4.加载及注册 bean 定义,由 DefaultBeanDefinitionDocumentReader 实现,见代码块9详解

代码块9:registerBeanDefinitions
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    logger.debug("Loading bean definitions");
    // 1.拿到文档的子节点,对于Spring的配置文件来说,理论上应该都是<beans>
    Element root = doc.getDocumentElement();
    // 2.通过拿到的节点,注册 Bean 定义
    doRegisterBeanDefinitions(root);
}

2.通过拿到的节点,注册 bean 定义,见代码块10详解

代码块10:doRegisterBeanDefinitions
protected void doRegisterBeanDefinitions(Element root) {
    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> 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;
    // 构建BeanDefinitionParserDelegate
    this.delegate = createDelegate(getReaderContext(), root, parent);
 
    // 1.校验root节点的命名空间是否为默认的命名空间(默认命名空间http://www.springframework.org/schema/beans)
    if (this.delegate.isDefaultNamespace(root)) {
        // 2.处理profile属性
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                    profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // 校验当前节点的 profile 是否符合当前环境定义的, 如果不是则直接跳过, 不解析该节点下的内容
            if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                            "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // 3.解析前处理, 留给子类实现
    preProcessXml(root);
    // 4.解析并注册bean定义
    parseBeanDefinitions(root, this.delegate);
    // 5.解析后处理, 留给子类实现
    postProcessXml(root);
 
    this.delegate = parent;
}

4.解析并注册 bean 定义,见代码块11详解

代码块11:parseBeanDefinitions
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // 1.默认命名空间的处理
    if (delegate.isDefaultNamespace(root)) {
        NodeList nl = root.getChildNodes();
        // 遍历root的子节点列表
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element ele = (Element) node;
                if (delegate.isDefaultNamespace(ele)) {
                    // 1.1 默认命名空间节点的处理,例如: <bean id="test" class="" />
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // 1.2 自定义命名空间节点的处理,例如:<context:component-scan/>、<aop:aspectj-autoproxy/>
                    delegate.parseCustomElement(ele);
                }
            }
        }
    } else {
        // 2.自定义命名空间的处理
        delegate.parseCustomElement(root);
    }
}

最终,我们来到了解析 bean 定义的核心部分,这边会遍历 root 节点(正常为 节点)下的所有子节点,对子节点进行解析处理。

如果节点的命名空间是 Spring 默认的命名空间,则走 parseDefaultElement(ele, delegate) 方法进行解析,例如最常见的:。

如果节点的命名空间不是 Spring 默认的命名空间,也就是自定义命名空间,则走 delegate.parseCustomElement(ele) 方法进行解析,例如常见的: context:component-scan/、aop:aspectj-autoproxy/。

如何判断默认命名空间还是自定义命名空间?

默认的命名空间为:http://www.springframework.org/schema/beans,其他都是自定义命名空间,

例如下图 aop 的命名空间为:http://www.springframework.org/schema/aop

image-20211013183419716

// 1.1 默认命名空间节点的处理,例如:

parseDefaultElement(ele, delegate);
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate){
    // 1.对import标签的处理
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    // 2.对alias标签的处理
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    // 3.对bean标签的处理(最复杂最重要)
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    // 4.对beans标签的处理
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

可以看到默认命名空间的一级节点只有4种:import、alias、bean、beans。这4种节点中,最重要、最复杂的就是 节点,重点介绍 节点的处理,理解了 节点后,其他的都不难理解。

另外, 节点只是递归调用之前的 doRegisterBeanDefinitions 方法,因此无需再介绍。

processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // 1.进行节点定义解析, 经过这个方法后,bdHolder会包含一个Bean节点的所有属性,例如name、class、id
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        // 2.若存在默认标签的子节点下再有自定义属性,需要再次对自定义标签再进行解析(基本不用,不做深入解析)
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            // 3.解析节点定义完成后,需要对解析后的bdHolder进行注册
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        } catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        // 4.最后发出响应事件,通知相关的监听器,这个Bean已经加载完成了
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}
  1. 进行节点定义解析,见代码块1详解
  2. 基本不用,不做深入解析。
  3. 解析节点定义完成后,需要对解析后的 bdHolder 进行注册,见代码块13详解
  4. 发出响应事件,通知相关的监听器,不做深入解析。
代码块1:parseBeanDefinitionElement
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}
 
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
    // 1.解析name和id属性
    // 解析id属性
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // 解析name属性
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
 
    // 分割name属性(通过逗号或分号)
    // 例如:<bean name="demoService,demoServiceAlias" class=""/>,分割后aliases为[demoService, demoServiceAlias]
    List<String> aliases = new ArrayList<String>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }
 
    // beanName默认使用id
    String beanName = id;
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        // 如果id为空,并且aliases不为空,则取aliases的第一个元素作为beanName,其他的仍作为别名
        beanName = aliases.remove(0);
        if (logger.isDebugEnabled()) {
            logger.debug("No XML 'id' specified - using '" + beanName +
                    "' as bean name and " + aliases + " as aliases");
        }
    }
 
    if (containingBean == null) {
        // 检查beanName和aliases是否在同一个 <beans> 下已经存在
        checkNameUniqueness(beanName, aliases, ele);
    }
 
    // 2.进一步解析bean的其他所有属性并统一封装至GenericBeanDefinition类型实例中
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                // 3.如果bean定义存在,但是beanName为空,则用Spring默认的生成规则为当前bean生成beanName
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                            beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    // Spring提供的生成规则生成beanName,例如:com.itheima.demo.service.impl.DemoServiceImpl#0
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    // Register an alias for the plain bean class name, if still possible,
                    // if the generator returned the class name plus a suffix.
                    // This is expected for Spring 1.2/2.0 backwards compatibility.
                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null &&
                            beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                            !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        // 如果Spring默认的生成规则生成的beanName为:类名加后缀,则将类名注册为别名
                        aliases.add(beanClassName);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Neither XML 'id' nor 'name' specified - " +
                            "using generated bean name [" + beanName + "]");
                }
            }
            catch (Exception ex) {
                error(ex.getMessage(), ele);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        // 4.将bean定义、beanName、bean别名数组封装成BeanDefinitionHolder
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }
 
    return null;
}

1.解析 name 和 id 属性,其中 name 属性可以通过分割符设置多个。如果 id 存在,则 使用 id 作为 beanName,name 属性分割后全部作为别名;如果 id 不存在,则将 name 属性分割后的第1个作为 beanName,剩下的全部作为别名。

举个例子:

<!-- 配置1 -->
<bean id="appleService" name="appleOne;appleTwo" class="com.xc.AppleServiceImpl"/>
 
<!-- 配置2 -->
<bean name="bananaOne;bananaTwo" class="com.xc.BananaServiceImpl"/>

2.进一步解析 bean 的其他所有属性并统一封装至 GenericBeanDefinition 类型实例中,见代码块2详解

代码块2:parseBeanDefinitionElement
public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {
 
    this.parseState.push(new BeanEntry(beanName));
 
    String className = null;
    // 1.解析class、parent属性
    // 解析class属性
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
 
    try {
        String parent = null;
        // 解析parent属性
        if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
            parent = ele.getAttribute(PARENT_ATTRIBUTE);
        }
        // 2.创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
 
        // 3.解析bean的各种属性
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        // 提取description
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
 
        // 解析元数据子节点(基本不用, 不深入介绍)
        parseMetaElements(ele, bd);
        // 解析lookup-method子节点(基本不用, 不深入介绍)
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        // 解析replaced-method子节点(基本不用, 不深入介绍)
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
 
        // 4.解析constructor-arg子节点
        parseConstructorArgElements(ele, bd);
        // 5.解析property子节点
        parsePropertyElements(ele, bd);
        // 解析qualifier子节点(基本不用, 不深入介绍)
        parseQualifierElements(ele, bd);
 
        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));
 
        return bd;
    }
    catch (ClassNotFoundException ex) {
        error("Bean class [" + className + "] not found", ele, ex);
    }
    catch (NoClassDefFoundError err) {
        error("Class that bean class [" + className + "] depends on not found", ele, err);
    }
    catch (Throwable ex) {
        error("Unexpected failure during bean definition parsing", ele, ex);
    }
    finally {
        this.parseState.pop();
    }
 
    return null;
}

1.解析了class、parent属性,因为第2步创建 AbstractBeanDefinition 需要用到这两个属性,否则,这两个属性可以放到第3步一起解析。

2.创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition。比较简单,直接 new 一个 GenericBeanDefinition,如果 className 和 classLoader 不为空,则通过反射构建出 BeanClass,并设置为 GenericBeanDefinition 的属性。

3.解析 bean 的剩余属性,见代码块3详解

4.解析 constructor-arg 子节点

5.解析 property 子节点,见代码块4详解

代码块3:parseBeanDefinitionAttributes
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
        BeanDefinition containingBean, AbstractBeanDefinition bd) {
    // 解析singleton属性
    if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        // singleton属性已经不支持, 如果使用了会直接抛出异常, 请使用scope属性代替
        error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
    }
    // 解析scope属性
    else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
        bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
    }
    else if (containingBean != null) {
        // Take default from containing bean in case of an inner bean definition.
        bd.setScope(containingBean.getScope());
    }
 
    // 解析abstract属性
    if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
        bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
    }
 
    // 解析lazy-init属性, 默认为false
    String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
    if (DEFAULT_VALUE.equals(lazyInit)) {
        lazyInit = this.defaults.getLazyInit();
    }
    bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
 
    // 解析autowire属性
    String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
    bd.setAutowireMode(getAutowireMode(autowire));
 
    // 解析dependency-check属性
    String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
    bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
 
    // 解析depends-on属性
    if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
        String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
        bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
    }
 
    // 解析autowire-candidate属性
    String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
    if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
        String candidatePattern = this.defaults.getAutowireCandidates();
        if (candidatePattern != null) {
            String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
            bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
        }
    }
    else {
        bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
    }
 
    // 解析primary属性
    if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
        bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
    }
 
    // 解析init-method属性
    if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
        String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
        if (!"".equals(initMethodName)) {
            bd.setInitMethodName(initMethodName);
        }
    }
    else {
        if (this.defaults.getInitMethod() != null) {
            bd.setInitMethodName(this.defaults.getInitMethod());
            bd.setEnforceInitMethod(false);
        }
    }
 
    // 解析destroy-method属性
    if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
        String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
        bd.setDestroyMethodName(destroyMethodName);
    }
    else {
        if (this.defaults.getDestroyMethod() != null) {
            bd.setDestroyMethodName(this.defaults.getDestroyMethod());
            bd.setEnforceDestroyMethod(false);
        }
    }
 
    // 解析factory-method属性
    if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
        bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
    }
    // 解析factory-bean属性
    if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
        bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
    }
 
    return bd;
}

内容比较简单,就是从节点 ele 拿到所有的属性值,塞给 AbstractBeanDefinition 的对应属性。这些属性的使用如下图。

image-20230813224523113

代码块4:parsePropertyElements
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    // 拿到beanEle节点的所有子节点
    NodeList nl = beanEle.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
            // 解析property节点
            parsePropertyElement((Element) node, bd);
        }
    }
}

拿到 beanEle 节点的所有子节点,遍历解析所有是 property 节点的子节点,见代码块5详解

property 的使用如下图所示,property 节点类似于set方法,bean 中的属性必须要有 set 方法才可以使用,否则会报错。

代码块5:parsePropertyElement
public void parsePropertyElement(Element ele, BeanDefinition bd) {
    // 1.拿到name属性
    String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    if (!StringUtils.hasLength(propertyName)) {
        // name属性为必要属性,如果没有配置,则抛出异常
        error("Tag 'property' must have a 'name' attribute", ele);
        return;
    }
    this.parseState.push(new PropertyEntry(propertyName));
    try {
        // 2.校验在相同bean节点下,是否存在相同的name属性,如果存在则抛出异常
        if (bd.getPropertyValues().contains(propertyName)) {
            error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            return;
        }
        // 3.解析属性值
        Object val = parsePropertyValue(ele, bd, propertyName);
        // 4.将解析的属性值和属性name封装成PropertyValue
        PropertyValue pv = new PropertyValue(propertyName, val);
        // 5.解析meta节点(基本不用,不深入解析)
        parseMetaElements(ele, pv);
        pv.setSource(extractSource(ele));
        // 6.将解析出来的PropertyValue,添加到BeanDefinition的propertyValues属性中(上面的重复校验用到)
        bd.getPropertyValues().addPropertyValue(pv);
    }
    finally {
        this.parseState.pop();
    }
}
代码块6:registerBeanDefinition
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {
 
    // Register bean definition under primary name.
    // 1.拿到beanName
    String beanName = definitionHolder.getBeanName();
    // 2.注册beanName、BeanDefinition到缓存中(核心逻辑),实现类为; DefaultListableBeanFactory
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
 
    // Register aliases for bean name, if any.
    // 注册bean名称的别名(如果有的话)
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            // 3.注册bean的beanName和对应的别名映射到缓存中(缓存:aliasMap)
            registry.registerAlias(beanName, alias);
        }
    }
}

2.注册 beanName、BeanDefinition 到缓存中,见代码块7详解

3.如果有别名,则注册 bean 的 beanName 和对应的别名映射到 aliasMap 缓存中,见代码块9详解

代码块7:registerBeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {
    // 1.beanName和beanDefinition为空校验
    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
 
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            // 注册前的最后校验
            ((AbstractBeanDefinition) beanDefinition).validate();
        } catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }
 
    BeanDefinition oldBeanDefinition;
 
    // 首先根据beanName从beanDefinitionMap缓存中尝试获取
    oldBeanDefinition = this.beanDefinitionMap.get(beanName);
    if (oldBeanDefinition != null) {
        // 2.beanName存在于缓存中
        if (!isAllowBeanDefinitionOverriding()) {
            // 如果不允许相同beanName重新注册,则直接抛出异常
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                            "': There is already [" + oldBeanDefinition + "] bound.");
        } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
                        "' with a framework-generated bean definition: replacing [" +
                        oldBeanDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (!beanDefinition.equals(oldBeanDefinition)) {
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        } else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + oldBeanDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        // 将本次传进来的beanName 和 BeanDefinition映射放入beanDefinitionMap缓存(以供后续创建bean时使用)
        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
        // 3.beanName不存在于缓存中
        if (hasBeanCreationStarted()) {
            // 3.1 bean创建阶段已经开始
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                // 将本次传进来的beanName 和 BeanDefinition映射放入beanDefinitionMap缓存
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 将本次传进来的beanName 加入beanDefinitionNames缓存
                List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                // 将beanName从manualSingletonNames缓存移除
                if (this.manualSingletonNames.contains(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                    updatedSingletons.remove(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        } else {
            // 3.2 bean创建阶段还未开始
            // Still in startup registration phase
            // 将本次传进来的beanName 和 BeanDefinition映射放入beanDefinitionMap缓存
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 将本次传进来的beanName 加入beanDefinitionNames缓存
            this.beanDefinitionNames.add(beanName);
            // 将beanName从manualSingletonNames缓存移除
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
 
    // 4.如果存在相同beanName的BeanDefinition,并且beanName已经存在单例对象,则将该beanName对应的缓存信息、单例对象清除,
    // 因为这些对象都是通过oldBeanDefinition创建出来的,需要被覆盖掉的,
    // 我们需要用新的BeanDefinition(也就是本次传进来的beanDefinition)来创建这些缓存和单例对象
    if (oldBeanDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

这个方法会将 beanName 添加到 beanDefinitionNames 缓存,将 beanName 和 BeanDefinition 的映射关系添加到beanDefinitionMap 缓存。

如果 beanName不重复(一般不会重复),对于我们当前正在解析的 obtainFreshBeanFactory 方法来说,因为 bean 创建还未开始,因此会走到 3.2 进行缓存的注册。

4.如果 beanName 重复,并且该 beanName 已经存在单例对象,则会调用 resetBeanDefinition 方法,见代码块8详解。

代码块8:resetBeanDefinition
protected void resetBeanDefinition(String beanName) {
    // Remove the merged bean definition for the given bean, if already created.
    // 1.删除beanName的mergedBeanDefinitions缓存(如果有的话)
    clearMergedBeanDefinition(beanName);
 
    // Remove corresponding bean from singleton cache, if any. Shouldn't usually
    // be necessary, rather just meant for overriding a context's default beans
    // (e.g. the default StaticMessageSource in a StaticApplicationContext).
    // 2.从单例缓存中删除该beanName对应的bean(如果有的话)
    destroySingleton(beanName);
 
    // Reset all bean definitions that have the given bean as parent (recursively).
    // 3.重置beanName的所有子Bean定义(递归)
    for (String bdName : this.beanDefinitionNames) {
        if (!beanName.equals(bdName)) {
            BeanDefinition bd = this.beanDefinitionMap.get(bdName);
            // 当前遍历的BeanDefinition的parentName为beanName,则递归调用resetBeanDefinition进行重置
            if (beanName.equals(bd.getParentName())) {
                resetBeanDefinition(bdName);
            }
        }
    }
}

比较简单,将该 beanName 的 mergedBeanDefinitions 缓存信息删除、单例缓存删除。如果存在子 bean 定义,则递归重置。实际开发过程中,基本不会出现 beanName 相同的情况,因此基本不会走到该方法。

代码块9:registerAlias
@Override
public void registerAlias(String name, String alias) {
    Assert.hasText(name, "'name' must not be empty");
    Assert.hasText(alias, "'alias' must not be empty");
    // 1.如果别名和beanName相同,则不算别名,从aliasMap缓存中移除
    if (alias.equals(name)) {
        this.aliasMap.remove(alias);
    }
    else {
        String registeredName = this.aliasMap.get(alias);
        if (registeredName != null) {
            if (registeredName.equals(name)) {
                // An existing alias - no need to re-register
                // 2.如果别名已经注册过,直接返回
                return;
            }
            // 3.如果存在相同的别名,并且不允许别名覆盖,则抛出异常
            if (!allowAliasOverriding()) {
                throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                        name + "': It is already registered for name '" + registeredName + "'.");
            }
        }
        // 4.检查name和alias是否存在循环引用。例如A的别名为B,B的别名为A
        checkForAliasCircle(name, alias);
        // 5.将别名和beanName的映射放到aliasMap缓存中
        this.aliasMap.put(alias, name);
    }
}

将别名和 beanName 注册到 aliasMap 缓存。

方法总结

到这里已经初始化了 Bean 容器,<bean /> 配置也相应的转换为了一个个 BeanDefinition,然后注册了各个 BeanDefinition 到注册中心,并且发送了注册事件

  • 首先,将 xml 中的 bean 配置信息进行了解析,并构建了 AbstractBeanDefinition(GenericBeanDefinition) 对象来存放所有解析出来的属性
  • 其次,将 AbstractBeanDefinition 、beanName、aliasesArray 构建成 BeanDefinitionHolder 对象并返回
  • 最后,通过 BeanDefinitionHolder 将 BeanDefinition 和 beanName 注册到 BeanFactory 中,也就是存放到缓存中。

执行完 parseDefaultElement 方法,我们得到了两个重要的缓存:

  • beanDefinitionNames 缓存
  • beanDefinitionMap 缓存

【3. bean工厂前置操作】prepareBeanFactory(beanFactory);

方法概述

配置 beanFactory 的标准上下文特征,例如上下文的 ClassLoader、后置处理器等。这个方法会注册3个默认环境 bean:environment、systemProperties 和 systemEnvironment,注册 2 个 bean 后置处理器:ApplicationContextAwareProcessor 和 ApplicationListenerDetector。

源码剖析

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 设置 BeanFactory 的类加载器 BeanFactory 需要加载类,也就需要类加载器
        beanFactory.setBeanClassLoader(getClassLoader());
        // 设置EL表达式解析器(Bean初始化完成后填充属性时会用到)
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        //设置属性注册解析器PropertyEditor
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        // 添加一个 BeanPostProcessor,这个 processor 比较简单:
        // 实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调,
        // 这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
        // 注意:它不仅仅回调 ApplicationContextAware,还会负责回调 EnvironmentAware、ResourceLoaderAware 等
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        //忽略依赖接口
        // skip:下面几行的意思就是,如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
        // Spring 会通过其他方式来处理这些依赖。
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        /*
         * skip:下面几行就是为特殊的几个 bean 赋值,如果有 bean 依赖了以下几个接口,会注入这边相应的值,
         */
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        // 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
        // 那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        //*****************************智能注册***************************************************
        //如果当前BeanFactory包含loadTimeWeaver Bean,说明存在类加载期织入AspectJ,
        // 这里涉及到特殊的 bean,名为:loadTimeWeaver,这不是我们的重点,忽略它
        // tips: ltw 是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样,
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        /**
         * 从下面几行代码我们可以知道,Spring 往往很 "智能" 就是因为它会帮我们默认注册一些有用的 bean,
         * 我们也可以选择覆盖
         */
        // 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }

        // 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        // 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

【4. bean工厂后置操作】postProcessBeanFactory(beanFactory);

此处为空方法,如果子类需要,自己去实现

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

【5. 调用bean工厂后置处理器】invokeBeanFactoryPostProcessors(beanFactory);

方法概述

  • 该方法会 实例化 和 调用 所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor)。
  • BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

image-20211013172617434

  • BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

实例演示

1.BeanDefinitionRegistryPostProcessor 的扩展使用

使用方法比较简单,新建一个类实现 BeanDefinitionRegistryPostProcessor 接口,并将该类注册到 Spring IoC 容器中。

package com.itheima.BeanFactoryPostProcessor;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
 

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry");
        // 自己的逻辑处理
    }
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory");
        // 自己的逻辑处理
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}
2.BeanFactoryPostProcessor 的扩展使用

使用方法跟 BeanDefinitionRegistryPostProcessor 类似。

package com.itheima.BeanFactoryPostProcessor;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor#postProcessBeanFactory");
        // 自己的逻辑处理
    }
}

源码剖析

invokeBeanFactoryPostProcessors(beanFactory);
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 1.getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值
    // 2.invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessor
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
 
    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}
    1. 拿到当前应用上下文 beanFactoryPostProcessors 变量中的值,见代码块1详解
    2. 实例化并调用所有已注册的 BeanFactoryPostProcessor,见代码块2详解
代码块1:getBeanFactoryPostProcessors
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}

这边 getBeanFactoryPostProcessors() 会拿到当前应用上下文中已经注册的 BeanFactoryPostProcessor,在默认情况下,this.beanFactoryPostProcessors 是返回空的。

如何添加自定义 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 变量?

在prepareBeanFactory#customizeContext 方法,该方法是 Spring 提供给开发者的一个扩展点,用于自定义应用上下文,并且在 refresh() 方法前就被调用。在这边就可以通过该方法来添加自定义的 BeanFactoryPostProcessor。

简单的实现如下:

1.新建一个 ApplicationContextInitializer 的实现类 SpringApplicationContextInitializer ,并在 initialize 方法中写我们的逻辑。

package com.xc.spring;
 
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
 
public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
 
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor();
        // 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中
        applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor);
        // ...自定义操作
        System.out.println("SpringApplicationContextInitializer#initialize");
    }
}

2.将 SpringApplicationContextInitializer 作为初始化参数 contextInitializerClasses 配置到 web.xml 中。

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>
        com.xc.spring.SpringApplicationContextInitializer
    </param-value>
</context-param>

这样,在启动应用时,FirstBeanDefinitionRegistryPostProcessor 就会被添加到 this.beanFactoryPostProcessors 中。

代码块2:invokeBeanFactoryPostProcessors
public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        // 1. 判断beanFactory是否为BeanDefinitionRegistry
        // beanFactory类型为DefaultListableBeanFactory,DefaultListableBeanFactory实现了BeanDefinitionRegistry,所有为true
        if (beanFactory instanceof BeanDefinitionRegistry) {
            // 类型强转
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            // 声明集合:保存普通的BeanFactoryPostProcessor类型的后置处理器
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            // 声明集合:保存BeanDefinitionRegistryPostProcessor类型的后置处理器
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            // 2.首先遍历处理入参中的BeanFactoryPostProcessor
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    // 2.1 如果是BeanDefinitionRegistryPostProcessor
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    // 2.1.1 执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    // 2.1.2 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
                    registryProcessors.add(registryProcessor);
                }
                else {
                    // 2.2 否则,只是普通的BeanFactoryPostProcessor
                    // 2.2.1 添加到regularPostProcessors集合
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            // 定义集合:用于保存本次要执行的BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 3.调用所有实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors
            // 3.1 找出所有实现了PriorityOrdered接口的Bean的beanName
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            // 3.2 遍历postProcessorNames
            for (String ppName : postProcessorNames) {
                // 3.3 校验是否实现了PriorityOrdered接口
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 3.4 获取ppName对应的bean实例,添加到currentRegistryProcessors
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    // 3.5 将要被执行的加入processedBeans,避免后续重复执行
                    processedBeans.add(ppName);
                }
            }
            // 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
            registryProcessors.addAll(currentRegistryProcessors);
            // 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 3.9 执行完毕后, 清空currentRegistryProcessors
            currentRegistryProcessors.clear();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)
            // 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,
            // 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 校验是否实现了Ordered接口,并且还未执行过
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            // 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                // 5.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    // 5.2 跳过已经执行过的
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        // 5.3 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor,
                        // 因此这边将reiterate赋值为true, 代表需要再循环查找一次
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                // 5.4 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            // 6.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor)
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            // 7.最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // 到这里 , 入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,
        // 下面开始处理容器中的所有BeanFactoryPostProcessor

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!

        // 8.找出所有实现BeanFactoryPostProcessor接口的类
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        // 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        // 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName
        List<String> orderedPostProcessorNames = new ArrayList<>();
        // 用于存放普通BeanFactoryPostProcessor的beanName
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        // 8.1 遍历postProcessorNames, 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开
        for (String ppName : postProcessorNames) {
            // 8.2 跳过已经执行过的
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 8.3 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                // 8.4 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName
                orderedPostProcessorNames.add(ppName);
            }
            else {
                // 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        // 9.首先,调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor
        // 9.1 对priorityOrderedPostProcessors排序
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 9.2 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        // 10.下一步,调用所有实现Ordered接口的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            // 10.1 获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 10.2 对orderedPostProcessors排序
        sortPostProcessors(orderedPostProcessors, beanFactory);
        // 10.3 遍历orderedPostProcessors, 执行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        // 11.调用所有剩下的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            // 11.1 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        // 11.2 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        // 12.清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
        // 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...
        beanFactory.clearMetadataCache();
    }

1.判断 beanFactory 是否为 BeanDefinitionRegistry。beanFactory 是在之前的 obtainFreshBeanFactory 方法构建的,具体代码在:AbstractRefreshableApplicationContext.refreshBeanFactory() 方法,代码如下。

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建一个新的BeanFactory
        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);
    }
}

可以看出,我们构建的 beanFactory 是一个 DefaultListableBeanFactory ,而 DefaultListableBeanFactory 实现了BeanDefinitionRegistry 接口,因此 beanFactory instanceof BeanDefinitionRegistry 结果为 true。

3.4 获取 ppName 对应的 bean 实例,添加到 currentRegistryProcessors 中,准备执行。beanFactory.getBean 方法会触发创建 ppName 对应的 bean 实例对象,创建 bean 实例是 IoC 的另一个核心内容,之后会单独解析,目前暂不深入解析。

3.6 进行排序,该方法在下面也被调用了好几次,见代码块3详解。

代码块3:sortPostProcessors
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) {
        // 1.获取设置的比较器
        comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) {
        // 2.如果没有设置比较器, 则使用默认的OrderComparator
        comparatorToUse = OrderComparator.INSTANCE;
    }
    // 3.使用比较器对postProcessors进行排序
    Collections.sort(postProcessors, comparatorToUse);
}

方法总结

  • 整个 invokeBeanFactoryPostProcessors 方法围绕两个接口,BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,其中 BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor 。
  • BeanDefinitionRegistryPostProcessor 主要用来在常规 BeanFactoryPostProcessor 检测开始之前注册其他 Bean 定义,说的简单点,就是 BeanDefinitionRegistryPostProcessor 具有更高的优先级,执行顺序在 BeanFactoryPostProcessor 之前。
  • 该方法就是完成了实例化并调用了所有的BeanFactoryPostProcessor

【6. 注册Bean后置处理器】registerBeanPostProcessors(beanFactory);

方法描述

方法作用:会注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类注册到 BeanFactory 中。

  • BeanPostProcessor 接口是 Spring 初始化 bean 时对外暴露的扩展点
  • 在所有 bean 实例化时,执行初始化方法前会调用所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法,在执行初始化方法后会调用所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。

注意:在 registerBeanPostProcessors 方法只是注册到 BeanFactory 中,具体调用是在 bean 初始化的时候。

实例演示

新建一个类实现 BeanPostProcessor 接口,并将该类注册到 Spring IoC 容器中。

package com.xc.BeanPostProcessor;
 
import com.itheima.demo.service.UserService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.PriorityOrdered;
 

@Component
public class MyBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {
 
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessBeforeInitialization");
        if (bean instanceof UserService) {
            System.out.println(beanName);
        }
        // 自己的逻辑
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor#postProcessAfterInitialization");
        // 自己的逻辑
        return bean;
    }
 
    @Override
    public int getOrder() {
        return 0;
    }
}

这样,在 Spring 创建 bean 实例时,执行初始化方法前会调用 MyBeanPostProcessor 的 postProcessBeforeInitialization 方法,在执行初始化方法后会调用 MyBeanPostProcessor 的 postProcessAfterInitialization 方法。

源码剖析

registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 1.注册BeanPostProcessor
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

1.注册 BeanPostProcessor,见代码块1详解

代码块1:registerBeanPostProcessors
public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
 
    // 1.找出所有实现BeanPostProcessor接口的类
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
 
    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    // BeanPostProcessor的目标计数
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 2.添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
 
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 3.定义不同的变量用于区分: 实现PriorityOrdered接口的BeanPostProcessor、实现Ordered接口的BeanPostProcessor、普通BeanPostProcessor
    // 3.1 priorityOrderedPostProcessors: 用于存放实现PriorityOrdered接口的BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.2 internalPostProcessors: 用于存放Spring内部的BeanPostProcessor
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
    // 3.3 orderedPostProcessorNames: 用于存放实现Ordered接口的BeanPostProcessor的beanName
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 3.4 nonOrderedPostProcessorNames: 用于存放普通BeanPostProcessor的beanName
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 4.遍历postProcessorNames, 将BeanPostProcessors按3.1 - 3.4定义的变量区分开
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 4.1 如果ppName对应的Bean实例实现了PriorityOrdered接口, 则拿到ppName对应的Bean实例并添加到priorityOrderedPostProcessors
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                // 4.2 如果ppName对应的Bean实例也实现了MergedBeanDefinitionPostProcessor接口,
                // 则将ppName对应的Bean实例添加到internalPostProcessors
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 4.3 如果ppName对应的Bean实例没有实现PriorityOrdered接口, 但是实现了Ordered接口, 则将ppName添加到orderedPostProcessorNames
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 4.4 否则, 将ppName添加到nonOrderedPostProcessorNames
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
 
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 5.首先, 注册实现PriorityOrdered接口的BeanPostProcessors
    // 5.1 对priorityOrderedPostProcessors进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 5.2 注册priorityOrderedPostProcessors
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
 
    // Next, register the BeanPostProcessors that implement Ordered.
    // 6.接下来, 注册实现Ordered接口的BeanPostProcessors
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : orderedPostProcessorNames) {
        // 6.1 拿到ppName对应的BeanPostProcessor实例对象
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        // 6.2 将ppName对应的BeanPostProcessor实例对象添加到orderedPostProcessors, 准备执行注册
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            // 6.3 如果ppName对应的Bean实例也实现了MergedBeanDefinitionPostProcessor接口,
            // 则将ppName对应的Bean实例添加到internalPostProcessors
            internalPostProcessors.add(pp);
        }
    }
    // 6.4 对orderedPostProcessors进行排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 6.5 注册orderedPostProcessors
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
 
    // Now, register all regular BeanPostProcessors.
    // 7.注册所有常规的BeanPostProcessors(过程与6类似)
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
 
    // Finally, re-register all internal BeanPostProcessors.
    // 8.最后, 重新注册所有内部BeanPostProcessors(相当于内部的BeanPostProcessor会被移到处理器链的末尾)
    // 8.1 对internalPostProcessors进行排序
    sortPostProcessors(internalPostProcessors, beanFactory);
    // 8.2注册internalPostProcessors
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
 
    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    // 9.重新注册ApplicationListenerDetector(跟8类似,主要是为了移动到处理器链的末尾)
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

5.2 注册 priorityOrderedPostProcessors,见代码块2详解

代码块2:registerBeanPostProcessors
private static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // 1.遍历postProcessors
    for (BeanPostProcessor postProcessor : postProcessors) {
        // 2.将PostProcessor添加到BeanFactory中的beanPostProcessors缓存
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

2.将 PostProcessor 添加到 BeanFactory 中的 beanPostProcessors 缓存,见代码块3详解

代码块3beanFactory.addBeanPostProcessor
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // 1.如果beanPostProcessor已经存在则移除(可以起到排序的效果,beanPostProcessor可能本来在前面,移除再添加,则变到最后面)
    this.beanPostProcessors.remove(beanPostProcessor);
    // 2.将beanPostProcessor添加到beanPostProcessors缓存
    this.beanPostProcessors.add(beanPostProcessor);
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        // 3.如果beanPostProcessor是InstantiationAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过InstantiationAwareBeanPostProcessors
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        // 4.如果beanPostProcessor是DestructionAwareBeanPostProcessor, 则将hasInstantiationAwareBeanPostProcessors设置为true,
        // 该变量用于指示beanFactory是否已注册过DestructionAwareBeanPostProcessor
        this.hasDestructionAwareBeanPostProcessors = true;
    }
}

该方法作用就是将 BeanPostProcessor 添加到 beanPostProcessors 缓存,这边的先移除再添加,主要是起一个排序的作用。

而 hasInstantiationAwareBeanPostProcessors 和 hasDestructionAwareBeanPostProcessors 变量用于指示 beanFactory 是否已注册过 InstantiationAwareBeanPostProcessors 和 DestructionAwareBeanPostProcessor,在之后的 IoC 创建过程会用到这两个变量,这边先有个印象。

方法总结

  • 1.整个 registerBeanPostProcessors 方法围绕 BeanPostProcessor 接口展开, 将 BeanPostProcessor 实现类注册到 BeanFactory 的 beanPostProcessors 缓存中(注意:只注册,不调用,还未到调用时机)
  • 2.BeanPostProcessor 实现类具体的 “出场时机” 在创建 bean 实例时,执行初始化方法前后。postProcessBeforeInitialization 方法在执行初始化方法前被调用,postProcessAfterInitialization 方法在执行初始化方法后被调用。
  • 3.BeanPostProcessor 实现类和 BeanFactoryPostProcessor 实现类一样,也可以通过实现 PriorityOrdered、Ordered 接口来调整自己的优先级。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值