Spring Ioc容器的加载流程是怎样的?加载过程详解

KLQ 2020-06-29 15:10:38 java常见问答 3554

很多人表示,在说到Spring Ioc容器的加载过程的时候都不是很清楚,那么具体的加载过程到底是怎样的呢?一起通过下文来了解一下吧。

Spring Ioc容器加载流程

1、Resource定位-容器寻找数据的过程;

2、载入-将用户定义好的bean表示成IOC容器内部的数据结构,也就是BeanDefinition;

3、注册-将载入的BeanDefinition注册到IOC容器;

通过下面的图片内容再来详细的了解一下。

Spring Ioc容器的加载流程

1、创建Ioc配置文件的抽象资源,这个抽象资源就包括了BeanDefinition的定义信息;

2、创建一个BeanFactory,这里使用DefaultListableBeanFactory;

3、创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory;

4、从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成;

完成了整个载入以及注册Bean定义之后,需要的IOC容器就建立起来了,那么这个时候,就可以直接的使用IOC容器了;

bean.xml

容器启动入口

refresh()方法

载入BeanDefinition入口

定位resource

载入BeanDefinition的核心实现

向IOC容器注册

public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException
{
    super(parent);
    this.setConfigLocations(configLocations);
    if (refresh)
    {
        this.refresh();
    }
}
 public void refresh() throws BeansException, IllegalStateException
 {
     Object var1 = this.startupShutdownMonitor;
     synchronized(this.startupShutdownMonitor)
     {
         this.prepareRefresh();
         //这里在子类中启动refreshBeanFactory 的地方
         ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
         this.prepareBeanFactory(beanFactory);
         try
         {
             // 设置beanFactory的后置处理
             this.postProcessBeanFactory(beanFactory);
             //bean注册容器
             this.invokeBeanFactoryPostProcessors(beanFactory);
             //注册bean的后处理,在bean创建过程中调用
             this.registerBeanPostProcessors(beanFactory);
             //对上下文消息进行初始化
             this.initMessageSource();
             //初始化上线文的事件机制
             this.initApplicationEventMulticaster();
             //初始化其他的特殊的bean
             this.onRefresh();
             //检查监听bean,并向容器注册
             this.registerListeners();
             //实例化所有的(non-lazy-init)单件
             this.finishBeanFactoryInitialization(beanFactory);
             //发布容器时间,结束Refresh过程
             this.finishRefresh();
         }
         catch (BeansException var9)
         {
             if (this.logger.isWarnEnabled())
             {
                 this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
             }
             //为防止容器占用资源,在异常中销毁前面已经生成的单件bean
             this.destroyBeans();
             //重置‘active’标签
             this.cancelRefresh(var9);
             throw var9;
         }
         finally
         {
             this.resetCommonCaches();
         }
     }
 }
//创建 BeanFactory 并载入BeanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
{
    this.refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    if (this.logger.isDebugEnabled())
    {
        this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException
{
    if (this.hasBeanFactory())
    {
        this.destroyBeans();
        this.closeBeanFactory();
    }
    try
    {
        //创建beanFactory
        DefaultListableBeanFactory beanFactory = this.createBeanFactory();
        beanFactory.setSerializationId(this.getId());
        this.customizeBeanFactory(beanFactory);
        //载入bean入口
        this.loadBeanDefinitions(beanFactory);
        Object var2 = this.beanFactoryMonitor;
        synchronized(this.beanFactoryMonitor)
        {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException var5)
    {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
    }
}
//AbstractXmlApplicationContext 
// XmlBeanDefinitionReader 定位resource,XmlBeanDefinitionReader 
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException
{
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    this.initBeanDefinitionReader(beanDefinitionReader);
    this.loadBeanDefinitions(beanDefinitionReader);
}
//IOC 容器加载的核心方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException
{
    try
    {
        InputStream inputStream = encodedResource.getResource()
            .getInputStream();
        try
        {
            //一:读取xml文件
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null)
            {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            //二:加载 beanefinition
            var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally
        {
            inputStream.close();
        }
    }
    return var5;
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException
{
    try
    {
        //一 1) 将xml文件转换为document
        Document doc = this.doLoadDocument(inputSource, resource);
        return this.registerBeanDefinitions(doc, resource);
    }
}
//一 2) 开始执行
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
{
    this.readerContext = readerContext;
    this.logger.debug("Loading bean definitions");
    Element root = doc.getDocumentElement();
    this.doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root)
{
    this.preProcessXml(root);
    //三 解析Element 获取xml内容
    this.parseBeanDefinitions(root, this.delegate);
    this.postProcessXml(root);
    this.delegate = parent;
}
//解析Element 得到node 判断node内容
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))
                {
                    //读取document的内容
                    this.parseDefaultElement(ele, delegate);
                }
                else
                {
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else
    {
        delegate.parseCustomElement(root);
    }
}
//四 判断xml中(document中节点的类型)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
{
    if (delegate.nodeNameEquals(ele, "import"))
    {
        this.importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, "alias"))
    {
        this.processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, "bean"))
    {
        /* 五 载入beanDefinition  这里只是读取<bean>中的设置的class的name, 然后载入到BeanDefinition中,只是做个记录,并不设计对象的实例化,对象的实例化是在依赖注入时完成的*/
        this.processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, "beans"))
    {
        this.doRegisterBeanDefinitions(ele);
    }
}
//五 载入BeanDefinition 这里得到documentReader后,为具体的spring bean 解析准备了数据 
protected void processBeanDefinition(Element ele, eanDefinitionParserDelegate delegate)
{
    //具体处理了BeanDefinition交给 BeanDefinitionParserDelegate
    /* 具体将<bean>的内容进行解析,解析为spring 的BeanDefinition
           BeanDefinitionHolder是BeanDefinition对象的封装,封装了bean的名称和别 
      名,用他来完成   向IOC容器注册,得到的BeanDefinitionHolder是通过beanDefinitionParserDelegate 对 XML的元素的信息按照spring 的bean规则进行解析得到的*/
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null)
    {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try
        {
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext()
                .getRegistry());
        }
        catch (BeanDefinitionStoreException var5)
        {
            this.getReaderContext()
                .error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
        }
        // BeanDefinition向IOC容器注册之后,发送消息
        this.getReaderContext()
            .fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}
