Spring之IOC容器初始化

1.IOC 容器的初始化过程分为三步骤:Resource 定位、BeanDefinition 的载入和解析,BeanDefinition 注册。

IOC容器初始化的简单示例。

ClassPathResource resource = new ClassPathResource("bean.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);

2.Spring 为了解决资源定位的问题,提供了两个接口:Resource、ResourceLoader,其中 Resource 接口是 Spring 统一资源的抽象接口,ResourceLoader 则是 Spring 资源加载的统一抽象。ResourceLoader的初始化是在XmlBeanDefinitionReader构造方法中调用父类AbstractBeanDefinitionReader 的构造器进行初始化。

3.BeanDefinition 的载入的时候,如示例程序,loadBeanDefinitions(resource)会将资源 resource 包装成一个 EncodedResource 实例对象,然后调用 loadBeanDefinitions() 方法,而将 Resource 封装成 EncodedResource 主要是为了对 Resource 进行编码,保证内容读取的正确性。从 encodedResource 源中获取 xml 的解析源,调用 doLoadBeanDefinitions() 执行具体的解析过程。在该方法中主要做两件事:1、根据 xml 解析源获取相应的 Document 对象,2、调用 registerBeanDefinitions() 开启 BeanDefinition 的解析注册过程。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            Document doc = doLoadDocument(inputSource, resource);
            return registerBeanDefinitions(doc, resource);
        }
        // 省略很多catch代码

4.调用 doLoadDocument() 会将 Bean 定义的资源转换为 Document 对象。

5.将资源转换为 Document 对象之后下一步就是将其解析为 Spring IOC 管理的 Bean 对象并将其注册到容器中。这个过程有方法 registerBeanDefinitions() 实现。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
       // 创建 BeanDefinitionDocumentReader 来对 xml 格式的BeanDefinition 解析
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        // 获得容器中注册的Bean数量
        int countBefore = getRegistry().getBeanDefinitionCount();

        // 解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
        // 具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }

6.documentReader.registerBeanDefinitions() 开启解析过程,这里使用的是委派模式,具体的实现由子类 DefaultBeanDefinitionDocumentReader 完成。

7.对 Document 对象的解析,主要是对四大标签:import、alias、bean、beans 进行解析。

8.将 Document 对象里面的 Bean 标签解析成了一个个的 BeanDefinition ,下一步则是将这些 BeanDefinition 注册到 IOC 容器中。动作的触发是在解析 Bean 标签完成后。

@Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {

      // 省略一堆校验

        BeanDefinition oldBeanDefinition;

        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
          // 省略一堆 if
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            if (hasBeanCreationStarted()) {
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }

最核心的部分是这句 this.beanDefinitionMap.put(beanName, beanDefinition),利用一个 Map 的集合对象来存放,key 是 beanName,value 是 BeanDefinition。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值