读spring源码__IOC

读spring源码__IOC

上一张中提到的initWebApplicationContext方法中configureAndRefreshWebApplicationContext方法是用来进行WebApplicationContext的配置工作,其中包括把servletContext和Spring容器关联起来,以及将配置文件(applicationContext.xml)加入到容器中。将配置文件加载,容器初始化结束后,下面看看ContextLoader的configureAndRefreshWebApplicationContext方法的实现:


protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
            // The application context id is still set to its original default value
            // -> assign a more useful id based on available information
            String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
            if (idParam != null) {
                wac.setId(idParam);//将contextId的值设置到容器中
            }
            else {
                // Generate default id...
                if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
                    // Servlet <= 2.4: resort to name specified in web.xml, if any.
                    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                            ObjectUtils.getDisplayString(sc.getServletContextName()));
                }
                else {
                    wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                            ObjectUtils.getDisplayString(sc.getContextPath()));
                }
            }
        }

        wac.setServletContext(sc);//将上下文环境servletcontext设置到容器中
        String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
        if (initParameter != null) {
            wac.setConfigLocation(initParameter);//将xml配置文件的路径设置到容器中
        }
        customizeContext(sc, wac);
        wac.refresh();//在这个方法中完成了配置文件的加载
    }

wac.refresh()方法完成了bean的加载,存储到bean缓冲池中,创建了beanFactory,注册了监听器等。
wac.refresh()的实现如下:

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识  
            prepareRefresh();//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动 

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();//为BeanFactory配置容器特性,例如类加载器、事件处理器等  

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // 为容器的某些子类指定特殊的BeanPost事件处理器  
                postProcessBeanFactory(beanFactory);

                // 调用所有注册的BeanFactoryPostProcessor的Bean  
                invokeBeanFactoryPostProcessors(beanFactory);

                // 为BeanFactory注册BeanPost事件处理器.BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件  
                registerBeanPostProcessors(beanFactory);

                // 初始化信息源,和国际化相关. 
                initMessageSource();

                // 初始化容器事件传播器.  
                initApplicationEventMulticaster();

                // 调用子类的某些特殊Bean初始化方法 
                onRefresh();

                // 为事件传播器注册事件监听器.
                registerListeners();

                // 初始化所有剩余的单态Bean.
                finishBeanFactoryInitialization(beanFactory);

                // 初始化容器的生命周期事件处理器,并发布容器的生命周期事件 
                finishRefresh();
            }

            catch (BeansException ex) {
                // //销毁以创建的单态Bean  
                destroyBeans();

                // 取消refresh操作,重置容器的同步标识. 
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

这个方法中的obtainFreshBeanFactory方法完成了beanfactory的创建,Spring将配置文件的信息放到容器的Bean定义注册表中(即beanDefinationRegistry),但此时bean还没有初始化。实现如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

跟进refreshBeanFactory()方法:

protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();//销毁单例对象
            closeBeanFactory();//关闭beanFactory
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();//创建BeanFactory
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);//通过配置文件加载bean
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

进入loadBeanDefinitions方法:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

直接进入loadBeanDefinitions(beanDefinitionReader)方法中,最终执行下面这个loadBeanDefinitions方法。

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader = getResourceLoader();
        if (resourceLoader == null) {
            throw new BeanDefinitionStoreException(
                    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
        }

        if (resourceLoader instanceof ResourcePatternResolver) {
            // Resource pattern matching available.
            try {
                Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
                int loadCount = loadBeanDefinitions(resources);//在这里加载资源配置文件,返回获取的资源个数
                if (actualResources != null) {
                    for (Resource resource : resources) {
                        actualResources.add(resource);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                }
                return loadCount;
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException(
                        "Could not resolve bean definition resource pattern [" + location + "]", ex);
            }
        }
        else {
            // Can only load single resources by absolute URL.
            Resource resource = resourceLoader.getResource(location);
            int loadCount = loadBeanDefinitions(resource);
            if (actualResources != null) {
                actualResources.add(resource);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
            }
            return loadCount;
        }
    }

继续进入int loadCount = loadBeanDefinitions(resource);中

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
        Assert.notNull(resources, "Resource array must not be null");
        int counter = 0;
        for (Resource resource : resources) {
            counter += loadBeanDefinitions(resource);
        }
        return counter;
    }

返回bean的个数,resource是返回的资源,通过resource读取配置文件的内容
以上都只是将beanDefination信息存入Bean定义注册表中(即beanDefinationRegistry),并没有将bean初始化。而初始化的工作是由InstantiationStrategy实例化,由beanWrapper完成属性填充。

1.2初始化beanfactory

进入AbstractRefreshableApplicationContext.java类的refreshBeanFactory方法中

在这个方法中,先判断是否有容器存在,如果已经有了一个beanfactory存在,先销毁bean,再关闭容器。try中的语句 {

  • 创建beanfactory
  • 设置序列化id
  • 定制化beanFactory
  • 加载beandefinitions
    }
    BeanFactory类体系结构
    BeanFactory 接口位于类结构树的顶端, 它最主要的方法就是getBean(StringbeanName),该方法从容器中返回特定名称的Bean,BeanFactory 的功能通过其他的接口得到不断扩展。

    ListableBeanFactory:该接口定义了访问容器中Bean 基本信息的若干方法,如查看Bean 的个数、获取某一类型Bean 的配置名、查看容器中是否包括某一Bean 等方法;

    HierarchicalBeanFactory:父子级联IoC 容器的接口,子容器可以通过接口方法访问父容器;

    ConfigurableBeanFactory:是一个重要的接口,增强了IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容器初始化后置处理器等方法;

    AutowireCapableBeanFactory:定义了将容器中的Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;

    SingletonBeanRegistry:定义了允许在运行期间向容器注册单实例Bean 的方法;

    BeanDefinitionRegistry:spring 配置文件中每一个节点元素在Spring 容器里都通过一个BeanDefinition 对象表示,它描述了Bean 的配置信息。而BeanDefinitionRegistry 接口提供了向容器手工注册BeanDefinition 对象的方法。
    这里写图片描述
    这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值