Spring源码解析—第二篇IOC之beanfactory初始化源码解析

1、IOC简介

IOC(Inversion of Control):即”控制反转”,也叫DI(Dependency Injection):DI即依赖注入。

所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。

IoC 容器:最主要是完成了完成对象的创建和依赖的管理注入等等。

对象和对象关系怎么表示?

可以用 xml , properties 文件等语义化配置文件表示。

描述对象关系的文件存放在哪里?

可能是 classpath , filesystem ,或者是 URL 网络资源, servletContext 等。

2、Spring IOC的简单实现

2.1、创建实体类User

package com.vesus.spring.model;

/**
 * @Description:
 * @Author: vesus
 * @CreateDate: 2018/5/31 下午11:44
 * @Version: 1.0
 */
public class User {

    private String id ;

    private String name ;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2.2、创建applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.vesus.spring.model.User" />
</beans>

2.3、新建测试类

package com.vesus.spring.model.test;

import com.vesus.spring.model.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Description:
 * @Author: vesus
 * @CreateDate: 2018/5/31 下午11:48
 * @Version: 1.0
 */
public class Test {

    public static void main(String[] args) {

        BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) beanFactory.getBean("user") ;
        System.err.println(user.getDesc());
    }
}

3、源码分析

3.1、入口类

public ClassPathXmlApplicationContext(
    String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);
        setConfigLocations(configLocations);//设置配置文件位置
        if (refresh) {
            refresh();//主要的加载bean的过程
        }
    }

有源码可以看到最主要的方法集中在refresh()上,下面分析一下refresh的源码。

3.2、refresh()源码分析

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 准备刷新上下文环境
            prepareRefresh();

            //读取xml文件的,初始化beanFactory
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            //准备beanfactory来使用这个上下文.做一些准备工作,例如classloader,beanfactoryPostProcessor等
            prepareBeanFactory(beanFactory);

            try {
                //空方法,供子类使用
                postProcessBeanFactory(beanFactory);

                //开始执行注册到该上下文的BeanFactoryPostProcessors
                invokeBeanFactoryPostProcessors(beanFactory);

                //开始注册BeanPostProcessor来拦截其他的bean的初始化过程
                registerBeanPostProcessors(beanFactory);

                //初始化消息源
                initMessageSource();

                //注册上下文事件的广播集
                initApplicationEventMulticaster();

                //初始化其他上下文中子类中的特殊bean
                onRefresh();

                //注册监听器
                registerListeners();

                //初始化单例
                finishBeanFactoryInitialization(beanFactory);

                //初始化完成
                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();
            }
        }
    }

Refresh 首先进行上下本刷新,然后读取xml文件,并初始化beanfactory。初始化beanfactory源码如下。

3.3、obtainFreshBeanFactory源码解析

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

3.4、refreshBeanFactory源码解析

protected final void refreshBeanFactory() throws BeansException {
        //判断容器是否存在,已经有了一个容器,先销毁里面的bean然后再关闭容器,spring保证只有一个容器
        if (hasBeanFactory()) {
            destroyBeans();//销毁已经存在的bean
            closeBeanFactory();//关闭bean工厂
        }
        try {
            //创建IoC容器
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //对IOC容器进行初始化
            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);
        }
    }

refreshBeanFactory中创建IOC容器,并对容器进行初始化,主要的方法为加载类。

3.5、loadBeanDefinitions源码解析

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        //创建一个XmlBeanDefinitionReader
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        //配置XmlBeanDefinitionReader
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        //初始化beanDefinitionReader
        initBeanDefinitionReader(beanDefinitionReader);
        //加载bean
        loadBeanDefinitions(beanDefinitionReader);
    }

从loadBeanDefinitions的源码中可以看到创建了一个XmlBeanDefinitionReader读取资源文件,加载资源文件中定义的类。继续跟踪loadBeanDefinitions最终找到XmlBeanDefinitionReader.java 中的registerBeanDefinitions

3.6、registerBeanDefinitions源码解析

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

这个方法是返回新加入的beanDefinition的个数,继续跟踪documentReader.registerBeanDefinitions,追踪到主要的方法为parseBeanDefinitions

3.7、parseBeanDefinitions源码解析

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            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)) {
                        //解析xml,获取bean
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

查看解析方法parseDefaultElement。

3.8、parseDefaultElement源码解析

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            //解析节点为bean的节点
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

3.9、processBeanDefinition源码解析

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //解析xml,获取bean
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                //注册bean
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

至此,beanfactory初始化基本完成了。

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/liuweilong07/article/details/80822620
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