1、Springboot 入門-配置和原理

**一、**Spring Boot 入門

 <!-- 這個插件,可以將應用打包成一個可執行的jar包;-->
 <artifactId>spring-boot-maven-plugin</artifactId>

將這個應用打成jar包,直接使用java -jar的命令進行執行;

1、啓動器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot將所有的功能場景都抽取出來,做成一個個的starters(啓動器),只需要在項目裏面引入這些starter相關場景的所有依賴都會導入進來。要用什麼功能就導入什麼場景的啓動器

2、主程序類

@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,SpringBoot就應該運行這個類的main方法來啓動SpringBoot應用;
J2EE的整體整合解決方案和自動配置都在spring-boot-autoconfigure-1.5.9.RELEASE.jar;

1、配置文件

SpringBoot使用一個全局的配置文件,配置文件名是固定的;
•application.properties
•application.yml

我們可以導入配置文件處理器,以後編寫配置就有提示了

<!--導入配置文件處理器,配置文件進行綁定就會有提示-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>

2、@Value VS @ConfigurationProperties

@Value:只是在某個業務邏輯中需要獲取一下配置文件中的某項值,;
@ConfigurationProperties:我們專門編寫了一個javaBean來和配置文件進行映射;

4、@PropertySource VS @ImportResource

@PropertySource:加載指定的配置文件;
@ImportResource:導入Spring的配置文件,

@ImportResource(locations = {"classpath:beans.xml"})
導入Spring的配置文件讓其生效

spring給容器中注入組件的幾種方式
1.包掃描+組件標註註解(@Controller/@Service/@Repository/@Component)適用於把自己寫的類加入組件(默認ID類名首字母小寫)
2.@Bean[導入的第三方包裏面的組件] (注意一定要在這個配置類上加上@Configuration)
3.@Import[快速給容器中導入一個組件]
4.使用Spring提供的 FactoryBean(工廠Bean);

2、Profile

1、多Profile文件

我們在主配置文件編寫的時候,文件名可以是 application-{profile}.properties/yml 默認使用application.properties的配置;

3、激活指定profile

​ 1、在配置文件中指定 spring.profiles.active=dev
​ 2、命令行:java -jar XXX.jar --spring.profiles.active=dev;
​ 3、虛擬機參數;-Dspring.profiles.active=dev

3、配置文件加載位置

springboot 啓動會掃描以下位置的application.properties或者application.yml文件作爲Spring boot的默認配置文件
–file:./config/
–file:./
–classpath:/config/(mvn項目 resources 目錄就是默認的classpath)
–classpath:/
優先級由高到底,高優先級的配置會覆蓋低優先級的配置,SpringBoot會從這四個位置全部加載主配置文件;互補配置;可通過spring.config.location來改變默認配置文件位置
java -jar XXX.jar --spring.config.location=G:/application.properties

4、外部配置加載順序

1.命令行參數**
2.來自java:comp/env的JNDI屬性
3.Java系統屬性(System.getProperties())
4.操作系統環境變量
5.RandomValuePropertySource配置的random.*屬性值

6.jar包外部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
7.jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件

8.jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
9.jar包內部的application.properties或application.yml(不帶spring.profile)配置文件

10.@Configuration註解類上的@PropertySource
11.通過SpringApplication.setDefaultProperties指定的默認屬性

二、自動配置原理

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

1、自動配置原理:

1)、SpringBoot啓動的時候加載主配置類,開啓了自動配置功能
@SpringBootConfiguration:Spring Boot的配置類;
—@Configuration:配置類;
——@Component 配置類也是容器中的一個組件;

2)、@EnableAutoConfiguration 作用:
@EnableAutoConfiguration
—@AutoConfigurationPackage:自動配置包: 將主配置類(@SpringBootApplication標註的類)的所在包及下面所有子包裏面的所有組件掃描到Spring容器;
—@Import(AutoConfigurationImportSelector.class): 給容器中導入組件,AutoConfigurationImportSelector:導入組件選擇器;將所有需要導入的組件以全類名的方式返回;這些組件就會被添加到容器中:

  • —selectImports()方法:
  • ——List configurations = getCandidateConfigurations(, );獲取候選的配置
    • List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
      SPI技術:掃描所有jar包類路徑下  META-INF/spring.factories
      
      SPI機制傳送門:深入理解SPI機制
      spring.factories中每一個 xxxAutoConfiguration類都是容器中的一個組件,都加入到容器中;用他們來做自動配置;

