博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring源码分析之Bean的加载流程
阅读量:6093 次
发布时间:2019-06-20

本文共 8744 字,大约阅读时间需要 29 分钟。

spring版本为4.3.6.RELEASE

不管是xml方式配置bean还是基于注解的形式,最终都会调用AbstractApplicationContext的refresh方法:

@Overridepublic void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        // Prepare this context for refreshing.        prepareRefresh();        // Tell the subclass to refresh the internal bean factory.        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        // Prepare the bean factory for use in this context.        prepareBeanFactory(beanFactory);        try {            // Allows post-processing of the bean factory in context subclasses.            postProcessBeanFactory(beanFactory);            // Invoke factory processors registered as beans in the context.            invokeBeanFactoryPostProcessors(beanFactory);            // Register bean processors that intercept bean creation.            registerBeanPostProcessors(beanFactory);            // Initialize message source for this context.            initMessageSource();            // Initialize event multicaster for this context.            initApplicationEventMulticaster();            // Initialize other special beans in specific context subclasses.            onRefresh();            // Check for listener beans and register them.            registerListeners();            // Instantiate all remaining (non-lazy-init) singletons.            finishBeanFactoryInitialization(beanFactory);            // Last step: publish corresponding event.            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();        }    }}

1、prepareRefresh();

刷新的准备工作,记录容器启动的时间,并设置容器处于活跃状态。

2、ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

刷新并获取beanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {    refreshBeanFactory();    ConfigurableListableBeanFactory beanFactory = getBeanFactory();    if (logger.isDebugEnabled()) {        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);    }    return beanFactory;}protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;@Overridepublic abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

这个refreshBeanFactory(),getBeanFactory()由子类AbstractRefreshableApplicationContext来实现:

@Overrideprotected final void refreshBeanFactory() throws BeansException {    if (hasBeanFactory()) {        destroyBeans();        closeBeanFactory();    }    try {        DefaultListableBeanFactory beanFactory = createBeanFactory();        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);    }}

关键的一个类出来了:

DefaultListableBeanFactory beanFactory = createBeanFactory();

protected DefaultListableBeanFactory createBeanFactory() {    return new DefaultListableBeanFactory(getInternalParentBeanFactory());}

在DefaultListableBeanFactory中有了很多实例变量,其中大多是集合形式,用来保存一些必要的对象。

/** Map of bean definition objects, keyed by bean name */private final Map
beanDefinitionMap = new ConcurrentHashMap
(256);

存储Bean名称–>Bean定义映射关系

/** Map of singleton and non-singleton bean names, keyed by dependency type */private final Map
, String[]> allBeanNamesByType = new ConcurrentHashMap
, String[]>(64);/** Map of singleton-only bean names, keyed by dependency type */private final Map
, String[]> singletonBeanNamesByType = new ConcurrentHashMap
, String[]>(64);

所有单例和非单例类型和bean的名字数组映射关系

/** List of bean definition names, in registration order */private volatile List
beanDefinitionNames = new ArrayList
(256);

所有的Bean definition name的集合

直接看AbstractXmlApplicationContext的loadBeanDefinitions

@Overrideprotected 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(beanDefin   itionReader);}

创建bean的解析类:XmlBeanDefinitionReader,将bean的解析工作,交给给BeanDefinitionReader处理。

->XmlBeanDefinitionReader.loadBeanDefinitions(EncodedResource encodedResource)

->XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource)

->XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource)

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;}

使用DefaultBeanDefinitionDocumentReader来读取并注册beanDefinition:

->DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)

protected void doRegisterBeanDefinitions(Element root) {        BeanDefinitionParserDelegate parent = this.delegate;        this.delegate = createDelegate(getReaderContext(), root, parent);        if (this.delegate.isDefaultNamespace(root)) {            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);            if (StringUtils.hasText(profileSpec)) {                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {                    if (logger.isInfoEnabled()) {                        logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +                                "] not matching: " + getReaderContext().getResource());                    }                    return;                }            }        }        preProcessXml(root);        parseBeanDefinitions(root, this.delegate);        postProcessXml(root);        this.delegate = parent;    }

->DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

->DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);    if (bdHolder != null) {        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);        try {            // Register the final decorated instance.            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));    }}

-> BeanDefinitionParserDelegate的parseBeanDefinitionElement方法来解析。

看到这里总算和可见的的配置文件对上了,BeanDefinitionParserDelegate会处理 命名空间下元素及其属性。

这里会将beanName赋值为配置文件中的id,最终将返回一个new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);

转载于:https://www.cnblogs.com/lucare/p/9312651.html

你可能感兴趣的文章
并行程序设计学习心得1——并行计算机存储
查看>>
mysql练习题40道
查看>>
JAVA入门到精通-第86讲-半双工/全双工
查看>>
bulk
查看>>
js document.activeElement 获得焦点的元素
查看>>
abb画学号
查看>>
C++ 迭代器运算
查看>>
【支持iOS11】UITableView左滑删除自定义 - 实现多选项并使用自定义图片
查看>>
day6-if,while,for的快速掌握
查看>>
JavaWeb学习笔记(十四)--JSP语法
查看>>
【算法笔记】多线程斐波那契数列
查看>>
Ajax使用进阶
查看>>
Jquery元素选取、常用方法
查看>>
C语言下的错误处理的问题
查看>>
Java中解析XML的方法
查看>>
条目六《当心C++编译器中最烦人的分析机制》
查看>>
servlet的简单定义
查看>>
laravel sql复杂语句,原生写法----连表分组
查看>>
webstorm中github的配置
查看>>
老妈-养生
查看>>