SpringBoot源码分析(1)—启动类
最近小编开发中使用SpringBoot,发现有许多基础知识忘记了,就边复习基础知识边看一下源码来增加记忆。小编还是菜鸟一个,写这个也是方便记录自己的理解,如有错误,请各路大神指正。
package com.italkbb.sailing.broctrl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
该类是程序的入口,根据自己的理解,写了下该类的这几句所代表的含义。
1、Application是主类,运行这个主类main方法时,程序会先初始化该主类。这时候的疑问(怎么初始化呢?什么叫初始化该类呢?做了什么呢?)
当程序主动使用这个Application类时,该类还未被加载到内存中,则系统就会通过加载、连接、初始化三个步骤来对该类初始化。没有意外的话,JVM将会完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化。
那第一步初始化Application类,而初始化的第一步又是类的加载和连接:会把该类的class文件读入内存,并为之创建一个java.lang.Class对象,这一步其实被细称为Application类的加载。也就是在下面方法里为啥可以使用Application.class来获取这个类的Class对象,因为第一步类加载的时候,就生成啦。
这时候还没有进行Applicaiton类的初始化,刚加载和连接完成,随后会检查该类的直接父类有没有被初始化,如果没有,会先初始化其直接父类。而所有类的基类都是Object类,所以会去初始化基类。其实在过程中,类加载器也会去加载所有JDK中的jar包的class文件。
把所有父类都初始化(包括加载、连接、初始化)完成了,再初始化(主要是类变量初始化,加载和连接在第一步已完成)Application,而该类没有类变量,所以就往下继续走。
2、遇到SpringApplication.run()方法,在遇到之前,还没有加载、连接、初始化该类(为方便,以下统称为初始化)。这时候为什么会初始化SpringApplication呢,因为一个类别初始化(加载、连接、初始化)有几个时机:
- 创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例
- 调用某个类的类方法(静态方法)
- 访问某个类或接口的类变量,或为该类变量赋值。
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。例如代码:Class.forName("Person"),如果系统还未初始化Person类,则这行代码将会导致该Person类被初始化,并返回Person类对应的java.lang.Class对象。
- 初始化某个类的子类。当初始化某个类的子类时,该子类的所有父类都会被初始化。
- 直接使用java.exe命令来运行某个主类时,程序会先初始化该主类。
所以SpringApplication.run()是属于第二种,调用类的类方法,所以这时候会初始化SpringApplication类。SpringApplication类中的这些变量肯定会被初始化啦。
image3、SpringApplication.run(Application.class, args)中只传递了两个参数,一个就是Application的Class对象,该Application的Class对象是在该类加载的时候JVM为其生成的。为什么要传递它呢,因为一旦获取某个类所对应的Class对象,程序就可以调用Class对象的方法来获得该类对象和该类的各种信息了。
SpringApplication.run(Application.class, args)传递Application的Class对象,以方便获取Application类上的各种信息,比如@SpringBootApplication注解,获取到该注解后,通过注解的注解解析器APT,为拥有该注解的类执行一些自定义的操作。这里又涉及注解的基础知识。
这一个启动类,这是精简,超神,这就是SpringBoot的启动类。往下的操作,还在继续学习中。