spring-boot源码解析-启动及自动配置篇

首先放一张接口设计图:


spring-boot 启动分析

SpringApplication.run(BlogApplication.class, args);

\1/

跟踪到

private void initialize(Object[] sources) {

    if(sources != null && sources.length > 0) {

        this.sources.addAll(Arrays.asList(sources));

    }

    this.webEnvironment = this.deduceWebEnvironment();

//加载所有jar中spring-factories下的所有工厂

    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

    this.mainApplicationClass = this.deduceMainApplicationClass();

}


public static List loadFactoryNames(Class factoryClass, ClassLoader classLoader) {

    String factoryClassName = factoryClass.getName();

    try {

        Enumeration urls = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");

        ArrayList result = new ArrayList();

        while(urls.hasMoreElements()) {

            URL url = (URL)urls.nextElement();

            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));

            String factoryClassNames = properties.getProperty(factoryClassName);//加载所有工厂

            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

        }

        return result;

    } catch (IOException var8) {

        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);

    }

}

这些工厂对应实现了不同的工厂类

private Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object... args) {

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));

    List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);

    AnnotationAwareOrderComparator.sort(instances);

    return instances;

}

* e.g 需要实例化的工厂


实例化所有工厂并排序

private void initialize(Object[] sources) {

    if(sources != null && sources.length > 0) {

        this.sources.addAll(Arrays.asList(sources));

    }

    this.webEnvironment = this.deduceWebEnvironment();

    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

    this.mainApplicationClass = this.deduceMainApplicationClass();

}

接下来为每个工厂设置监听

private Class deduceMainApplicationClass() {

    try {

        StackTraceElement[] stackTrace = (new RuntimeException()).getStackTrace();

        StackTraceElement[] var2 = stackTrace;

        int var3 = stackTrace.length;

        for(int var4 = 0; var4 < var3; ++var4) {

            StackTraceElement stackTraceElement = var2[var4];

            if("main".equals(stackTraceElement.getMethodName())) {

                return Class.forName(stackTraceElement.getClassName());

            }

        }

    } catch (ClassNotFoundException var6) {

        ;

    }

    return null;

}

设置异常处理栈

SpringApplication设置并初始化完毕,接下来看下它的run方法

public ConfigurableApplicationContext run(String... args) {

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();

    ConfigurableApplicationContext context = null;

    FailureAnalyzers analyzers = null;

    this.configureHeadlessProperty();

    SpringApplicationRunListeners listeners = this.getRunListeners(args);//加载刚才所有 //SpringApplicationRunListener listener实例并启动

    listeners.starting();

    try {

        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

        Banner printedBanner = this.printBanner(environment);

        context = this.createApplicationContext();

        new FailureAnalyzers(context);

        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

        this.refreshContext(context);

        this.afterRefresh(context, applicationArguments);

        listeners.finished(context, (Throwable)null);

        stopWatch.stop();

        if(this.logStartupInfo) {

            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);

        }

        return context;

    } catch (Throwable var9) {

        this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);

        throw new IllegalStateException(var9);

    }

}

看下listener.start方法在干什么:


依次执行以上构造方法

public void starting() {

    this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));

}

public void multicastEvent(ApplicationEvent event) {

    this.multicastEvent(event, this.resolveDefaultEventType(event));

}

遍历所有观察者,发布事件

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {

    ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);

    Iterator var4 = this.getApplicationListeners(event, type).iterator();

    while(var4.hasNext()) {

        final ApplicationListener listener = (ApplicationListener)var4.next();

        Executor executor = this.getTaskExecutor();

        if(executor != null) {

            executor.execute(new Runnable() {

                public void run() {

                    SimpleApplicationEventMulticaster.this.invokeListener(listener, event);

                }

            });

        } else {

            this.invokeListener(listener, event);

        }

    }

}

//发布事件,spring启动啦,各部门该干啥干啥去啦

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {

    ErrorHandler errorHandler = this.getErrorHandler();

    if(errorHandler != null) {

        try {

            listener.onApplicationEvent(event);

        } catch (Throwable var7) {

            errorHandler.handleError(var7);

        }

    } else {

        try {

            listener.onApplicationEvent(event);

        } catch (ClassCastException var8) {

            String msg = var8.getMessage();

            if(msg != null && !msg.startsWith(event.getClass().getName())) {

                throw var8;

            }

            Log logger = LogFactory.getLog(this.getClass());

            if(logger.isDebugEnabled()) {

                logger.debug("Non-matching event type for listener: " + listener, var8);

            }

        }

    }

}

//接着发布spring准备好了启动事件

ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);

//打印logo,初始化各个上下文

context = this.createApplicationContext();

new FailureAnalyzers(context);

this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);

this.refreshContext(context);

this.afterRefresh(context, applicationArguments);

listeners.finished(context, (Throwable)null);

stopWatch.stop();

//stopWatch监听启动用时

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容