Springboot sentiment edify-springapplication (II.)

Source: Internet
Author: User
Tags print object

To undertake the former Wen springboot sentiment edify-springapplication (a), this article will be the run () method to make a detailed analysis

Springapplication#run ()

The run () method that is often called by the main function is the key to our analysis, first on the source code

    Public Configurableapplicationcontext run (String ... args) {StopWatch StopWatch = new StopWatch ();        Stopwatch.start ();        Configurableapplicationcontext context = null;        collection<springbootexceptionreporter> exceptionreporters = new arraylist<> ();        Reads the java.awt.headless system variable, which defaults to true. Commonly used in Linux image rendering Configureheadlessproperty (); Get Springapplicationrunlistener Interface Set merge instantiation call public interface starting () Springapplicationrunlisteners listeners = Getrunlisteners        (args);        Listeners.starting ();            try {applicationarguments applicationarguments = new defaultapplicationarguments (args);                    Environment configuration Configurableenvironment environment = prepareenvironment (listeners,            applicationarguments);            Spring.beaninfo.ignore Property Read Configureignorebeaninfo (Environment); Springboot Banner-like diagram Banner Printedbanner = PrintbaNner (Environment);            Create a spring app context (not yet refreshed) context = CreateApplicationContext (); Springbootexceptionreporter Interface Collection Read exceptionreporters = Getspringfactoriesinstances (Sprin            Gbootexceptionreporter.class, new class[] {Configurableapplicationcontext.class}, context);                    ApplicationContext configuration Preparecontext (context, environment, listeners, applicationarguments,            Printedbanner);            Refreshes the spring application context Refreshcontext (contextual);            AfterRefresh (context, applicationarguments);            Stopwatch.stop (); if (this.logstartupinfo) {new Startupinfologger (this.mainapplicationclass). Logstar            Ted (Getapplicationlog (), stopWatch);            }//Springapplicationrunlistener interface started () method call listeners.started (context);     Callrunners (context, applicationarguments);   } catch (Throwable ex) {handlerunfailure (context, ex, exceptionreporters, listeners);        throw new IllegalStateException (ex);        The running () method of the try {//Springapplicationrunlistener interface is called listeners.running (context);            } catch (Throwable ex) {handlerunfailure (context, ex, exceptionreporters, NULL);        throw new IllegalStateException (ex);    } return context; }

The above code comments a bit more, the author block to do a list of analysis

Springapplication#getrunlisteners ()

Gets the springapplicationrunlistener interface Set Merge instantiation, according to the previous article, read is the corresponding attribute in the meta\spring.factories file,
Here I take Org.springframework.boot.context.event.EventPublishingRunListener as an example.

First observe its constructor

    public EventPublishingRunListener(SpringApplication application, String[] args) {        this.application = application;        this.args = args;        this.initialMulticaster = new SimpleApplicationEventMulticaster();        for (ApplicationListener<?> listener : application.getListeners()) {            this.initialMulticaster.addApplicationListener(listener);        }    }

Note the application.getlisteners () method, which, according to the previous article, will get a collection of type Applicationlistener and deposit to Simpleapplicationeventmulticaster broadcast class;
The rest of the methods, such as starting ()/started ()/environmentprepared ( ) and so on, are all corresponding events that call all Applicationlistener interfaces uniformly. The author here takes starting () as an example

    @Override    public void starting() {        this.initialMulticaster.multicastEvent(                new ApplicationStartingEvent(this.application, this.args));    }

It will look for listeners to support the response to the applicationstartingevent event and execute the appropriate event method. Response listeners are Loggingapplicationlistener and liquibaseservicelocatorapplicationlistener , etc.

Springapplication#prepareenvironment ()

Environment Environment Preparation work

    private ConfigurableEnvironment prepareEnvironment(            SpringApplicationRunListeners listeners,            ApplicationArguments applicationArguments) {        // Create and configure the environment        ConfigurableEnvironment environment = getOrCreateEnvironment();        // 解析args参数和spring.profiles.active配置读取        configureEnvironment(environment, applicationArguments.getSourceArgs());        // 触发ApplicationEnvironmentPreparedEvent事件        listeners.environmentPrepared(environment);        bindToSpringApplication(environment);        if (this.webApplicationType == WebApplicationType.NONE) {            environment = new EnvironmentConverter(getClassLoader())                    .convertToStandardEnvironmentIfNecessary(environment);        }        ConfigurationPropertySources.attach(environment);        return environment;    }

There is too much content in the code, the author here for their own reading to make a summary

    1. The args parameter is wrapped as the simplecommandlinepropertysource property Source, corresponding to the keycommandLineArgs

    2. spring.profiles.activeSystem property Read, configuration for different conditions

    3. Applicationenvironmentpreparedevent event triggering, the main configfileapplicationlistener monitoring Class ( It will read the Application.properties/application.xml/application.yaml configuration file by default)

      PS:Configfileapplicationlistener This class is more important, it will also go to read the configuration file in the properties of the spring.profiles.active load profile;
      Also go to read the environmentpostprocessor interface to unify the call. Interested readers can do a good bit of analysis

    4. Binds the property source containing the environment to the configurationProperties propertysources type of key to facilitate springboot the properties contained in the global search context

Springapplication#configureignorebeaninfo ()

Read spring.beaninfo.ignore property, default is true, mainly for ignoring Bean's basic information

Springapplication#printbanner ()

Create a banner print object with the default print sample shown below (acting on console). Specific readers are interested in self-reading principles

  .   ____          _            __ _ _ /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \  \\/  ___)| |_)| | | | | || (_| |  ) ) ) )  '  |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::        (v2.0.3.RELEASE)
