欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

Spring源码阐明:非懒加载的单例Bean初始化前后的一些操纵

点击: 次  来源:宝鼎软件 时间:2017-06-01

原文出处: 五月的仓颉

前言

之前两篇文章Spring源码分析:非懒加载的单例Bean初始化过程(上)和Spring源码分析:非懒加载的单例Bean初始化过程(下)比较详细地分析了非懒加载的单例Bean的初始化过程,整个流程始于AbstractApplicationContext的refresh()方法:

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.
            destroyBeans();

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

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

之前重点分析的是finishBeanFactoryInitialization方法,这个方法完成了所有非懒加载的单例Bean的初始化。今天我回头重看了一下refresh()方法,发现前面有一些方法还是忽略了没有去特别在意,其实他们都是Spring整个启动流程中的重要组成部分,下面就来分析一下finishBeanFactoryInitialization方法前面的一些方法。

obtainFreshBeanFactory方法之前已经详细分析过了,就从prepareBeanFactory方法开始。

PrepareBeanFactory方法

看一下PrepareBeanFactory方法的实现:

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        Map systemProperties;
        try {
            systemProperties = System.getProperties();
        }
        catch (AccessControlException ex) {
            systemProperties = new ReadOnlySystemAttributesMap() {
                @Override
                protected String getSystemAttribute(String propertyName) {
                    try {
                        return System.getProperty(propertyName);
                    }
                    catch (AccessControlException ex) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
                                    ex.getMessage());
                        }
                        return null;
                    }
                }
            };
        }
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
    }

    if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        Map<String,String> systemEnvironment;
        try {
            systemEnvironment = System.getenv();
        }
        catch (AccessControlException ex) {
            systemEnvironment = new ReadOnlySystemAttributesMap() {
                @Override
                protected String getSystemAttribute(String variableName) {
                    try {
                        return System.getenv(variableName);
                    }
                    catch (AccessControlException ex) {
                        if (logger.isInfoEnabled()) {
                            logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
                                    ex.getMessage());
                        }
                        return null;
                    }
                }
            };
        }
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
    }
}

首先是第3行,配置当前上下文ClassLoader

接着是第4行,这是一个表达是语言处理器,可以使用#{bean.xxx}的方式来调用相关属性值

接着是第5行,这是一个属性编辑器,具体没怎么用过