澳门新葡亰娱乐网站-www.142net-欢迎您

澳门新葡亰娱乐网站是因为你还没有找到一条正确的致富之路,www.142net是将所有的游戏都汇集在一起的官方平台,因为澳门新葡亰娱乐网站这个网站当中有着大量的游戏攻略,托IP定位技术,传达终端直接到达的精准传播方式。

源码分析,boot的初始化工具创建源码

来源:http://www.bhtsgq.com 作者:计算机知识 人气:194 发布时间:2019-05-30
摘要:前⾔ 前⾔ 通过上一章的源码分析,我们通晓了springboot里面的listeners到底是何许(META-INF/spring.factories定义的财富的实例),以及它是创制和起步的,明天我们承接深远分析一下SpringAp

前⾔

前⾔

图片 1

通过上一章的源码分析,我们通晓了spring boot里面的listeners到底是何许(META-INF/spring.factories定义的财富的实例),以及它是创制和起步的,明天我们承接深远分析一下SpringApplication实例变量中的run函数中的其余内容。依然先把run函数的代码贴出来:

我们⽣成⼀个源码分析,boot的初始化工具创建源码。spring boot 项⽬时,会⾃带⼀个运转类. 代码如下:

笔者们⽣成⼀个spring boot 项⽬时,会⾃带⼀个运转类. 代码如下:

    /**
     * Run the Spring application, creating and refreshing a new
     * {@link ApplicationContext}.
     * @param args the application arguments (usually passed from a Java main method)
     * @return a running {@link ApplicationContext}
     */
    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 {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            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;
    }
@SpringBootApplication
public class SpringBootAnalysisApplication {
 public static void main(String[] args) {
 SpringApplication.run(SpringBootAnalysisApplication.class, args);
 }
}
@SpringBootApplicationpublic class SpringBootAnalysisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootAnalysisApplication.class, args); }}

在listeners运转了后头,我们来看一下ApplicationArguments applicationArguments
= new DefaultApplicationArguments(args); 在DefaultApplicationArguments的构造函数里,大家追踪过去察觉其最后调用的SimpleCommandLineArgsParser.parse函数:

就是如此简单的代码,构成了spring boot的世界. 那么代码中只有⼀个@SpringBootApplication 注明 和 调⽤了SpringApplication#run

正是那般轻易的代码,构成了spring boot的世界. 那么代码中唯有⼀个@SpringBootApplication 评释 和 调⽤了SpringApplication#run⽅法.那么我们先来深入分析SpringApplication的run⽅法.

public CommandLineArgs parse(String... args) {
        CommandLineArgs commandLineArgs = new CommandLineArgs();
        String[] var3 = args;
        int var4 = args.length;

        for(int var5 = 0; var5 < var4;   var5) {
            String arg = var3[var5];
            if(arg.startsWith("--")) {
                String optionText = arg.substring(2, arg.length());
                String optionValue = null;
                String optionName;
                if(optionText.contains("=")) {
                    optionName = optionText.substring(0, optionText.indexOf(61));
                    optionValue = optionText.substring(optionText.indexOf(61)   1, 
                    optionText.length());
                } else {
                    optionName = optionText;
                }

                if(optionName.isEmpty() || optionValue != null && optionValue.isEmpty()) {
                    throw new IllegalArgumentException("Invalid argument syntax: "   arg);
                }

                commandLineArgs.addOptionArg(optionName, optionValue);
            } else {
                commandLineArgs.addNonOptionArg(arg);
            }
        }

        return commandLineArgs;
    }

⽅法.那么大家先来深入分析SpringApplication的run⽅法.

解析⾸先调⽤了org.springframework.boot.SpringApplication#run(Object, String...) ⽅法.代码如下:

从这段代码中我们看到DefaultApplicationArguments其实是读取了命令行的参数。

 

public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[] { source }, args);}

小开采:通过分析那么些函数的概念,你是否回想了spring boot运转的时候,用命令行参数自定义端口号的光景?
java -jar MySpringBoot.jar --server.port=8000

解析

随着调⽤如下代码:

接着往下看:ConfigurableEnvironment environment = this.prepareEnvironment(listeners, ex);
由此那行代码我们得以观望spring boot把前边成立出来的listeners和命令行参数,传递到prepareEnvironment函数中来打算运维条件。来看一下prepareEnvironment函数的真相:

  1. ⾸先调⽤了org.springframework.boot.SpringApplication#run(Object, String...) ⽅法.代码如下:

    public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[] { source }, args); }

public static ConfigurableApplicationContext run(Object[] sources, String[] args) { return new SpringApplication.run;}
    private ConfigurableEnvironment prepareEnvironment(
            SpringApplicationRunListeners listeners,
            ApplicationArguments applicationArguments) {
        // Create and configure the environment
        ConfigurableEnvironment environment = getOrCreateEnvironment();
        configureEnvironment(environment, applicationArguments.getSourceArgs());
        listeners.environmentPrepared(environment);
        bindToSpringApplication(environment);
        if (this.webApplicationType == WebApplicationType.NONE) {
            environment = new EnvironmentConverter(getClassLoader())
                    .convertToStandardEnvironmentIfNecessary(environment);
        }
        ConfigurationPropertySources.attach(environment);
        return environment;
    }

接着调⽤如下代码:

能够窥见 ⾸先开端化了SpringApplication,然后调⽤其实例⽅法:run.

在此间咱们看看了条件是通过getOrCreateEnvironment创造出来的,再深挖一下getOrCreateEnvironment的源码:

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
 return new SpringApplication(sources).run(args);
}
  1. 在 SpringApplication 的构造器中,调⽤了 initialize ⽅法.
    private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;
        }
        if (this.webApplicationType == WebApplicationType.SERVLET) {
            return new StandardServletEnvironment();
        }
        return new StandardEnvironment();
    }

能够窥见 ⾸首发轫化了SpringApplication,然后调⽤其实例⽅法:run.

经过这段代码大家见到了假如environment 已经存在,则平素回到当前的情状。

2. 在 SpringApplication 的构造器中,调⽤了 initialize ⽅法.

public SpringApplication(Object... sources) { initialize;}

小思虑:在怎么着情况下会出现environment 已经存在的意况?提醒:大家方今讲过,能够本身起始化SpringApplication,然后调用run函数,在初叶化SpringApplication和调用run函数之间,是否足以发生点什么?

public SpringApplication(Object... sources) {
 initialize(sources);
}
  1. SpringApplication#initialize⽅法代码如下:

上边包车型客车代码剖断了webApplicationType是否SEPAJEROVLET,如若是,则创设Servlet的条件,不然创设基本条件。我们来挖1挖webApplicationType是在何地起初化的:

3. SpringApplication#initialize⽅法代码如下:

    private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework."
              "web.reactive.DispatcherHandler";

    private static final String MVC_WEB_ENVIRONMENT_CLASS = "org.springframework."
              "web.servlet.DispatcherServlet";
    /**
     * Create a new {@link SpringApplication} instance. The application context will load
     * beans from the specified primary sources (see {@link SpringApplication class-level}
     * documentation for details. The instance can be customized before calling
     * {@link #run(String...)}.
     * @param resourceLoader the resource loader to use
     * @param primarySources the primary bean sources
     * @see #run(Class, String[])
     * @see #setSources(Set)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = deduceWebApplicationType();
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }

    private WebApplicationType deduceWebApplicationType() {
        if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
                && !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
            return WebApplicationType.REACTIVE;
        }
        for (String className : WEB_ENVIRONMENT_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return WebApplicationType.NONE;
            }
        }
        return WebApplicationType.SERVLET;
    }
private void initialize(Object[] sources) {
 if (sources != null && sources.length > 0) {
 this.sources.addAll(Arrays.asList(sources));
 }
 this.webEnvironment = deduceWebEnvironment();
 setInitializers((Collection) getSpringFactoriesInstances(
 ApplicationContextInitializer.class));
 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
 this.mainApplicationClass = deduceMainApplicationClass();
}
private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList; } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass();}

通过这段代码,大家发掘了原来spring boot是透过检查当前条件中是或不是存在
org.springframework.web.servlet.DispatcherServlet类来推断当前是不是是web遭遇的。
继之往下看,获得了ConfigurableEnvironment意况以往,通过后边的代码对情状实行“微调”。
经过this.configureIgnoreBeanInfo(environment);就算System中的spring.beaninfo.ignore属性为空,就把当前条件中的属性覆盖上去:

可以见到做了之类5件事:

能够见见做了之类5件事:

    private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
        if(System.getProperty("spring.beaninfo.ignore") == null) {
            Boolean ignore = (Boolean)environment.getProperty("spring.beaninfo.ignore", 
            Boolean.class, Boolean.TRUE);
            System.setProperty("spring.beaninfo.ignore", ignore.toString());
        }

    }

1. 如果sources⻓度⼤于0的话,加⼊到SpringApplication的sources中,该sources是⼀个LinkedHashSet.

  1. 如果sources⻓度⼤于0的话,加⼊到SpringApplication的sources中,该sources是⼀个LinkedHashSet.

  2. 调⽤deduceWebEnvironment⽅法决断是不是是web情形

  3. 设置initializers.

  4. 设置Listeners.

  5. 设置mainApplicationClass.

  6. deduceWebEnvironment代码如下:

经过Banner printedBanner = this.printBanner(environment);那行代码打字与印刷出spring boot的Banner。还记得spring boot运转的时候,在调整台展现的特别图片吗?这里不作深究,继续往下看:
context = this.createApplicationContext();创制了应用上下文:

  1. 调⽤deduceWebEnvironment⽅法剖断是或不是是web遭受

  2. 设置initializers.

  3. 设置Listeners.

  4. 设置mainApplicationClass.

    public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."
              "annotation.AnnotationConfigApplicationContext";

    public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot."
              "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

    public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
              "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";

    protected ConfigurableApplicationContext createApplicationContext() {
        Class<?> contextClass = this.applicationContextClass;
        if (contextClass == null) {
            try {
                switch (this.webApplicationType) {
                case SERVLET:
                    contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
                    break;
                case REACTIVE:
                    contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                    break;
                default:
                    contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
                }
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Unable create a default ApplicationContext, "
                                  "please specify an ApplicationContextClass",
                        ex);
            }
        }
        return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
    }

本文由澳门新葡亰发布于计算机知识,转载请注明出处:源码分析,boot的初始化工具创建源码

关键词: spring 源码 初始化 使用

上一篇:P1001

下一篇:没有了

最火资讯