//载入BeanDefinition 
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)
{
    String id = ele.getAttribute("id");
    String nameAttr = ele.getAttribute("name");
    List < String > aliases = new ArrayList();
    if (StringUtils.hasLength(nameAttr))
    {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
        aliases.addAll(Arrays.asList(nameArr));
    }
    String beanName = id;
    if (!StringUtils.hasText(id) && !aliases.isEmpty())
    {
        beanName = (String) aliases.remove(0);
        if (this.logger.isDebugEnabled())
        {
            this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
        }
    }
    if (containingBean == null)
    {
        this.checkNameUniqueness(beanName, aliases, ele);
    }
    //将xml的内置转换为spring的bean信息
    AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
}
//对<bean>的内容进行解析,转换为spring的bean
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean)
{
    this.parseState.push(new BeanEntry(beanName));
    String className = null;
    if (ele.hasAttribute("class"))
    {
        className = ele.getAttribute("class")
            .trim();
    }
    String parent = null;
    if (ele.hasAttribute("parent"))
    {
        parent = ele.getAttribute("parent");
    }
    try
    {
        //生成需要的BeanDefinition对象,为BeanDefinition的载入做准备
        AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
        //设置<bean>的attribute scope,init,destory 等
        this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
        //设置元数据 如 key ,value这样的
        this.parseMetaElements(ele, bd);
        this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        //解析<bean>构造函数 
        this.parseConstructorArgElements(ele, bd);
        //设置<bean>property元素
        this.parsePropertyElements(ele, bd);
        this.parseQualifierElements(ele, bd);
        bd.setResource(this.readerContext.getResource());
        bd.setSource(this.extractSource(ele));
        AbstractBeanDefinition var7 = bd;
        return var7;
    }
}
finally
{
    this.parseState.pop();
}
return null;
}
/注册 BeanDefinition
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException
{
    //获取bean的 名称
    String beanName = definitionHolder.getBeanName();
    //注册bean 并将bean放入到ioc容器里面 
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null)
    {
        String[] var4 = aliases;
        int var5 = aliases.length;
        for (int var6 = 0; var6 < var5; ++var6)
        {
            String alias = var4[var6];
            //注册其他信息 是否是单例,是否允许重载 是否是abstract 类
            registry.registerAlias(beanName, alias);
        }
    }
}
//DefaultListableBeanFactory 具体执行注册的
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException
{
    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 var9)
        {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
        }
    }
    //bean 已经存在
    BeanDefinition existingDefinition = (BeanDefinition) this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null)
    {
        //不允许覆盖 报异常
        if (!this.isAllowBeanDefinitionOverriding())
        {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + existingDefinition + "] bound.");
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else
    {
        if (this.hasBeanCreationStarted())
        {
            Map var4 = this.beanDefinitionMap;
            //synchronized,保证数据一致性
            synchronized(this.beanDefinitionMap)
            {
                //将bean放入容器
                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
        {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            this.manualSingletonNames.remove(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
    if (existingDefinition != null || this.containsSingleton(beanName))
    {
        this.resetBeanDefinition(beanName);
    }
}

Spring Ioc容器的加载流程你都了解了吗?更多和Spring Ioc容器相关的常见问题,可以继续关注奇Q工具网来了解哦。

推荐阅读:

spring ioc容器是什么?有什么作用?

spring ioc注入方式有几种?该怎么实现?

spring ioc应用场景都有哪些?要如何配置?