spring-boot-2.0.3 not the same series of source text

Source: Internet
Author: User
Tags stack trace groovy script
Objective

Previous: spring-boot-2.0.3 not the same series of the Shiro-building, the realization of spring-boot and Shiro integration, the effect of everyone also saw, the project does integrate the Shiro certification and authorization functions. If we can set up correctly, and achieve the effect of certification and authorization, that means we will use, indicating that we know it, very good, to meet the basic requirements of the work.

But is that enough? It is obviously not enough, know it is a bottleneck, but if we can cross this bottleneck, the road behind will become more and more magnanimous. Take a blog to say, we just add a few bean configuration in the Shiroconfig class, how to let Spring-boot integration Shiro,shiro and how to do authentication and authorization, and so on some column problems, if we go to think, There is really a lot of doubt that we need to explore.

Since we are going to explore, it is bound to read the source code. Source is really not good to read, in our work, when we read colleagues (or former colleagues) write code, there is always a sentence: Grass mud horse, which is what SB write, lingering in our hearts, and sometimes will find that he is my own writing ah, hey, I am! Sometimes it's a headache to read your own code, not to mention what someone else has written.

Say so much, we cut to the point, and then there will be a series of articles to resolve the Springboot start process, and today we only look at the Springapplication class construction method.

Springapplication class

The entrance is still the familiar entrance: main function

Springapplication class Comments
/*** Class that can is used to bootstrap and launch a Spring application from a Java main * method. By default class would perform the following steps to bootstrap your * application: * * <ul> * <li>create an AP propriate {@linkApplicationContext} instance (depending on your * classpath) </li> * <li>register a {@linkCommandlinepropertysource} to expose command line arguments as * Spring properties</li> * <li>refresh the Application context, loading all singleton beans</li> * <li>trigger any {@linkCommandlinerunner} beans</li> * </ul> * * In most circumstances the static {@link#run (Class, string[])} method can be called * directly from your {@literalMain} method to bootstrap your application: * * <pre class= "code" > * & #064; Configuration * & #064; Enableautoconfiguration * public class MyApplication {* *//... Bean definitions * public static void Main (string[] args) throws Exception {* Springapplication.run (MyApplication . class, args); *} *} * </pre> * * <p> * for + Advanced Configuration a {@linkSpringapplication} instance can be created and * customized before being run: * * <pre class= ' code ' > * Public s tatic void Main (string[] args) throws Exception {* Springapplication application = new Springapplication (MyApplication. Class); *//... customize application settings here * Application.Run (args) *} * </pre> * * {@linkspringapplication}s can read beans from a variety of different sources. IT is * generally recommended. A single {@code@Configuration} class is used to bootstrap * Your application, however, and may also set {@link#getSources () sources} from: * <ul> * <li>the fully qualified class name to being loaded by * {@linkannotatedbeandefinitionreader}</li> * <li>the location of a XML resource to being loaded by {@linkXmlbeandefinitionreader}, or * A groovy script to being loaded by {@linkgroovybeandefinitionreader}</li> * <li>the name of a package to being scanned by {@linkclasspathbeandefinitionscanner}</li> * </ul> * Configuration properties is also bound to the {@linkspringapplication}. This makes it * possible to set {@linkSpringapplication} Properties dynamically, like additional * sources ("spring.main.sources"-a CSV list) the flag to Indicate a Web Environment * ("Spring.main.web-application-type=none") or the flag to switch off the banner * ("spring.ma In.banner-mode=off "). */
View Code

The content of the words is probably as follows:

Springapplication is used to boot and start the spring application from the Java Main method, which by default performs the following steps to guide our application:

1. Create an appropriate ApplicationContext instance (depending on the classpath)

2. Register Commandlinepropertysource to expose command-line parameters as spring properties

3. Refresh the application context and load all the singleton beans

4. Trigger All Commandlinerunner beans

Most of the cases, like Springapplication.run (Shiroapplication.class, args), to launch our app, or to create and customize Springapplication instances before running, Refer to the example in the note for details.

Springapplication can read beans from a variety of different sources. It is generally recommended to use a single @configuration class to boot, but we can also set resources in the following ways:

1. Load fully qualified class name via Annotatedbeandefinitionreader

2. Load the XML resource location via Xmlbeandefinitionreader, or load the groovy script location via Groovybeandefinitionreader

3. Scan package name by Classpathbeandefinitionscanner

That is to say springapplication still do a lot of things, concrete implementation will slowly speak, today's protagonist is just springapplication construction method.

Springapplication Construction Method

The source code is as follows

/*** Create a new {@linkSpringapplication} instance. The application context would load * Beans from the specified primary sources (see {@linkspringapplication class-level} * documentation for details. The instance can be customized before calling * {@link#run (String ...)}. * @paramResourceloader the resource loader to use *@paramprimarysources The primary bean sources *@see#run (Class, string[]) *@see#setSources (Set)*/@SuppressWarnings ({"Unchecked", "Rawtypes" })     PublicSpringapplication (Resourceloader Resourceloader, class<?>... primarysources) {         This. Resourceloader =Resourceloader; Assert.notnull (Primarysources,"Primarysources must not being null");  This. primarysources =NewLinkedhashset<>(Arrays.aslist (primarysources));  This. Webapplicationtype =Deducewebapplicationtype (); Setinitializers (Collection) getspringfactoriesinstances (Applicationcontextinitializer.class)); Setlisteners (Collection) getspringfactoriesinstances (Applicationlistener.class));  This. Mainapplicationclass =Deducemainapplicationclass (); }

From a comment, it means creating an shiroapplication instance that the application context loads the bean from a specific resource file. You can customize the instance before calling run.

From the source point of view, mainly Deducewebapplicationtype (); getspringfactoriesinstances (Xxx.class); Deducemainapplicationclass (); These three methods , we look at it one by one.

Deducewebapplicationtype

Infer web App types

PrivateWebapplicationtype Deducewebapplicationtype () {if(Classutils.ispresent (Reactive_web_environment_class,NULL)            &&! Classutils.ispresent (Mvc_web_environment_class,NULL)) {        returnwebapplicationtype.reactive; }     for(String classname:web_environment_classes) {if(! Classutils.ispresent (ClassName,NULL)) {            returnWebapplicationtype.none; }    }    returnWebapplicationtype.servlet;}//determines whether a given class can be loaded, i.e. whether a given class exists under the Classpath Public Static BooleanisPresent (String className, @Nullable ClassLoader ClassLoader) {Try{forname (className, ClassLoader); return true; }    Catch(Throwable ex) {//Class or One of its dependencies are not present ...        return false; }}

If the Org.springframework.web.reactive.DispatcherHandler can be loaded and the Org.springframework.web.servlet.DispatcherServlet cannot be loaded, then it is determined that the Web Application type is reactive If either javax.servlet.Servlet and Org.springframework.web.context.ConfigurableWebApplicationContext cannot be loaded, then the Web app type is determined to be none; It is reactive and none, then the servlet type, and the specific three types represent what it means, and you can look at the instructions in Webapplicationtype.

Getspringfactoriesinstances

From the literal point of view is to obtain the Spring factory instance, as to where to obtain which factory instances, we look down.

Getspringfactoriesinstances Source

Private<T> collection<t> getspringfactoriesinstances (class<t>type, Class<?>[] parametertypes, Object ... args) {ClassLoader ClassLoader=Thread.CurrentThread (). Getcontextclassloader (); //Use names and ensure unique to protect against duplicatesset<string> names =NewLinkedhashset<>(Springfactoriesloader.loadfactorynames (Type, classLoader)); //gets the factory name of the specified typelist<t> instances = createspringfactoriesinstances (type, parametertypes,//Create a factory instance by name and typeClassLoader, args, names);    Annotationawareordercomparator.sort (instances); returninstances;}
View Code

From the source we see the main do three things:

1, Loadfactorynames, load the factory name of the specified type

Loadspringfactories

Loadspringfactories Source

Private StaticMap<string, list<string>>loadspringfactories (@Nullable ClassLoader ClassLoader) {Multivaluemap<string, string> result =Cache.get (ClassLoader); if(Result! =NULL) {        returnresult; }    Try{Enumeration<URL> urls = (ClassLoader! =NULL?classloader.getresources (factories_resource_location): Classloader.getsystemresources (    factories_resource_location)); //classloader.getresources (factories_resource_location) Gets the URL of all meta-inf/spring.factories under the Classpathresult =NewLinkedmultivaluemap<>();  while(Urls.hasmoreelements ()) {//iterate through all URLs and read the attributes in Meta-inf/spring.factories one by oneURL url =urls.nextelement (); Urlresource Resource=Newurlresource (URL); Properties Properties=propertiesloaderutils.loadproperties (Resource);  for(map.entry<?,? >Entry:properties.entrySet ()) {List<String> Factoryclassnames =arrays.aslist (Stringutils.commadelimitedlisttostringarray (String) Entry.getvalue ());        Result.addall (String) Entry.getkey (), factoryclassnames); //attribute all into multivaluemap<string, string> result, note the type of result}} cache.put (ClassLoader, result); //results are put into cache for next search        returnresult; }    Catch(IOException ex) {Throw NewIllegalArgumentException ("Unable to load factories from location [" +factories_resource_location+ "]", ex); }}
View Code        

Loadspringfactories did the following things.

A, find the URL of all meta-inf/spring.factories under the Classpath

b, load all the properties in Spring.factories according to the URL, spring.factories content as follows

C, cache the values in all spring.factories to the cache in Springfactoriesloader:

Private static final Map<classloader, multivaluemap<string, string>> cache = new ConcurrentReferenceHashMap <> (); convenient for next call.

After all the factory names are loaded, you get a list of factory names for the specified factory type, which is what Getordefault (Factoryclassname, Collections.emptylist ()) does.

2, Createspringfactoriesinstances, creating a factory instance of the specified type

Based on the list of factory names of the specified type obtained above, we can think of the chemical plant bean simply by reflection, but the concrete implementation is not so simple, and the interested partner can go with it.

3. Sort the factory instance and return to the sorted instance list

Collation: @Order from small to large, without order, in the order before sorting.

Deducemainapplicationclass

Gets the name of the class where the main method resides from the current stack trace list

Summary of construction methods

1. Construct Self-instance

2. Speculate on the type of Web application and assign value to attribute Webapplicationtype

3. Set properties list<applicationcontextinitializer<?>> initializers and list<applicationlistener<?>> Listeners

The properties of all meta-inf/spring.factories under the classpath are read and cached in the cache cache of the Springfactoriesloader

4. Infer the main class and assign a value to the attribute Mainapplicationclass

After the construction method is complete, the property values for the instance are as follows

Feelings

Originally is thinking of springboot start source parsing only use two to explain, then talk about Shiro source; but I wrote to find a lot of examples of inexplicable wonderful is instantiated, a lot of details did not read, so decided to cut, will springboot the START process split into several pieces to explain, I really understand what Springboot has done in the process of initiation.

Add: Sometimes, not how powerful opponents, but we do not dare to try; Take the first step bravely, you will find yourself better than you think! As Hayes first ran into the human 10s mark, he said, "God, that door is ajar!"

Reference

Spring Boot 2.0 Source analysis (i)

Springboot Source

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.