Spring Boot Start Source analysis

Source: Internet
Author: User
Tags assert exception handling prepare split

The Spring boot project has a startup class, as follows:

@SpringBootApplication public
class demoapplication{public
    static void Main (string[] args) {
        Springapplication.run (Demoapplication.class, args);
    }
}

Write in front:
Automatic configuration of the load and configuration of classes:
The Springfactoriesloader.loadfactorynames () method loads all the meta-inf/spring.factories files, which are the classes that are configured to be configured automatically.
The configuration of the file contains: Applicationlistener, Applicationcontextinitializer,autoconfigurationimportfilter, Enableautoconfiguration and so on, you can go and see for yourself.

This file is spring-boot-autoconfigure-1.5.9.release.jar!/meta-inf/spring.factories.

1, Springapplication.run () method:
Trace to implementation:

public static Configurableapplicationcontext run (object[] sources, string[] args) {
/First new one springapplication object, and then call the Run method.
        return (new springapplication (sources)). Run (args);

1.1 Create a new Springapplication (sources) object:

public springapplication (Object ... sources) {//Initialize this.initialize (sources);} Initialize Initialize (sources) private void Initialize (object[] sources) {if (sources! = null && sources.length >
	0) {This.sources.addAll (arrays.aslist (sources)); }//Through "Javax.servlet.Servlet", "Org.springframework.web.context.ConfigurableWebApplicationContext" These two classes are exist// Create a webapplicationcontext or a standard standalone application applicationcontext type this.webenvironment = This.deducewebenvironment
	
	(); Find and load all available Applicationcontextinitializer class This.setinitializers (Springfactoriesloader) in Classpath.
	
	This.getspringfactoriesinstances (Applicationcontextinitializer.class)); Find and load all available Applicationlistener class This.setlisteners (Springfactoriesloader) in Classpath.
	
	This.getspringfactoriesinstances (Applicationlistener.class));
The starting class of the Main method is This.mainapplicationclass = This.deducemainapplicationclass (); }

2, Springapplication called the Run method after it was created:

Public Configurableapplicationcontext run (String ... args) {//monitor each task execution time StopWatch StopWatch = new StopWatch ();
	
	Stopwatch.start ();
	Configurableapplicationcontext context = null;
	
	Failureanalyzers analyzers = null;
	
	Set headless mode, which defaults to true Configureheadlessproperty (); Finds all Springapplicationrunlistener classes loaded through Springfactoriesloader and calls the starting method springapplicationrunlisteners
	Listeners = Getrunlisteners (args);
	
	Listeners.starting ();
		
		try {////package start parameter applicationarguments applicationarguments = new defaultapplicationarguments (args); Prepare the runtime environment, configure the environment that the current spring Boot application will use, call Configureenvironment () in the method to load Propertysource and profile//and Invoke all
		Listeners's Environmentprepared method informs the current springboot of the environment is well equipped.
		
		Configurableenvironment environment = prepareenvironment (listeners, applicationarguments);
		
		Load the printed Banner Banner printedbanner = printbanner (Environment); Based on whether the initialization is webenvironment, create the corresponding applicationcontext context = CreateApplicationContext();
		
		Exception handling analyzers = new Failureanalyzers (context);
		
		Prepare ApplicationContext preparecontext (context, environment, listeners, Applicationarguments,printedbanner); This is the Refresh method called ApplicationContext, which is familiar, that is, the spring IOC//Last Call The Configurationclassparser.processdeferredimportselectors () method is to load the selectors.
		
		You can find the call chain through debug//by calling the import class that parses the @import meta annotation of the @SpringBootApplication annotation and calls the Selectimports method Refreshcontext (context); Execute the Run method of Applicationrunner and Commandlinerunner in the IOC container, you can define the subclass of these two classes, and automatically call AfterRefresh after loading (context,
		
		applicationarguments);
		
		Call all the springapplicationrunlisteners to tell you that the boot is finished listeners.finished (context, NULL);
		
		Stopwatch.stop (); if (this.logstartupinfo) {new Startupinfologger (This.mainapplicationclass). logstarted (Getapplicationlog (),
		StopWatch);
	} return context;
		}catch (Throwable ex) {handlerunfailure (context, listeners, analyzers, ex);
	throw new IllegalStateException (ex); }
}

The following is an analysis of the imported classes that prepare ApplicationContext and @Import

Prepare the ApplicationContext method process:

