【SpringBoot】--Spring Boot核心(原理以及程式碼實現)
github:https://github.com/Ccww-lx/SpringBoot.git
SpringBoot作為我們日常開發的框架,我們必須熟悉掌握SpringBoot基礎核心,包括SpringBoot執行原理、基礎配置、外部配置、日誌配置、Profile配置、核心註解等等,其中:
SpringBoot執行原理:
- 入口類和@SpringBootApplication
- Starter pom
核心註解:
- 註解解析
- 自定義
基礎配置:
- banner配置
- Spring Boot配置檔案(properties、yaml)
- xml檔案配置
外部配置:
- 命令列引數配置
- 常規屬性配置、型別安全的配置
日誌配置:
- 支援Log4J、Log4J2以及Logback(預設)
Profile配置:
- 不同環境對應不同配置:application-{profile}.properties
基礎配置
banner配置
在src/main/resources下新建一個banner.txt,banner.txt可以通過網站生成字元自動生成。啟動閉關程式碼如下:
@SpringBootApplication public class BaseSpringBootApplication { public static void main(String[] args) { //關閉banner SpringApplication application = new SpringApplication(BaseSpringBootApplication.class); //application.setBannerMode(Banner.Mode.OFF); application.run(); //使用fluent API修改 /* new SpringApplicationBuilder(BaseSpringBootApplication.class) .bannerMode(Banner.Mode.OFF) .run();*/ } }
Spring Boot配置檔案(properties、yaml)
可使用配置檔案application.properties或application.yml, 放置在src/main/resources目錄下的任何目錄下。如下圖所示:
xml檔案配置
可使用註解@ImportResource來載入xml配置,更加spring boot的靈活性。程式碼如下:
//匯入Spring的配置檔案,讓配置檔案裡面的內容生效 @ImportResource(locations = {"classpath:base.xml"}) @Configuration public class LoadXmlFileConfiguration { //載入base.xml檔案下的bean到IOC容器中 }
外部配置
命令列引數配置
可以直接在啟動時通過命令列進行配置,如下:
java -jar xxx.jar --server.port=8888
更多詳細引數使用可以檢視。
常規屬性配置、型別安全的配置
通過@Value注入值,只需在properties或者yaml檔案中定義屬性, 直接使用@Value注入即可,也通過@ConfigurationProperties將properties或者yaml屬性和一個Bean及其屬性關聯, 從而實現型別安全的配置。程式碼如下所示:
//通過@ConfigurationProperties載入properties檔案屬性
//可使用perfix字首指定載入properties檔案屬性,通過location載入指定檔案
@ConfigurationProperties(prefix = "project")
@Configuration
public class AutoConfigurationProperties {
@Value("${project.name}")
private String projectName;
@Value("project.author")
private String projectAuthor;
public String getServerInfo() {
System.out.println("projectName:" + projectName + "projectAuthor:" + projectAuthor);
return "projectName:" + projectName +" ----" + "projectAuthor:" + projectAuthor;
}
}
日誌配置
Spring Boot預設使用Logback作為日誌框架,也支援Java Util Logging、 Log4J、 Log4J2。
log從高到低級別:
- OFF Level:最高等級的,用於關閉所有日誌記錄
- FATAL level:指出每個嚴重的錯誤事件將會導致應用程式的退出
- ERROR level:指出雖然發生錯誤事件,但仍然不影響系統的繼續執行
- WARN level:明會出現潛在錯誤的情形
- INFO level:應用程式的執行過程
- DEBUG Level:除錯應用級別
- TRACE :記錄事件訊息
- ALL:是最低等級的,用於開啟所有日誌記錄
日誌配置如下:
<?xml version="1****.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="LOG_EXCEPTION_CONVERSION_WORD">%xwEx</Property>
<Property name="LOG_LEVEL_PATTERN">%5p</Property>
<Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
<Property name="CONSOLE_LOG_PATTERN">%clr{%d{${LOG_DATEFORMAT_PATTERN}}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{%pid}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
<Property name="FILE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.cn.ccww.*" level="info" />
<Root level="info">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
Profile配置
不同環境對應不同配置:application-{profile}.properties,並通過在application.properties中設定 spring.profiles.active=prod來指定活動的Profile。如下圖所示:
SpringBoot執行原理
入口類和@SpringBootApplication
通常定義一個XXXApplication的類並使用@SpringBootApplication註解作為啟動類, 入口類裡有一個main方法,並使用SpringApplication.run( XXXApplication.class, args) , 啟動Spring Boot應用專案。
@SpringBootApplication是Spring Boot的核心註解, 它是一 個組合註解,它的核心功能是由@EnableAutoConfiguration註解提供,並由@Import註解匯入EnableAutoConfigurationImportSelector類實現自動配置。
@SpringBootApplication原始碼:
@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 {
....
}
<font size=4.5 face="微軟雅黑">詳細@SpringBootApplication原始碼可以檢視文章【簡明易理解的@SpringBootApplication註解原始碼分析】</font>
Starter pom
Spring Boot為我們提供了簡化企業級開發絕大多數場景的starter pom, 只要使用了應用場景所需要的starter pom, 相關的 技術配置將會消除, 就可以得到Spring Boot為我們提供的自動配置的Bean。
常見starter: 名稱|描述 :-|:- spring-boot-starter|Spring Boot核心starter,包含自動配置、日誌、yaml配置檔案支援 spring-boot-starter-activemq|為JMS使用Apache ActiveMQ spring-boot-starter-amqp|使用Spring AMQP、Rabbit MQ spring-boot-starter-aop|通過Spring AOP、AspectJ面向切面程式設計 spring-boot-starter-cache|使用 Spring caching快取支援 spring-boot-starter-data-cassandra|使用Cassandra分散式資料庫、Spring Data Cassandra spring-boot-starter-data-elasticsearch|使用Elasticsearch、analytics engine、Spring Data Elasticsearch spring-boot-starter-data-jdbc|通過 Tomcat JDBC 連線池使用JDBC spring-boot-starter-data-jpa|通過 Hibernate 使用 Spring Data JPA (Spring-data-jpa依賴於Hibernate) spring-boot-starter-data-mongodb|使用 MongoDB 檔案儲存資料庫、Spring Data MongoDB spring-boot-starter-data-neo4j|使用Neo4j圖形資料庫、Spring Data Neo4j spring-boot-starter-data-redis|通過Spring Data Redis 、Jedis client使用Redis鍵值儲存資料庫 spring-boot-starter-data-rest|使用Spring Data REST 以 REST 方式暴露 Spring Data repositories spring-boot-starter-data-solr|通過 Spring Data Solr 使用 Apache Solr搜尋引擎 spring-boot-starter-freemarker|使MVC Web applications 支援 FreeMarker,類似JSP spring-boot-starter-groovy-templates|使MVC Web applications 支援Groovy Templates spring-boot-starter-integration|使用Spring Integration,Spring Integration是Spring框架建立的一個API,面向企業應用整合(EAI) spring-boot-starter-json|使用Json讀寫 spring-boot-starter-mail|使用Java Mail、Spring email傳送支援 spring-boot-starter-oauth2-client|使用Spring Security’s OAuth2或者OpenID連線客戶端 spring-boot-starter-quartz|使用Quartz scheduler spring-boot-starter-security|使用 Spring Security安全框架 spring-boot-starter-test|測試 Spring Boot applications包含JUnit、 Hamcrest、Mockito spring-boot-starter-thymeleaf|使MVC Web applications 支援Thymeleaf,類似JSP spring-boot-starter-validation|通過Hibernate Validator使用 Java Bean Validation,Bean Validation 是一個數據驗證的規範;Hibernate Validator是一個數據驗證框架 spring-boot-starter-web|構建Web,包含RESTful風格框架SpringMVC和預設的嵌入式容器Tomcat spring-boot-starter-webflux|支援使用Spring Framework’s Reactive Web構建WebFlux applications spring-boot-starter-websocket|使用Spring WebSocket構建 WebSocket 應用
更多詳細strater可以檢視官方文件13.5 Starters
自定義starter
自定義Starter可以檢視【SpringBoot】--自定義starter(原理以及程式碼實現)】
核心註解
核心註解的條件註解在org.springframwork.boot.autoconfigure.condition包下,其都由元註解@Conditional組合而成。更多的註解詳情可檢視文章【推薦收藏系列:Spring boot 2.x註解Annotation大全(持續更新....)】。 註解|解析 :-|:-| @ConditionalOnBean|當容器裡有指定的Bean的條件下。 @ConditionalOnClass|當類路徑下有指定的類的條件下。 @ConditionalOnExpression|基於SpEL表示式作為判斷條件。 @ConditionalOnJava|基於JVM版本作為判斷條件。 @ConditionalOnJndi|在JNDI存在的條件下查詢指定的位置。 @ConditionalOnMissingBean|當容器裡沒有指定Bean的情況下。 @ConditionalOnMissingClass|當類路徑下沒有指定的類的條件下。 @ConditionalOnNotWebApplication|當前專案不是Web專案的條件下。 @ConditionalOnProperty|指定的屬性是否有指定的值。 @ConditionalOnResource|類路徑是否有指定的值。 @ConditionalOnSingleCandidate|當指定Bean在容器中只有一個, 或者雖然有多個但是指定首選的Bean。 @ConditionalOnWebApplication|當前專案是Web專案的條件下
原始碼分析:
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnMissingBean {
.....
}
其中,@Conditional的OnBeanCondition類為@ConditionalOnMissingBean的實現,可自定義,詳情檢視下節。
自定義conditional實現類:
實現一個是否windows系統條件的conditional實現類,程式碼如下:
//判斷是否windows系統
public class WindowsCondition implements Condition {
private final static String WINDOWS="Windows";
/**
* ConditionContext:判斷條件能使用的上下文(環境)
* AnnotatedTypeMetadata:註釋資訊
*/
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//獲取當前環境變數
Environment environment=conditionContext.getEnvironment();
//獲取bean註冊器
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//能獲取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//獲取環境變數中作業系統
String property = environment.getProperty("os.name");
//判斷作業系統是否為windows
if(property.contains(WINDOWS)){
//判斷是否存在baseWindowsSevice類,不存在則進行bean註冊
boolean isWindowsSevice = registry.containsBeanDefinition("baseWindowsSevice");
if(!isWindowsSevice){
//指定Bean定義資訊;(Bean的型別,Bean的一系列資訊)
RootBeanDefinition beanDefinition = new RootBeanDefinition(BaseWindowsService.class);
//註冊一個Bean,指定bean名
registry.registerBeanDefinition("baseWindowsSevice", beanDefinition);
BaseWindowsService windowsSevice = (BaseWindowsService)beanFactory.getBean("baseWindowsSevice");
windowsSevice.addServiceName("ccww---baseWindowsSevice");
}
return true;
}
return fal