Spring源码阅读3

 2019-11-02 21:26  阅读(1104)
文章分类:Spring boot

承接上一篇。

下面是 refush()方法的源代码。这个方法是在AbstractApplicationContext类中实现的,该类为AbstractApplicationContext的子类。

public 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) {
                    // Destroy already created singletons to avoid dangling resources.
                    beanFactory.destroySingletons();

                    // Reset 'active' flag.
                    cancelRefresh(ex);

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

首先来看这个prepareRefresh()方法,顾名思义,这个是用来做做刷新容器前的准备工作。

protected void prepareRefresh() {
            this.startupDate = System.currentTimeMillis();

            synchronized (this.activeMonitor) {
                this.active = true;
            }

            if (logger.isInfoEnabled()) {
                logger.info("Refreshing " + this);
            }
        }

这个方法,先得到了系统时间,然后通过this.activeMonitor来进行同步,这个一个 Object的实例对象,用来进行同步active标志位。
设置active为true,代表当前applicationContext是活动的,查看active的引用点,可以看到所有对 active的操作都是同步在activeMonitor下的,在调用cancelRefresh()和doClose()两个方法的时候会把它设置为false,其中cancelRefresh()代表中止refresh,doClose()则是当前applicationContext的关闭销毁方法。

然后是obtainFreshBeanFactory()的源码,

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            refreshBeanFactory();
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();

            if (logger.isInfoEnabled()) {
                logger.info("Bean factory for application context [" + getId() + "]: " +
                        ObjectUtils.identityToString(beanFactory));
            }
            if (logger.isDebugEnabled()) {
                logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);
            }

            return beanFactory;
        }

``

``

protected final void refreshBeanFactory() throws BeansException {
            if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }
            try {
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                customizeBeanFactory(beanFactory);
                loadBeanDefinitions(beanFactory);
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            }
            catch (IOException ex) {
                throw new ApplicationContextException(
                        "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
            }
        }

这两个方法都是在WebApplicationContext所继承的父类(包括父类的父类)中实现,从这个 refreshBeanFactory的方法中,我们能看到beanFactory的刷新过程。当存在BeanFactory则销毁容器中的beans,并且销毁容器。我们通过观察这两个有关刷新的类,AbstractApplicationContext,以及AbstractRefreshApplicationContext,会发现原来有关控创建销毁beanfactory的方法都在这里进行实现。并且都是通过synchronized (this.beanFactoryMonitor)对beanFactory进行同步。上面的destroyBeans的方法主要由 xmlBeanFactory继承的DefaultListAbleBeanFactory类的destroySingleton方法实现。一定很想知道,spring 到底是这样清空bean的吧。

public void destroySingletons() {
            if (logger.isInfoEnabled()) {
                logger.info("Destroying singletons in " + this);
            }
            synchronized (this.singletonObjects) {
                this.singletonsCurrentlyInDestruction = true;
            }

            synchronized (this.disposableBeans) {
                String[] disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
                for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
                    destroySingleton(disposableBeanNames[i]);
                }
            }

            this.containedBeanMap.clear();
            this.dependentBeanMap.clear();
            this.dependenciesForBeanMap.clear();

            synchronized (this.singletonObjects) {
                this.singletonObjects.clear();
                this.singletonFactories.clear();
                this.earlySingletonObjects.clear();
                this.registeredSingletons.clear();
                this.singletonsCurrentlyInDestruction = false;
            }
        }

上面就是spring销毁容器中的单例的bean的方法。注意,一个spring容器中的bean都是单例的,根据xml配置文件的id唯一,如果配置两个id则为两个不同的实例。好,继续看上面方法,设置了一个用于操作单例对象的同步锁,

singletonObjects

这个对象用于存放beanName和bean实例之间的关系,是一个map。

singletonsCurrentlyInDestruction是一个
标志,指示我们目前在destroysingletons。同理,锁住disposeBeans,再通过她的beanName一个个销毁。接着,我们看到了一个个容器对象的清空,完成后,在改变销毁标志位。这就是一个完整的销毁过程,以此,我们也看到了,spring的主要容器对象。

protected void removeSingleton(String beanName) {
            synchronized (this.singletonObjects) {
                this.singletonObjects.remove(beanName);
                this.singletonFactories.remove(beanName);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.remove(beanName);
            }
        }

以上,我们看到了spring启动之前的清空容器的过程。下面我们来看看beanFactory的创建过程。

DefaultListableBeanFactory beanFactory = createBeanFactory();
                customizeBeanFactory(beanFactory);
                loadBeanDefinitions(beanFactory);
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }

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

protected BeanFactory getInternalParentBeanFactory() {
            return (getParent() instanceof ConfigurableApplicationContext) ?
                    ((ConfigurableApplicationContext) getParent()).getBeanFactory() : (BeanFactory) getParent();
        }

来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring源码阅读3

相关推荐