Spring源码阅读3

  承接上一篇。

下面是 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();
    }

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