1. 程式人生 > >spring源碼之IOC的非核心部分

spring源碼之IOC的非核心部分

構造方法 置配 finish 總結 clas lec lose ica XML

前言

這篇是對IOC的非核心部分進行分析,是除去了初始化和依賴註入的部分進行分析。對於非web應用,我們在使用spring時,我們會new一個上下文,比如常用的new ClassPathXmlApplicaionContext("applicationContext.xml")。

那麽我們就從這句開始進行分析。

概述

源碼分析

  • 從new 開始,這裏我們可以看到,做了下面幾個事情
    • 構造方法委托處理,設置父類上下文,這裏我們可以看到設置為null,即沒有父上下文
    • 設置配置文件路徑,解析設置的路徑放到configLocations中就好
    • 判斷是否需要刷新上下文,這裏refresh=true,所以會刷新上下文
//ClassPathXmlApplicationContext類的方法
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
    this(configLocations, true, null);
}

//ClassPathXmlApplicationContext類的方法
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        
throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } //AbstractRefreshableConfigApplicationContext類的方法 //設置資源文件路徑 public void setConfigLocations(String... locations) { if (locations != null) { Assert.noNullElements(locations,
"Config locations must not be null"); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
  • 總入口,刷新上下文
//AbstractApplicationContext類方法
//刷新上下文,模板模式,我們可以通過實現這個抽象類,實現自己的applicationContext
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //為上下文刷新做準備
        prepareRefresh();

        //獲取bean工廠,完成bean定義的註冊,這裏核心後面分析
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        //對上面創建好的bean工廠做預處理
        prepareBeanFactory(beanFactory);

        try {
            //對bean工廠進行後置處理
            postProcessBeanFactory(beanFactory);

            //調用bean工廠的後置處理器
            invokeBeanFactoryPostProcessors(beanFactory);

            //註冊bean的後置處理器
            registerBeanPostProcessors(beanFactory);

            //初始化消息源
            initMessageSource();

            //初始化事件廣播器
            initApplicationEventMulticaster();

            //初始化一些特殊的bean
            onRefresh();

            //註冊監聽
            registerListeners();

            //初始化所有非懶加載的單例
            finishBeanFactoryInitialization(beanFactory);

            //發布合適的事件
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            //銷毀單例bean
            destroyBeans();

            //取消刷新
            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();
        }
    }
}
  • 為上下文刷新做準備,這裏主要做了幾件事件
    • 設置容器處理激活狀態
    • 初始和校驗屬性源,在spring mvc的AbstractRefreshableWebApplicationContext有到
    • 初始一個早期事件的空鏈表  
//AbstractApplicationContext類的方法
//為上下文刷新做準備
protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    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>();
}
  • 獲取bean工廠

  核心後面進行分析

  • bean工廠的預處理

總結

Aware接口的很簡單,但很實用

參考鏈接

https://www.cnblogs.com/niejunlei/archive/2016/11/11/6054713.html(prepareBeanFactory)

spring源碼之IOC的非核心部分