服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - SpringBoot 启动方法run()源码解析

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

2021-08-29 12:51码上代码 Java教程

这篇文章主要介绍了SpringBoot 启动方法run()源码赏析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

入口

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

?
1
2
3
4
5
6
7
8
9
10
@SpringBootApplication
@RestController
@RequestMapping("/")
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
}

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

run方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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);
         // 准备上下文,装配bean
            prepareContext(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

获取监听器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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.factories
        Set<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;
    }
?
1
createSpringFactoriesInstances
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
 
    @Override
    public 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()内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_44302240/article/details/110499108

延伸 · 阅读

精彩推荐