SpringBoot启动流程(七)
之前我们看了SpringBoot的Context初始化和加载,下面继续研究启动流程:
前略:
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
接下来调用的是afterRefresh这个方法是个空方法,然后走到下面listeners.started(context);处理各个listener,最后callRunners
这里面重要的就是callRunners,一开始我看这块儿的源码就是因为我的实现CommandLineRunner的类走了两遍,后来发现是有别的类继承了
实现CommandLineRunner 的类导致的.然后才开始研究Springboot的启动流程.
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
*
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class>[] scanBasePackageClasses() default {};
}
这个类同样有很多注解,重要的是@ComponentScan 注解,在parser.parse中会递归的遍历被ComponentScan修饰的类,然后
获取里面的内容,在把内容进行扫描在继续处理.在我们没有写@ComponentScan 注解时,Spring会自动的读取启动类的包名,
并把这个包名当做basePackages从而扫描,注意:当同事有@ComponentScan和启动类时,这两个扫描会同时进行,即会扫描
@ComponentScan 中指明的basePackages和启动类的包名的下的类.获取完之后返回Context,SpringBoot的启动流程就完成了!
结语:这次是我第一次真正意义上独立学习源码知识,Spring设计的精巧是在令人叹服,在阅读代码中难免会有疏漏和错误,如果各位读者
发现请立即指正,我会立即更正,以免误导他人,谢谢大家.