3)、每一個自動配置類進行自動配置功能;

4)、以**HttpEncodingAutoConfiguration(Http編碼自動配置)**爲例解釋自動配置原理;

@Configuration   //表示這是一個配置類,以前編寫的配置文件一樣,也可以給容器中添加組件
@EnableConfigurationProperties(HttpEncodingProperties.class)  //啓動指定類的ConfigurationProperties功能;將配置文件中對應的值和HttpEncodingProperties綁定起來;並把HttpEncodingProperties加入到ioc容器中

@ConditionalOnWebApplication //Spring底層@Conditional註解(Spring註解版),根據不同的條件,如果滿足指定的條件,整個配置類裏面的配置就會生效;    判斷當前應用是否是web應用,如果是,當前配置類生效

@ConditionalOnClass(CharacterEncodingFilter.class)  //判斷當前項目有沒有這個類CharacterEncodingFilter;SpringMVC中進行亂碼解決的過濾器;

@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)  //判斷配置文件中是否存在某個配置  spring.http.encoding.enabled;如果不存在,判斷也是成立的
//即使我們配置文件中不配置pring.http.encoding.enabled=true,也是默認生效的;
public class HttpEncodingAutoConfiguration {
  
  	//他已經和SpringBoot的配置文件映射了
  	private final HttpEncodingProperties properties;
  
   //只有一個有參構造器的情況下,參數的值就會從容器中拿
  	public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
		this.properties = properties;
	}
  
    @Bean   //給容器中添加一個組件,這個組件的某些值需要從properties中獲取
	@ConditionalOnMissingBean(CharacterEncodingFilter.class) //判斷容器沒有這個組件?
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

根據當前不同的條件判斷,決定這個配置類是否生效
一但這個配置類生效;這個配置類就會給容器中添加各種組件;這些組件的屬性是從對應的properties類中獲取的,這些類裏面的每一個屬性又是和配置文件綁定的;

5)、所有在配置文件中能配置的屬性都是在xxxxProperties類中封裝者‘;配置文件能配置什麼就可以參照某個功能對應的這個屬性類

精髓:
1)、SpringBoot啓動會加載大量的自動配置類
2)、我們看我們需要的功能有沒有SpringBoot默認寫好的自動配置類;
3)、我們再來看這個自動配置類中到底配置了哪些組件;(只要我們要用的組件有,我們就不需要再來配置了)
4)、給容器中自動配置類添加組件的時候,會從properties類中獲取某些屬性。我們就可以在配置文件中指定這些屬性的值;

xxxxAutoConfigurartion:自動配置類;
給容器中添加組件 :@Bean
xxxxProperties:封裝配置文件中相關屬性;

2、細節

自動配置類必須在一定的條件下才能生效;我們怎麼知道哪些自動配置類生效;
我們可以通過啓用 debug=true屬性;來讓控制檯打印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效

三、日誌

1、日誌框架

異步模式、自動歸檔。
一個統一的接口層:日誌門面(日誌的一個抽象層);給項目中導入具體的日誌實現就行了;

市面上的日誌框架;

日誌門面 (日誌的抽象層) 日誌實現
JCL(Jakarta Commons Logging) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j JUL(java.util.logging) Log4j2 Logback

左邊選一個門面(抽象層)、右邊來選一個實現;

SpringBoot默認 SLF4j和logback;

2、SLF4j使用

1、如何在系統中使用SLF4j

開發的時候,日誌記錄方法的調用,不應該來直接調用日誌的實現類,而是調用日誌抽象層裏面的方法;

給系統裏面導入slf4j的jar和 logback的jar

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

2、遺留問題

如何讓系統中所有的日誌都統一到slf4j;

1、將系統中其他日誌框架先排除出去;

2、用中間包來替換原有的日誌框架;

3、我們導入slf4j其他的實現

底層依賴關係

在這裏插入圖片描述

