SpringBoot 启动方法run()源码解析

入口

通常一个简单的SpringBoot基础项目我们会有如下代码

@SpringBootApplication@RestController@RequestMapping("/")public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

值得关注的有SpringApplication.run以及注解@SpringBootApplication

run方法

public ConfigurableApplicationContext run(String... args) { // 秒表StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();// 获取监听器SpringApplicationRunListeners listeners = getRunListeners(args);// 监听器启动listeners.starting();try { // application 启动参数列表ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 配置忽略的bean信息configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);// 创建应用上下文context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context); // 准备上下文,装配beanprepareContext(context, environment, listeners, applicationArguments, printedBanner);// 上下文刷新refreshContext(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;}

getRunListeners

获取监听器

private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };// 获取 Spring Factory 实例对象return new SpringApplicationRunListeners(logger,getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates// 读取 spring.factoriesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 创建SpringFactory实例List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);/** * 排序 {@link Ordered} */AnnotationAwareOrderComparator.sort(instances);return instances;}
createSpringFactoriesInstances
 @SuppressWarnings("unchecked") private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { // 初始化 List<T> instances = new ArrayList<>(names.size()); for (String name : names) { try {  // 通过名字创建类的class对象 Class<?> instanceClass = ClassUtils.forName(name, classLoader); Assert.isAssignable(type, instanceClass); // 构造器获取 Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes); // 创建具体实例 T instance = (T) BeanUtils.instantiateClass(constructor, args); // 加入实例表中 instances.add(instance); } catch (Throwable ex) { throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex); } } return instances; }

printBanner

private Banner printBanner(ConfigurableEnvironment environment) {if (this.bannerMode == Banner.Mode.OFF) {return null;}ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(getClassLoader());// 创建打印器SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);if (this.bannerMode == Mode.LOG) { // 输出return bannerPrinter.print(environment, this.mainApplicationClass, logger);} // 输出return bannerPrinter.print(environment, this.mainApplicationClass, System.out);}Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {Banner banner = getBanner(environment);banner.printBanner(environment, sourceClass, out);return new PrintedBanner(banner, sourceClass);}

最终输出内容类:org.springframework.boot.SpringBootBanner

class SpringBootBanner implements Banner {private static final String[] BANNER = { "", " . ____  _  __ _ _"," /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\"," \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", " ' |____| .__|_| |_|_| |_\\__, | / / / /"," =========|_|==============|___/=/_/_/_/" };private static final String SPRING_BOOT = " :: Spring Boot :: ";private static final int STRAP_LINE_SIZE = 42;@Overridepublic void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {for (String line : BANNER) {printStream.println(line);}String version = SpringBootVersion.getVersion();version = (version != null) ? " (v" + version + ")" : "";StringBuilder padding = new StringBuilder();while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {padding.append(" ");}printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),AnsiStyle.FAINT, version));printStream.println();}}

希望通过本篇对于springboot启动方法的解读,让大家对springboot底层有了一个大致了解,只分析了主要方法,希望对大家有帮助

到此这篇关于SpringBoot 启动方法run()源码赏析的文章就介绍到这了,更多相关SpringBoot 启动run()内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

最好的节约是珍惜时间,最大的浪费是虚度年华。

SpringBoot 启动方法run()源码解析

相关文章:

你感兴趣的文章:

标签云: