前言
新公司太忙了,都沒啥空更新博客,就隨便記錄一下以前的學習筆記吧。SpringBoot是基于Spring上的衍生框架,只要看懂了Spring的話,學這個就比較簡單了;SpringBoot也是在當前微服務時代下流行的框架,并且該框架采用了自動配置,所以只要簡單的配置一下就可以直接使用了,省去了很多做配置的時間,可以說是開箱即用。當前SpringBoot版本號為2.1.15.RELEASE版本
使用SpringBoot
這個可以借鑒一下官網:快速創建SpringBoot?Initializer
我們新建一個maven項目,然后在pom.xml添加一下兩種依賴中的一種即可
<!--添加父模塊-->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.15.RELEASE</version>
</parent>
<!--添加依賴管理-->
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.15.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
由于在SpringBoot框架中采用模塊化形式,所以如果想要使用哪些模塊,可直接引入spring-boot-starter-xxxx模塊,例如:
<!-- test模塊 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- Web模塊 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 操作數據庫模塊 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 操作redis模塊 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
引用好對應的模塊之后,接下來就是打包了,一般采用SpringBoot自己封裝的打包plugin工具,打成可執行包,如果要打成普通的引入jar包的話,那就不需要引入這個plugin了;
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins>
</build>
然后就是啟動了,在主類加上相應的配置,就可以使用了
@SpringBootApplication
public class App {public static void main( String[] args ) {SpringApplication.run(App.class, args);}
}
啟動原理
簡單的使用講過,接下來開始講講源碼啦
@SpringBootApplication
注解主要作用是標識當前類為啟動類,通過SpringBoot打包后的jar中找到該類,并啟動當前應用,常用的屬性有:
exclude:去除指定自動配置類。
scanBasePackages:掃描路徑同ComponentScan一致
該注解源碼中包含一下注解:
//設置為配置類相當于@Configuration,可自行點進去閱讀
@SpringBootConfiguration
//自動配置注解,該注解包含@Import注解
@EnableAutoConfiguration
//開啟掃描路徑,默認為啟動類同路徑下所有包
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@EnableAutoConfiguration
該注解為表示自動配置,SpringBoot中自動配置,開箱即用的精髓都在于這個自動配置注解,該注解引用了@Import注解,去掃描spring.factories文件下的
org.springframework.boot.autoconfigure.EnableAutoConfiguration
?對應的的自動配置類,并加載相關Bean注入到IOC容器當中
SpringApplication
該類是應用啟動的主類,點進去看一下會發現其實就是創建SpringApplication對象并且調用run方法:
創建對象
讀取累路徑下META-INF/spring.factories文件中的相關屬性,并且拿到對應的Class對象
@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 = WebApplicationType.deduceFromClasspath();//讀取spring.factories中ApplicationContextInitializer相關配置setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//讀取spring.factories中ApplicationListener相關配置setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();
}
在SpringBoot默認的spring.factories文件中對應的ApplicationListener和ApplicationContextInitializer對應的示例:
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
拿到這些類,并執行對應的方法:
ApplicationContextInitializer
配置在META-INF/spring.factories文件中,配置示例如上,繼承接口并實現initialize方法,在Spring初始化之前執行該方法:
public class AppListenerStarter implements ApplicationContextInitializer<ConfigurableApplicationContext> {@Overridepublic void initialize(ConfigurableApplicationContext applicationContext) {System.out.println("AppListenerStarter ... ");}}
SpringApplicationRunListener
配置在META-INF/spring.factories文件中,配置示例如上,繼承接口并實現initialize方法,在Spring初始化之前執行該方法:
public class AppListener implements SpringApplicationRunListener {//必須要有參構造方法public AppListener(SpringApplication application, String[] args) {}@Overridepublic void starting() {System.out.println("AppListener starting...");}@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {Object o = environment.getSystemProperties().get("os.name");System.out.println("AppListener environmentPrepared..." + o);}@Overridepublic void contextPrepared(ConfigurableApplicationContext context) {System.out.println("AppListener contextPrepared...");}@Overridepublic void contextLoaded(ConfigurableApplicationContext context) {System.out.println("AppListener contextLoaded...");}@Overridepublic void started(ConfigurableApplicationContext context) {System.out.println("AppListener ConfigurableApplicationContext started...");}@Overridepublic void running(ConfigurableApplicationContext context) {System.out.println("AppListener running...");}@Overridepublic void failed(ConfigurableApplicationContext context, Throwable exception) {System.out.println("AppListener failed...");}}
執行結果為:
?調用run方法
//計時器,用來記錄Spring容器啟動花費的時間
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//從spring.factories文件中獲取SpringApplicationRunListener實現類
SpringApplicationRunListeners listeners = getRunListeners(args);
//開始執行對應的監聽器
listeners.starting();
try {//封裝命令行參數ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//封裝監聽器和參數ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);configureIgnoreBeanInfo(environment);//打印Banner日志,就是那個SpringBoot的大LOGOBanner printedBanner = printBanner(environment);//創建指定SpringIOC容器context = createApplicationContext();//獲取spring.factories文件中SpringBootExceptionReporter對應的Class,默認值為FailureAnalyzersexceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);//執行監聽器中的contextPrepared()方法prepareContext(context, environment, listeners, applicationArguments, printedBanner);//刷新IOC容器,即調用Spring中的refresh方法(掃描,加載),優先加載業務組件中的,然后在加載spring.factories文件中自動配置的類refreshContext(context);afterRefresh(context, applicationArguments);//計時停止stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}//開始調用監聽器中的started方法listeners.started(context);//回調ApplicationRunner和CommandLineRunner接口的實現類方法callRunners(context, applicationArguments);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);
}try {//調用監聽器running方法listeners.running(context);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);
}
return context;
至此,SpringBoot啟動流程結束了,自動配置就是將spring.factories文件中的指定配置類全部加載到容器中,優先加載業務Bean,后加載自動配置類中的Bean。