Prepare ApplicationContext private void Preparecontext (Configurableapplicationcontext context, configurableenvironment Environment, springapplicationrunlisteners listeners, applicationarguments applicationarguments, Banner Printedbanner) {//Set environment, Resource ApplicationContext class loader, inject the generated Beanname class (Beannamegenerator) into context context.setenvironment (E
	
	Nvironment); For ApplicationContext further processing//beannamegenerator injection//resourceloader and Calssloader settings Postprocessapplicationcontext (
	
	context); With all Applicationcontextinitializer loaded with Springfactoriesloader, the ApplicationContext is further set to Applyinitializers (context)
	
	;
	
	Call all of the Springapplicationrunlistener's contextprepared methods to tell the context is ready for listeners.contextprepared (context);
		Log processing if (this.logstartupinfo) {Logstartupinfo (context.getparent () = = null);
	Logstartupprofileinfo (context);
			}//Source comment: Add boot specific singleton beans context.getbeanfactory (). Registersingleton ("Springapplicationarguments",
	
	applicationarguments); if (PrintedbanneR! = null) {//Register banner Context.getbeanfactory (). Registersingleton ("Springbootbanner", Printedbanner);
	}//Load the sources set<object> sources = getsources ();
	
	Assert.notempty (sources, "sources must not being empty");
	Injects the current source (the current startup class, or the class you want to inject) into the spring container, and gets the metadata from the information annotated by the source.
	
	Load (context, Sources.toarray (new Object[sources.size ())); Call all of the Springapplicationrunlisteners contextloaded methods to tell ApplicationContext that the filling is complete listeners.contextloaded (context)
; }//load method: protected void Load (ApplicationContext context, object[] sources) {if (logger.isdebugenabled ()) {Logge
	R.debug ("Loading source" + stringutils.arraytocommadelimitedstring (sources)); }//Create Beandefinitionloader, including Annotatedbeandefinitionreader Xmlbeandefinitionreader Classpathbeandefinitionscanne R provides a variety of scenarios for bean read mode 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);
}//Load Method Loader.load ();
}//loader.load ();
	private int Load (Object source) {assert.notnull (source, "source must not is null");
	if (source instanceof class<?>) {//Use this load method to start with return load ((class<?>) source);
	} if (source instanceof Resource) {//load from Resource return load ((Resource) source);
	The IF (source instanceof package) {//is loaded from the packet, which is the scanner scan return load (source);
	} if (source instanceof charsequence) {//load from String return load ((charsequence) source);
	
} throw new IllegalArgumentException ("Invalid Source Type" + Source.getclass ());} Load (Class) method private int Load (class<?> source) {if (Isgroovypresent ()) {//any groovyloaders added in beans {} DSL can contribute beans here if (GroovyBeanDefinitionSource.class.isAssignablEfrom (source)) {Groovybeandefinitionsource loader = Beanutils.instantiateclass (source, Groovybeandefinitionsource
			. Class);
		Load (loader); }} if (Iscomponent (source)) {//This is the way to implement, one layer at a down, and the last to find is the Annotatedreader.registerbean () method this.annotatedReader.re
		Gister (source);
	return 1;
} return 0;
 }/** * Register a bean from the given Bean class, deriving it metadata from class-declared annotations. * Translate: Register the bean from the given Bean class and get the bean's metadata through this class-defined annotations.
 This is clear, @SpringBootApplication related annotations are resolved here. */public void Registerbean (class<?> annotatedclass, String name, class<? extends Annotation> .... qualifiers)
	{//create beandefinition of annotations, create a standardannotationmetadata in the construction method to hold Annotatedclass annotations
	
	Annotatedgenericbeandefinition abd = new Annotatedgenericbeandefinition (annotatedclass);
	Determine if metadata is not loaded by Conditional if (This.conditionEvaluator.shouldSkip (Abd.getmetadata ())) {return; }//Parse meta data scope scopemetadata Scopemetadata = This.scopemetAdataresolver.resolvescopemetadata (ABD);
	
	Abd.setscope (Scopemetadata.getscopename ()); Bean name, which is the bean that started the class demoapplication String beanname = (name! = null? name:this.beanNameGenerator.generateBeanName (ABD
	
	, This.registry)); Whether the underlying elements of metadata have lazy Primary DependsOn Role Description annotations or meta annotations, if any, set related properties (see source) Annotationconfigutils.processco
	
	Mmondefinitionannotations (ABD); When the bean is injected, if (qualifiers! = null) {for (class<? extends annotation> qualifier:qualifiers) {if (primary.cl
			Qualifier) {abd.setprimary (true);
			} else if (Lazy.class = = qualifier) {Abd.setlazyinit (true);
			} else {abd.addqualifier (new Autowirecandidatequalifier (qualifier)); }}}//Create Beandefinitionholder, this through beanname aliases holding bean beandefinitionholder Definitionholder = new Beandefiniti
	
	Onholder (Abd, beanname); Apply for a Definitionholder proxy object, Definitionholder = Annotationconfigutils.applyscopedproxymode (Scopemetadata, Definitionholder, This.registRY);
Put the beandefinition into the Spring container beandefinitionreaderutils.registerbeandefinition (Definitionholder, this.registry); }