總結:
​ 1)、SpringBoot底層也是使用slf4j+logback的方式進行日誌記錄
​ 2)、SpringBoot也把其他的日誌都替換成了slf4j;
​ 3)、中間替換包

@SuppressWarnings("rawtypes")
public abstract class LogFactory {

    static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";

    static LogFactory logFactory = new SLF4JLogFactory();

4、日誌使用;

1、默認配置

SpringBoot默認幫我們配置好了日誌;

//日誌由低到高   trace<debug<info<warn<error
logging.level.com.atguigu=trace

給類路徑下放上每個日誌框架自己的配置文件即可;SpringBoot就不使用他默認配置的了

三、嵌入式Servlet容器原理

SpringBoot默認使用Tomcat作爲嵌入式的Servlet容器;

1)、如何定製和修改Servlet容器的相關配置;

1、修改和server有關的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】);

server.port=8081
server.context-path=/crud
server.tomcat.uri-encoding=UTF-8
//通用的Servlet容器設置
server.xxx
//Tomcat的設置
server.tomcat.xxx

2、編寫一個嵌入式的Servlet容器的定製器;來修改Servlet容器的配置

2)、註冊Servlet三大組件【Servlet、Filter、Listener】

由於SpringBoot默認是以jar包的方式啓動嵌入式的Servlet容器來啓動SpringBoot的web應用,沒有web.xml文件。
註冊三大組件用以下方式
ServletRegistrationBean

//註冊三大組件
@Bean
public ServletRegistrationBean myServlet(){
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet");
    return registrationBean;
}

FilterRegistrationBean

@Bean
public FilterRegistrationBean myFilter(){
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(new MyFilter());
    registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
    return registrationBean;
}

ServletListenerRegistrationBean

@Bean
public ServletListenerRegistrationBean myListener(){
    ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener());
    return registrationBean;
}

SpringBoot幫我們自動MVC的時候,自動註冊SpringMVC的前端控制器;DIspatcherServlet;

DispatcherServletAutoConfiguration中:

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public ServletRegistrationBean dispatcherServletRegistration(
      DispatcherServlet dispatcherServlet) {
   ServletRegistrationBean registration = new ServletRegistrationBean(
         dispatcherServlet, this.serverProperties.getServletMapping());
    //默認攔截: /  所有請求;包靜態資源,但是不攔截jsp請求;   /*會攔截jsp
    //可以通過server.servletPath來修改SpringMVC前端控制器默認攔截的請求路徑
    
   registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
   registration.setLoadOnStartup(
         this.webMvcProperties.getServlet().getLoadOnStartup());
   if (this.multipartConfig != null) {
      registration.setMultipartConfig(this.multipartConfig);
   }
   return registration;
}

默認支持:引入web模塊默認就是使用嵌入式的Tomcat作爲Servlet容器;

嵌入式Servlet容器啓動原理;

什麼時候創建嵌入式的Servlet容器工廠?什麼時候獲取嵌入式的Servlet容器並啓動Tomcat;

獲取嵌入式的Servlet容器工廠:

1)、SpringBoot應用啓動運行run方法

2)、refreshContext(context);SpringBoot刷新IOC容器【創建IOC容器對象,並初始化容器,創建容器中的每一個組件】

3)、refresh(context);刷新剛纔創建好的ioc容器;

4)、 onRefresh(); web的ioc容器重寫了onRefresh方法

由 refresh() 可知,重寫方法的執行順序爲:postProcessBeanFactory()、onRefresh()、finishRefresh()。

.postProcessBeanFactory()

  1. 添加後置處理器 WebApplicationContextServletContextAwareProcessor
  2. 忽略自動裝配以來接口 ServletContextAware
  3. 註冊 web 應用的作用域

.onRefresh()

  1. 調用父類的 onRefresh() 方法
  2. 創建 Web 服務器
    onRefresh() 創建 Web 服務器時,首先從 BeanFactory 獲取 ServletWebServerFactory 類型的 Bean,即Tomcat/Jetty/Undertow ,默認 TomcatServletWebServerFactory。利用這個工廠類的方法public WebServer getWebServer(ServletContextInitializer... initializers)來創建 TomcatWebServer,這個方法主要就是爲 TomcatWebServer 創建 Tomcat 實例。此外,注意其入參 ServletContextInitializer 是函數式接口,可以將其方法作爲參數傳入,初始化 TomcatWebServer 時,調用 Tomcat.start() 啓動 Server,以異步的方式執行該函數接口的實現類,即執行 onStartup() 方法。

