1. 程式人生 > >spring boot知識總結

spring boot知識總結

目錄

Spring Boot是什麼?

Spring Boot  Starter

約定1:專案結構層面的約定

約定2:springMVC框架層面的約定和定製

約定3:嵌入式web容器層面的約定和定製

Automatically Configuration

關於@SpringBootApplication這個註解的作用,記住下面這張圖即可:

@Configuration

@ComponentScan

@EnableAutoConfiguration

自動配置幕後英雄:SpringFactoriesLoader詳解

Acutator

spring boot啟動過程


Spring Boot是什麼?

Spring Boot是為簡化Spring MVC/spring的開發而生的專案。主要從以下三個方面:

  1. simplify configuration 簡化配置

  2. simplify deployment簡化部署

  3. simplify monitor 簡化系統監控

spring boot由四個主要的元件組成:

  1. Spring Boot  Starter:

  2. Automatically Configuration.

  3. CLI. Use with groovy.

  4. Actuator

Spring Boot  Starter

spring boot starter起到的作用是,把一些列的依賴結合起來,依賴之間可以像java類繼承一樣引用對方。這樣的好處是解決了依賴之間衝突的問題(這個問題在maven使用過程中非常常見),減少了依賴的數量。

下面是一個spring boot starter web的例子:

在這個時代,使用spring開發的應用大多數都是在使用springMVC開發web應用,為了幫我們快速搭建並開發一個web專案,spring boot為我們提供了spring-boot-starter-web自動配置模組。

只要將spring-boot-starter-web加入專案的maven依賴,我們就得到了一個直接可執行的web應用,在當前專案下執行spring boot:run,就可以直接啟動一個使用了嵌入式Tomcat服務的web應用,只不過我們還沒有提供任何可以響應web請求的controller,所以當前訪問任何的路徑都會返回一個spring boot預設提供的錯誤頁面(white label error page). 如果在當前專案下新建一個服務根路徑web請求的controller:

@RestController
public class IndexController {
    @RequestMapping("/")
    public String index(){
        return "hello, there";
    }
}

重新執行mvn spring-boot:run並訪問http://localhost:8080,錯誤頁面將被controller返回的訊息所替代。至此,一個簡單的web應用就已經這樣完成了。但是,毫無疑問背後的潛規則(約定)是我們必須去了解的。

約定1:專案結構層面的約定

與傳統打包為war包的java web應用的差異在於,靜態檔案和頁面模板的存放位置變了,原來是放在src/main/webapp目錄下的一系列資源,現在都統一放在了src/main/resources下。

約定2:springMVC框架層面的約定和定製

spring-boot-starter-web預設為我們配置了一些springMVC必要元件

  1. ViewResolver
  2. Converter,Formatter等bean註冊到IoC
  3. HttpMessageConverter
  4. MessageCodesResolver

當然,我們完全可以自己配置這些東西,而不用它提供的配置。

約定3:嵌入式web容器層面的約定和定製

  1. 預設使用嵌入式tomcat作為web容器對外提供http服務,預設使用8080埠對外監聽和提供服務
  2. 假設不行使用簽署tomcat,可引入spring-boot-starter-jetty或spring-boot-starter-undertow作為替代
  3. 假設不想使用8080作為預設埠,可以更改配置項server.port使用自己指定的埠號,如:server.port = 9000

Automatically Configuration

自動配置的主要職責是:減少spring的配置。

自動配置是什麼,用一個例子比較好說明。當我們把spring-boot-starter-web加入到專案的maven依賴裡以後,它就會自動的新增spring mvc的相關依賴,如果spring mvc相關的配置在classpath裡面被scan到,它就會自動的將相關的bean加到IoC容器裡面(messageConvert等)。spring啟動的時候會掃描classpath並且去找META-INF/spring.factories這個檔案,然後去載入configuration. 這個檔案的格式是 key = value的格式,並且key和value都必須是java 類的全限定名(Fully qualified), 比如:

   exmaple.MyService = example.MyServiceImpl

如果我們使用了註解@EnableAutoConfiguration,它會去載入,例項化所有加了@Configuration的註解的類到IoC容器裡去(ApplicationContext),通常,這個註解會用在主類裡邊,並且主類一般是在開發包的最頂部,因此它就可以掃描到所有的類。