When ApplicationContext is ready, the Refreshcontext (context) method that is called when Spring starts is called, and the automatically configured class is called here.

@SpringBootApplication annotated import class for @import meta annotations, and call the Selectimports method

Autoconfiguration method, the argument is the demoapplication of the start class string[] Selectimports (annotationmetadata
	Annotationmetadata) {//not automatically configured to return if (!isenabled (Annotationmetadata)) {return no_imports; } try {//Meta-inf/spring-autoconfigure-metadata.properties and create the configuration of this file, then creates the Propertiesautoconfigurationm Etadata object and returns Autoconfigurationmetadata Autoconfigurationmetadata = Autoconfigurationmetadataloader.loadmetadata (
		
		This.beanclassloader);
		The Annotationmetadata attribute, which is the exclude value of the @SpringBootApplication annotation, is parsed out.
		
		Annotationattributes attributes = GetAttributes (annotationmetadata);			Use ClassLoader to load all the meta-inf/spring.factories files and parse the Enableautoconfiguration.class subclasses from them.
		is to use the Springfactoriesloader.loadfactorynames () method, in front of the load applyinitializers is also using the same method, just parse the class is not the same.
		
		list<string> configurations = getcandidateconfigurations (annotationmetadata,attributes);
		
		Go to heavy configurations = removeduplicates (configurations); Sorting, sorted alphabetically, followed by order note, and finally@AutoConfigureBefore @AutoConfigureAfter Note 1 configurations = sort (configurations, autoconfigurationmetadata);
		
		Gets the class set<string> exclusions = Getexclusions (annotationmetadata, attributes) to which the Annotationmetadata attribute is excluded from loading;
		
		If the excluded class exists and is not in the configurations collection, then it is necessary to illegalstateexception the runtime exception checkexcludedclasses (configurations, exclusions);
		
		Delete the class Configurations.removeall (exclusions) that ignores automatic configuration; Filter out classes that are not automatically configured.
		
		This filter method is the place where we have configured the Condition matchs () method call configurations = Filter (configurations, autoconfigurationmetadata);
		
		Start automatic configuration of fireautoconfigurationimportevents (configurations, exclusions);
	Return Configurations.toarray (New String[configurations.size ()));
	} catch (IOException ex) {throw new IllegalStateException (ex);
		}}//filter out classes that are not configured, and return the private list<string> filter to be configured automatically (list<string> configurations,
	
	Autoconfigurationmetadata autoconfigurationmetadata) {Long startTime = System.nanotime (); Automatic configuration class full class name string[] CandidaTES = Configurations.toarray (New String[configurations.size ()));
	
	Whether auto-configured classes will skip automatic configuration boolean[] Skip = new Boolean[candidates.length];
	
	If you have skipped automatic configuration, then it is true, if all the automatic configuration classes are matched, then false, you can quickly return, do not have to not automatically configure the class to filter out the Boolean skipped = false; Get the Autoconfigurationimportfilter object through Pringfactoriesloader.loadfactories (), all the candidates are filtered through the filter, Find out which class//getautoconfigurationimportfilters () method is determined to be automatically configured, that is, the springfactoriesloader.loadfactories () method loads all Autoconfigurationimportfilter.class class for (Autoconfigurationimportfilter filter:getautoconfigurationimportfilters
		
		()) {//Set resource, ClassLoader attribute invokeawaremethods (filter);
		
		This method is called the Condition match () method where boolean[] match = filter.match (candidates, autoconfigurationmetadata);
				for (int i = 0; i < match.length; i++) {if (!match[i]) {Skip[i] = true;
			skipped = true;
	}}}//If all configurations have not skipped automatic configuration, then return directly if (!skipped) {return configurations; }//The code below is to remove classes that are not automatically configured, and the rest of the classes are automatically configured list<string> REsult = new arraylist<string> (candidates.length);
		for (int i = 0; i < candidates.length; i++) {if (!skip[i]) {Result.add (candidates[i]);
		}} if (Logger.istraceenabled ()) {int numberfiltered = Configurations.size ()-result.size (); Logger.trace ("Filtered" + numberfiltered + "Auto Configuration class in" + TimeUnit.NANOSECONDS.toMillis (System.nan
	Otime ()-StartTime) + "MS");
} return new arraylist<string> (result); }//Take a look at how the Filter.match () method matches the implementation. Only one Autoconfigurationimportfilter class Onclasscondition is configured in the Spring.factories configuration.
The match () method of this class is called. @Override Public boolean[] Match (string[] autoconfigurationclasses, Autoconfigurationmetadata
	
	Autoconfigurationmetadata) {//Get condition-judged class Conditionevaluationreport report = Getconditionevaluationreport (); Converts the full class name into a Conditionoutcome object.
	
	The conditionoutcome[of match in this conversion] outcomes = Getoutcomes (autoconfigurationclasses, autoconfigurationmetadata);
	
	boolean[] match = new Boolean[outcomes.length]; For (int i = 0; i < outcomes.length; i++) {//Determine if match match[i] = (outcomes[i] = = NULL | | outcomes[i].ismatch ());
			
			if (!match[i] && outcomes[i]! = null) {Logoutcome (autoconfigurationclasses[i], outcomes[i]);
			if (report! = null) {report.recordconditionevaluation (autoconfigurationclasses[i], this, outcomes[i]);
}}} return match; }//Convert the auto-configured full-class name to the Conditionoutcome object and verify that private conditionoutcome[] Getoutcomes is configured automatically (string[] Autoconfigurationclasses, Autoconfigurationmetadata autoconfigurationmetadata) {//Autoconfigurationclasses
	Divided into two parts to deal with. Split the work and perform half in a background thread. Using a single//additional thread seems to offer the best performance.
	More threads make//things worse int split = AUTOCONFIGURATIONCLASSES.LENGTH/2; Outcomesresolver firsthalfresolver = createoutcomesresolver (autoconfigurationclasses, 0, Split,
	Autoconfigurationmetadata); Outcomesresolver secondhalfresolver = new StandardoutcomesresoLver (autoconfigurationclasses, Split, Autoconfigurationclasses.length,autoconfigurationmetadata,
	
	This.beanclassloader);
	Convert the auto-configured full-class name to Conditionoutcome object, see Onclasscondition inner Class Standardoutcomesresolver.resolveoutcomes () method
	conditionoutcome[] Secondhalf = Secondhalfresolver.resolveoutcomes ();
	
	conditionoutcome[] Firsthalf = Firsthalfresolver.resolveoutcomes ();
	
	Results of merge processing completed conditionoutcome[] outcomes = new Conditionoutcome[autoconfigurationclasses.length];
	System.arraycopy (firsthalf, 0, outcomes, 0, firsthalf.length);
	
	System.arraycopy (secondhalf, 0, outcomes, split, secondhalf.length);