創建 Tomcat 實例這一步完成初始化的工作,其生命週期狀態變化爲:NEW->INITIALIZING->INITIALIZEDINITIALIZED表示已經初始化的狀態。

.finishBeanFactoryInitialization(beanFactory)

從 BeanFactory 獲取 name 爲 requestMappingHandlerMapping 的 Bean,並初始化這個 Bean,過程中執行其實現的接口方法 InitializingBean.afterPropertiesSet(),該方法遍歷所有可用的 Bean,找到 @Controller 或者 @RequestMapping 註解的類,利用反射技術,遍歷出這些類的方法及其請求 URL 的映射關係進行緩存。

.finishRefresh()

真正完成啓動 Tomcat,其生命週期狀態變化爲:INITIALIZED->STARTING_PREP->STARTING->STARTED,即表示啓動成功。

9、使用外置的Servlet容器

嵌入式Servlet容器:應用打成可執行的jar
​ 優點:簡單、便攜;
​ 缺點:默認不支持JSP、優化定製比較複雜(自己編寫嵌入式Servlet容器的創建工廠);

外置的Servlet容器:外面安裝Tomcat—應用war包的方式打包;

流程:
1)、啓動Tomcat
2)、spring-web-4.3.14.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer:
Spring的web模塊裏面有這個文件:org.springframework.web.SpringServletContainerInitializer
3)、SpringServletContainerInitializer將@HandlesTypes(WebApplicationInitializer.class)標註的所有這個類型的類都傳入到onStartup方法的Set<Class<?>>;爲這些WebApplicationInitializer類型的類創建實例;
4)、每一個WebApplicationInitializer都調用自己的onStartup;
20180302221835.png)]

5)、相當於我們的SpringBootServletInitializer的類會被創建對象,並執行onStartup方法

6)、SpringBootServletInitializer實例執行onStartup的時候會createRootApplicationContext;創建容器

7)、Spring的應用就啓動並且創建IOC容器

啓動Servlet容器,再啓動SpringBoot應用

#Docker
docker主機(Host):安裝了Docker程序的機器(Docker直接安裝在操作系統之上);

docker客戶端(Client):連接docker主機進行操作;

docker倉庫(Registry):用來保存各種打包好的軟件鏡像;

docker鏡像(Images):軟件打包好的鏡像;放在docker倉庫中;

docker容器(Container):鏡像啓動後的實例稱爲一個容器;容器是獨立運行的一個或一組應用

1)、SpringData簡介

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-b93b42EV-1591340161211)(images/搜狗截圖20180306105412.png)]

自定義starter:
2、如何編寫自動配置

@Configuration  //指定這個類是一個配置類
@ConditionalOnXXX  //在指定條件成立的情況下自動配置類生效
@AutoConfigureAfter  //指定自動配置類的順序
@Bean  //給容器中添加組件

@ConfigurationPropertie結合相關xxxProperties類來綁定相關的配置
@EnableConfigurationProperties //讓xxxProperties生效加入到容器中

自動配置類要能加載
將需要啓動就加載的自動配置類,配置在META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

​ 3、模式:
啓動器只用來做依賴導入;
專門來寫一個自動配置模塊;
別人只需要引入啓動器(starter),啓動器依賴自動配置:自定義啓動器名-spring-boot-starter

步驟:

  1. 編寫屬性類: HelloProperties
  2. 編寫服務類 :HelloService
  3. 編寫配置類:
@Configuration
@ConditionalOnWebApplication //web應用才生效
@EnableConfigurationProperties(HelloProperties.class)
public class HelloServiceAutoConfiguration {

    @Autowired
    HelloProperties helloProperties;
    @Bean
    public HelloService helloService(){
        HelloService service = new HelloService();
        service.setHelloProperties(helloProperties);
        return service;
    }
}

4 編寫spring.factories 文件
5.mvn install 打到本地倉庫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章