@EnableAutoConfiguration這個註解的示意圖如下:

@ComponentScan:

會自動掃描包路徑下面的所有@Controller、@Service、@Repository、@Component 的類。

 basePackages指定掃描的包,includeFilters包含那些過濾,excludeFilters不包含那些過濾,useDefaultFilters預設的過濾規則是開啟的,如果我們要自定義的話是要關閉的

@Configuration

把一個類標記為IoC容器的一個bean

關於@SpringBootApplication這個註解

這個註解由下面幾個註解組成:

@Configuration

它就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration.

這裡的啟動類標註了@Configuration之後,本身其實也是一個IoC容器的配置類。

任何一個標註了@Configuration的Java類定義都是一個JavaConfig配置類。

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	

這個springBoot啟動類等價於下面的寫法:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class AppConfiguration{
    @Bean
    public Controller controller(){
        return new Controller();
    }
}

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(AppConfiguration.class, args);
	}
}
	

經過這樣的改造之後,就很明白了,啟動類就是一個普通的main函式啟動類,沒有什麼特別之處,在main 裡面呼叫了一個方法而已。

而由@Configuration修飾的AppConfiguration類定義就是一個普通的javaConfig形式的IoC容器配置類而已。

@ComponentScan

@ComponentScan這個註解在Spring中很重要,它對應XML配置中的元素,@ComponentScan的功能其實就是自動掃描並載入符合條件的元件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義載入到IoC容器中。

我們可以通過basePackages等屬性來細粒度的定製@ComponentScan自動掃描的範圍,如果不指定,則預設Spring框架實現會從宣告@ComponentScan所在類的package進行掃描。

p.s. 所以SpringBoot的啟動類最好是放在root package下,因為預設不指定basePackages

@EnableAutoConfiguration

@EnableAutoConfiguration是藉助@Import的幫助,將所有符合自動配置條件的bean定義載入到IoC容器,僅此而已。

它本事也是一個複合的註解,它的實現如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

最關鍵的要屬@Import(EnableAutoConfigurationImportSelector.class),藉助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以幫助SpringBoot應用將所有符合條件的@Configuration配置都載入到當前SpringBoot建立並使用的IoC容器.

藉助於Spring框架原有的一個工具類:SpringFactoriesLoader的支援,@EnableAutoConfiguration可以智慧的自動配置功效才得以大功告成.

自動配置幕後英雄:SpringFactoriesLoader詳解

SpringFactoriesLoader屬於Spring框架私有的一種擴充套件方案,其主要功能就是從指定的配置檔案META-INF/spring.factories載入配置。

配合@EnableAutoConfiguration使用的話,它更多是提供一種配置查詢的功能支援,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查詢的Key,獲取對應的一組@Configuration類.

以下是從springBoot的:spring-boot-autoconfigure依賴包中的截圖:

@EnableAutoConfiguration自動配置的魔法就是:從classpath中搜尋所有的META-INF/spring.factories配置檔案,並將其中org.springframework.boot.autoconfigure.EnableautoConfiguration對應的配置項通過反射(Java Refletion)例項化為對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,然後彙總為一個並載入到IoC容器

在我們啟動spring boot的app時會呼叫一個SpringBootApplication的run方法。這個方法在執行過程中會去主動初始化需要用到的bean。其重要實現如下:

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
                        result.addAll((String)entry.getKey(), factoryClassNames);
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var9) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
            }
        }
    }

可以看到,是從一個名字(變數FACTORIES_RESOURCE_LOCATION)叫spring.factories的資原始檔中,讀取所有的配置資訊存放在了一個LinkedMultiValueMap型別的區域性變數result當中。

Acutator

spring提供了actutator用於幫助我們監控服務的各種狀態:

路徑 作用

info

know the service situation
error  
autoconfig list config decisions
beans List  all the config beans
dump List application’s thread information
/env/{name} list all the environment variables
health  
info  
/metrics/{name} list the realated index
shutdown shut down the service
trace list the recent quest metadata,include request and response header
configprops list all the  @ConfigurationProperties

spring boot啟動過程

spring boot專案的啟動過程大致如下圖: