Spring源码分析之IoC(二)

栏目: Java · 发布时间: 6年前

内容简介:上篇文章讲了setConfigLocations方法,本篇继续往下分析refresh方法。该方法实现在其父类AbstractApplicationContext中,我们进入该方法看下具体实现:

上篇文章讲了setConfigLocations方法,本篇继续往下分析refresh方法。该方法实现在其父类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) {
            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();
        }
    }
}
复制代码

首先会执行prepareRefresh方法,该方法为刷新上下文做准备,进入该方法:

protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.active.set(true);
    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }
    // Initialize any placeholder property sources in the context environment
    initPropertySources();
    // Validate that all properties marked as required are resolvable
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();
    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
复制代码

该方法首先会设置开始刷新时间startupDate、活动标志active,然后执行initPropertySources方法初始化属性源,进入initPropertySources方法看下:

protected void initPropertySources() {
    // For subclasses: do nothing by default.
}
复制代码

该方法是个空方法,子类可以重写该方法,达到扩展目的。

然后,会执行validateRequiredProperties方法:

public void validateRequiredProperties() throws MissingRequiredPropertiesException {
    this.propertyResolver.validateRequiredProperties();
}
复制代码
public void validateRequiredProperties() {
    MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
    for (String key : this.requiredProperties) {
        if (this.getProperty(key) == null) {
            ex.addMissingRequiredProperty(key);
        }
    }
    if (!ex.getMissingRequiredProperties().isEmpty()) {
        throw ex;
    }
}
复制代码

该方法会校验系统环境中设置的RequiredProperties属性是否为空,如果为空则抛出异常。比如说我们设置了属性值aaa:getEnvironment().setRequiredProperties(“aaa”),但是在系统环境中没有该属性则会抛异常。例子:

public class MyApplicationContext extends AbstractXmlApplicationContext {
    public MyApplicationContext () {
        getEnvironment().setRequiredProperties("aaa");
        refresh();
    }
}
复制代码
@Test
public void testMyApplicationContext() {
    ApplicationContext applicationContext = new MyApplicationContext();
}
复制代码

此时,启动就会报错:

org.springframework.core.env.MissingRequiredPropertiesException: The following properties were declared as required but could not be resolved: [aaa]
复制代码

我们在系统环境中设置该属性,就不会抛出该异常:

@Test
public void testMyApplicationContext() {
    Properties properties = System.getProperties();
    properties.setProperty("aaa", "bbb");
    ApplicationContext applicationContext = new MyApplicationContext();
}
复制代码

prepareRefresh方法最后创建一个 LinkedHashSet<ApplicationEvent> ,并赋值给earlyApplicationEvents,到此prepareRefresh方法就结束了。

如果读完觉得有收获的话,欢迎点赞、关注、加公众号【Java在线】,查阅更多精彩历史!!!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

领域驱动设计

领域驱动设计

[美] Eric Evans / 赵俐、盛海艳、刘霞 / 人民邮电出版社 / 2016-6-1 / 69

本书是领域驱动设计方面的经典之作,修订版更是对之前出版的中文版进行了全面的修订和完善。 全书围绕着设计和开发实践,结合若干真实的项目案例,向读者阐述如何在真实的软件开发中应用领域驱动设计。书中给出了领域驱动设计的系统化方法,并将人们普遍接受的一些实践综合到一起,融入了作者的见解和经验,展现了一些可扩展的设计新实践、已验证过的技术以及便于应对复杂领域的软件项目开发的基本原则。一起来看看 《领域驱动设计》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具