Springapplication#createapplicationcontext ()

Creates an application context object that creates the appropriate context based on the type of application that is judged.

context corresponds to C Lass class
servlet org.springframework.boot.web.servlet.context.annotationconfigservletwebserverapplicationcontext
servlet
reactive
none

Obviously, all annotations are applied to load the context.

Springapplication#preparecontext ()

To prepare for a context object that has already been created

Springapplication#applyinitializers ()

Start the appropriate initialization classes, which are all implementation classes of the Applicationcontextinitializer interface

    protected void applyInitializers(ConfigurableApplicationContext context) {        for (ApplicationContextInitializer initializer : getInitializers()) {            // 检查相应的ApplicationContextInitializer实体类所接收的泛型实体class            Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(                    initializer.getClass(), ApplicationContextInitializer.class);            // 只对接收的泛型为ConfigurableApplicationContext.class进行相应的初始化            Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");            initializer.initialize(context);        }    }

For the code comment above, the initialization class is basically Configurationwarningsapplicationcontextinitializer/contextidapplicationcontextinitializer /delegatingapplicationcontextinitializer/serverportinfoapplicationcontextinitializer and so on.
Interested in self-analysis of what the corresponding initialization classes are doing

Springapplication#load ()

Load beans into the appropriate context object ApplicationContext

    // 此处的source一般为main函数所在的class,也可通过SpringApplication#setSource()来新增    protected void load(ApplicationContext context, Object[] sources) {        if (logger.isDebugEnabled()) {            logger.debug(                    "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));        }        BeanDefinitionLoader loader = createBeanDefinitionLoader(                getBeanDefinitionRegistry(context), sources);        if (this.beanNameGenerator != null) {            loader.setBeanNameGenerator(this.beanNameGenerator);        }        if (this.resourceLoader != null) {            loader.setResourceLoader(this.resourceLoader);        }        if (this.environment != null) {            loader.setEnvironment(this.environment);        }        // 加载beans        loader.load();    }

I am here most concerned about this Beandefinitionloader will play what tricks, continue down

Start with the constructor function first

  Beandefinitionloader (Beandefinitionregistry registry, Object ... sources) {ASSERT.NOTNU        LL (registry, "Registry must not being null");        Assert.notempty (sources, "sources must not being empty");        this.sources = sources;        Annotation parsing class This.annotatedreader = new Annotatedbeandefinitionreader (registry);        XML parsing class This.xmlreader = new Xmlbeandefinitionreader (registry);        if (Isgroovypresent ()) {This.groovyreader = new Groovybeandefinitionreader (registry);        }//Classpath scans the class and masks the specified sources class This.scanner = new Classpathbeandefinitionscanner (registry);    This.scanner.addExcludeFilter (new Classexcludefilter (sources)); }
  1. The annotatedbeandefinitionreader annotation parsing class, which registers multiple postprocessor interfaces for subsequent context refresh operations to be invoked for parsing @Configuration/@Autowired/@Required/ .

  2. Annotatedbeandefinitionreader XML parsing class, which parses the XML configuration

  3. classpathbeandefinitionscanner Scan the specified package in the CLASSPATH environment and specify class

And look at the processing method. load ()

    public int load () {int count = 0;        for (Object source:this.sources) {count + = load (source);    } return count;        } private int Load (Object source) {assert.notnull (source, "source must not is null");        if (source instanceof class<?>) {return load ((class<?>) source);        } if (source instanceof Resource) {return load ((Resource) source);        } if (source instanceof package) {Return to load (package) source;        } if (source instanceof charsequence) {return load ((charsequence) source);    } throw new IllegalArgumentException ("Invalid Source Type" + Source.getclass ()); }//The author focuses on private int load (class<?> source) {if (Isgroovypresent () && Groov YBeanDefinitionSource.class.isAssignableFrom (source)) {//any groovyloaders added in beans{} DSL can contribut      E beans Here      Groovybeandefinitionsource loader = Beanutils.instantiateclass (source, Groovybeandefinitionsource            . Class);        Load (loader); }//To see if the class has been @component decorated. This is used to load the main class if (Iscomponent (source)) {//Register Bean This.annotatedreaannotatedbeandefinitionrea            Derder.register (source);        return 1;    } return 0;    }

The load () method here is primarily to determine whether the set of sources classes are @Component annotated, or inject them into the bean factory. That is, the main () function class that we write often adds @SpringApplication annotations, which are eventually processed by Annotatedbeandefinitionreader .

Springapplication#refresh ()

Refresh the context object, the author does not expand here, can refer to the previous article Spring source sentiment edify-abstractapplicationcontext

Exception handling

Springboot exception handling mechanism is to read the Springbootexceptionreporter interface class to different exceptions for different output, interested in self-reading

Summary

Through the above analysis, the basic work principle of springboot has a certain understanding, the most important thing is that it will be the public configuration placed in the meta\spring.factories file, we will just pay more attention to this document would understand more.
As to @SpringApplication how the annotations serve the Springboot, the author further analyzes

Springboot sentiment edify-springapplication (II.)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.