目錄
pringBoot 應用啓動入口
在SpringBoot的入口類中,我們通常是通過調用SpringApplication的run方法(一個靜態方法),另外再加上@SpringBootApplication註解來啓動SpringBoot項目
通過調用SpringApplication的方法,調整應用的行爲
SpringApplicationBuilder提供了Fluent API,可以實現鏈式調用。我們可以用它來實現剛剛定義的功能,可以發現代碼層面在編寫上較爲方便
示例代碼
@SpringBootApplication
public class SpringBootStudyApplication {
public static void main(String[] args) {
// 1. 通過靜態 run 方法
SpringApplication.run(SpringBootStudyApplication.class, args);
// 2. 通過 api 調整應用行爲
SpringApplication application =
new SpringApplication(SpringBootStudyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
// 3. SpringApplicationBuilder Fluent Api, 鏈式調用
new SpringApplicationBuilder(SpringBootStudyApplication.class)
.bannerMode(Banner.Mode.OFF)
// .web(WebApplicationType.NONE)
.run(args);
}
}
SpringBoot 自動配置原理
簡單的說,自動配置就是會根據在類路徑中的jar、類自動配置Bean。Spring Boot將所有的功能場景都抽取出來,做成一個個的starter(啓動器),只需要在項目裏面引入這些starter,相關場景的所有依賴都會導入進來。
自動配置就是基於三個重要的註解實現的(實際就是 @SpringBootApplication 註解)
// @SpringBootConfiguration:我們點進去以後可以發現底層是Configuration註解,其實就是支持JavaConfig的方式來進行配置(使用Configuration配置類等同於XML文件)
// @EnableAutoConfiguration:這個註解用來開啓自動配置,是自動配置實現的核心註解
// @ComponentScan:這個註解,學過Spring的同學應該對它不會陌生,就是掃描註解,默認是掃描當前類下的package。將@Controller/@Service/@Component/@Repository等註解加載到IOC容器中
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
}
@EnableAutoConfiguration源碼
// @AutoConfigurationPackage:自動配置包
// @Import:給IOC容器導入組件
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
@AutoConfigurationPackage 源碼
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName())
}
// 很容易可以看到,它的作用就是將主配置類(@SpringBootApplication)的所在包及其子包裏邊的組件掃描到Spring容器中
@Import(AutoConfigurationImportSelector.class) 源碼
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
// 可以得到了很多配置信息
protected AutoConfigurationEntry getAutoConfigurationEntry(...) {
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 配置信息從這裏來
protected List<String> getCandidateConfigurations(...) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(...);
// 配置加載的位置
public static List<String> loadFactoryNames(...) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader)...;
}
private static Map<String, List<String>> loadSpringFactories(...) {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
result.add(factoryClassName, factoryName.trim());
// 這個方法也就是自動配置的核心實現了,主要是三點內容:
// FACTORIES_RESOURCE_LOCATION的值是META-INF/spring.factories
// Spring啓動的時候會掃描所有jar路徑下的META-INF/spring.factories,將其文件包裝成Properties對象
// 從Properties對象獲取到key值爲EnableAutoConfiguration的數據,然後添加到容器裏邊
SpringBoot 配置文件
1、同一個目錄下的 application 和 bootstrap
-
bootstrap 優先級高於 application,優先被加載
-
bootstrap 用於應用程序上下文的引導階段,由父 ApplicationContext 加載
-
bootstrap 是系統級別的配置(不變的參數),application 是應用級別的配置
2、不同位置的配置文件加載順序(優先級)
-
file:./config/ - 優先級最高(項目根路徑下的 config)
-
file:./ - 優先級第二(項目根路徑下)
-
classpath:/config/ - 優先級第三(項目 resources/config 下)
-
classpath:/ - 優先級第四(項目 resources 目錄下)
-
高優先級覆蓋低優先級相同配置、多個配置文件互補
SpringBoot Actuator監控
微服務的特點決定了功能模塊的部署是分佈式的,大部分功能模塊都是運行在不同的機器上,彼此通過服務調用進行交互,前後臺的業務流會經過很多個微服務的處理和傳遞,出現了異常如何快速定位是哪個環節出現了問題?
在這種框架下,微服務的監控顯得尤爲重要。SpringBoot給我們提供了一個用於監控的組件:Actuator,它也是一個starter,方便在日常的開發、運行中對我們的微服務進行監控治理。
- Actuator監控分類
-
應用配置類:可以查看應用在運行期的靜態信息:例如自動配置信息、加載的 springbean 信息、yml 文件配置信息、環境信息、請求映射信息
-
度量指標類:主要是運行期的動態信息,例如堆棧、請求連、一些健康指標、metrics 信息等
-
操作控制類:主要是指 shutdown,用戶可以發送一個請求將應用的監控功能關閉
配置注入的方式
-
直接使用 @Value
- 使用 @ConfigurationProperties + prefix 的方式
Jackson 的使用技巧
通常在項目中處理JSON一般用的都是阿里巴巴的fastjson, 後來發現使用Spring Boot內置的Jackson來完成JSON的序列化和反序列化操作也是非常方便的。
- @JsonProperty,作用在屬性上,用來爲JSON Key指定一個別名
- @Jsonlgnore,作用在屬性上,用來忽略此屬性
- @JsonIgnoreProperties,忽略一組屬性,作用於類上
- @JsonFormat,用於日期格式化
- Jackson通過使用ObjectMapper的writeValueAsString方法將Java對象序列化爲JSON格式字符串
- 反序列化使用 ObjectMapper 的 readValue
定時任務
-
@EnableScheduling:允許當前的應用開啓定時任務
-
@Scheduled:指定定時任務的運行規則
異步任務
通常代碼都是順序執行(一行一行的執行),這也就是同步調用。但是異步編程卻沒有這樣的限制,代碼執行並不是阻塞的。可以直接調用不用等待返回,而是在某一個想要獲取結果的時間點再去獲取結果。
-
引入spring-boot-starter-web依賴
- 在SpringBoot入口類上加上 @EnableAsync 註解,開啓異步支持
- 只需要在方法上加上 @Async 註解,則當前方法就是異步方法
默認情況下的異步線程池配置使得線程不能被重用,每次調用異步方法都會新建一個線程,我們可以自己定義異步線程池來優化。
單元測試
編寫單元測試可以幫助開發人員編寫高質量的代碼,提升代碼質量,減少Bug,便於重構。SpringBoot提供了一些實用程序和註解,用來幫助我們測試應用程序,在SpringBoot中開啓單元測試只需引入spring-boot-starter-test即可,其包含了一些主流的測試庫。
一個標準的SpringBoot測試用例應該包含兩個註解:
-
@SpringBootTest:意思是帶有 SpringBoot 支持的引導程序,其中提供了可以指定 Web 環境的參數
-
@RunWith(SpringRunner.class):告訴JUnit運行使用Spring的測試支持。SpringRunner是SpringJUnit4ClassRunner的新名字,這個名字只是讓名字看起來簡單些