return outcomes; The//resolveoutcomes () method calls the following two methods to implement the private conditionoutcome[] Getoutcomes (final string[] autoconfigurationclasses, in t start, int end, Autoconfigurationmetadata autoconfigurationmetadata) {conditionoutcome[] outcomes = new Conditionoutco
	Me[end-start];
		for (int i = start; i < end; i++) {String autoconfigurationclass = autoconfigurationclasses[i]; Get the automatic configuration class COnditionalonclass the value of the annotation property, that is, if you want to configure it automatically, there is a need for these classes to exist.
		Set<string> candidates = Autoconfigurationmetadata.getset (Autoconfigurationclass, "ConditionalOnClass");
			if (candidates! = NULL) {//If there is a Conditionalonclass property configuration, verify that there are any of these classes.
		Outcomes[i-start] = getoutcome (candidates);
}} return outcomes; } private Conditionoutcome Getoutcome (set<string> candidates) {try {//through Matchtype.missing method to verify candidates class is No, if there is a non-existent, then the Conditionoutcome.nomatch (False, "message") object is returned. 
		It's done here.
		List<string> missing = getmatches (candidates, matchtype.missing,this.beanclassloader); 
							if (!missing.isempty ()) {return Conditionoutcome.nomatch (conditionmessage.forcondition (Conditionalonclass.class)
		. Didnotfind ("Required class", "Required classes"). Items (style.quote, missing));
}} catch (Exception ex) {//We ' ll get another chance later} return null; }

This is the only way to see Conditionalonclass's match () and the other match (), which can be viewed on its own.

There's a lot of conditional in the Spring-boot-autoconfigure-1.5.9.release.jar org.springframework.boot.autoconfigure.condition bag. Definition, you can look at the specific implementation.








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.