我们现在经常使用的beanFactory有两种,一种是xml方式的, 另一种是注解方式的. 其实使用注解的更多一些. xml和注解方式的bean工厂在初始化的时候也是有区别的.
    08-Spring源码refresh-obtainFreshBeanFactory - 图1
    从上图可以看出, 获取两种方式的bean工厂的区别

    1. AbstractRefreshableApplicationContext: 基于xml配置文件的方式
      1. GenericApplicationContext: 基于注解的方式. 基于注解实现的里面代码很简单, 只是刷新的beanFactory. 没有耦合加载beanDefinition的流程. 基于xml实现的代码, 里面耦合了加载beanDefinition
    1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    2. /**
    3. * 刷新bean工厂,判断bean工厂是否已经存在,如果存在需要进行销毁和关闭
    4. * 默认调用的是AbstractRefreshableApplicationContext的refreshBeanFactory方法.
    5. * 刷新Bean工厂时会进行bean定义的加载操作。
    6. */
    7. refreshBeanFactory();
    8. return getBeanFactory();
    9. }

    刷新bean工厂,判断bean工厂是否已经存在,如果存在需要进行销毁和关闭,我们接着继续往下看。先来看看基于注解方式的, 基于注解方式只是指定了bean工厂的序列化ID

    1. @Override
    2. protected final void refreshBeanFactory() throws IllegalStateException {
    3. if (!this.refreshed.compareAndSet(false, true)) {
    4. throw new IllegalStateException(
    5. "GenericApplicationContext does not support multiple refresh attempts:                 just call 'refresh' once");
    6. }
    7. // 指定bean工厂的序列化ID
    8. this.beanFactory.setSerializationId(getId());
    9. }

    再来看看基于xml方式的, 基于xml方式的 除了指定了bean工厂的序列化id, 还耦合加载了beanDefinition

    1. @Override
    2. protected final void refreshBeanFactory() throws BeansException {
    3. // 判断bean工厂是否存在,如果存在需要先销毁和关闭。否则会出现问题
    4. if (hasBeanFactory()) {
    5. // 销毁bean,根据bean的名称将bean工厂中的所有bean都从map中移除
    6. destroyBeans();
    7. // 关闭bean工厂,设置Bean工厂的序列化id为null,并将beanFactory的值赋值为null
    8. closeBeanFactory();
    9. }
    10. try {
    11. // 重新创建bean工厂,默认返回的是Bean工厂类型是:DefaultListableBeanFactory
    12. DefaultListableBeanFactory beanFactory = createBeanFactory();
    13. // 设置序列化ID,ID: class名称 + "@" + 对象的十六进制值
    14. beanFactory.setSerializationId(getId());
    15. // 定制bean工厂。作用:设置bean定义是否可以被覆盖以及设置bean在创建的时候是否允许循环引用.
    16. customizeBeanFactory(beanFactory);
    17. // 解析并加载bean的定义,默认是通过AbstractXmlApplicationContext类中的loadBeanDefinitions实现
    18. loadBeanDefinitions(beanFactory);
    19. synchronized (this.beanFactoryMonitor) {
    20. this.beanFactory = beanFactory;
    21. }
    22. }
    23. catch (IOException ex) {
    24. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    25. }
    26. }

    refreshBeanFactory一共做了几件事情;

    1. 判断bean工厂是否存在,如果存在需要先销毁和关闭。否则会出现问题;
    2. 重新创建bean工厂,默认返回的是Bean工厂类型是:DefaultListableBeanFactory;
    3. 设置序列化ID,ID: class名称 + “@” + 对象的十六进制值;
    4. 定制bean工厂。作用:设置bean定义是否可以被覆盖以及设置bean在创建的时候是否允许循环引用.
    5. 解析并加载bean的定义,默认是通过AbstractXmlApplicationContext类中的loadBeanDefinitions实现;

      1. <br /> 我们接下来看它是如果创建DefaultListableBeanFactory的。

      ```java // AbstractRefreshableApplicationContext
      protected DefaultListableBeanFactory createBeanFactory() {

      1. return new DefaultListableBeanFactory(getInternalParentBeanFactory());

      }

      // DefaultListableBeanFactory public DefaultListableBeanFactory(@Nullable BeanFactory parentBeanFactory) {

      1. super(parentBeanFactory);

      }

      // AbstractAutowireCapableBeanFactory

      1. public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) {
      2. this();
      3. setParentBeanFactory(parentBeanFactory);

      }

    1. /**
    2. * Create a new AbstractAutowireCapableBeanFactory.
    3. * ignoreDependencyInterface:方法用来在自动装配时自动忽略类或者接口子类的注入.
    4. */
    5. public AbstractAutowireCapableBeanFactory() {
    6. super();
    7. // 在Bean自动装配时自动忽略BeanNameAware子类的注入
    8. ignoreDependencyInterface(BeanNameAware.class);
    9. // 忽略BeanFactoryAware接口子类的注入
    10. ignoreDependencyInterface(BeanFactoryAware.class);
    11. // 忽略BeanClassLoaderAware接口子类的注入
    12. ignoreDependencyInterface(BeanClassLoaderAware.class);
    13. }
    1. 接下来看下customizeBeanFactory是如何定制BeanFactory的。
    2. ```java
    3. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    4. // 是否允许覆盖Bean的定义
    5. if (this.allowBeanDefinitionOverriding != null) {
    6. beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    7. }
    8. // 该属性在解决Spring Bean的循环依赖中会使用到
    9. // 如果该属性的值为true,而且将要初始化的bean为单例,而且正在创建中,则在初始化属性前会把该bean的信息放入到singletonFactories中.
    10. if (this.allowCircularReferences != null) {
    11. beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    12. }
    13. }

    两个属性,allowBeanDefinitionOverriding是否允许覆盖Bean的定义,allowCircularReferences该属性在解决Spring Bean的循环依赖中会使用到。

    1. 接下来我们来看下loadBeanDefinitions,这里loadBeanDefinitions是一个重载方法大家看的时候不要被绕晕了。
    1. @Override
    2. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    3. // 创建Xml格式的Bean读取器,里面会设置bean工厂的资源加载器及环境信息
    4. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    5. // 对象创建bean读取器的时候已经初始化.此处直接获取
    6. beanDefinitionReader.setEnvironment(this.getEnvironment());
    7. // 上述创建时已经初始化,此处直接获取
    8. beanDefinitionReader.setResourceLoader(this);
    9. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    10. // Allow a subclass to provide custom initialization of the reader,
    11. // then proceed with actually loading the bean definitions.
    12. initBeanDefinitionReader(beanDefinitionReader);
    13. // 会解析xml中的标签属性,并添加到bean定义中.
    14. loadBeanDefinitions(beanDefinitionReader);
    15. }

    他首先是创建Xml格式的Bean读取器,里面会设置bean工厂的资源加载器及环境信息,然后对beanDefinitionReader进行一些属性赋值,最后就会解析xml中的标签属性,并添加到bean定义中,我们具体看对应的解析源码;

    1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    2. // 通过另外一个构造函数构造的容器,会使用configResources的方式去加载bean定义
    3. Resource[] configResources = getConfigResources();
    4. if (configResources != null) {
    5. reader.loadBeanDefinitions(configResources);
    6. }
    7. // 获取所有的配置文件名称,例如:{"beans.xml"}。主要是xml配置文件的名称
    8. String[] configLocations = getConfigLocations();
    9. if (configLocations != null) {
    10. reader.loadBeanDefinitions(configLocations);
    11. }
    12. }

    https://blog.csdn.net/jokeMqc/article/details/122299241