微服務技術方案:Spring Cloud 從入門到實戰


隨着互聯網技術的發展與不斷創新,以及用戶流量的不斷增大,越來越多的企業項目面臨大數據、高並發等問題,隨之而來的就是通過分布式模型組建架構,微服務思想就集中體現了應用價值,2020 年的你還沒有掌握微服務技術嗎?

本課程會講解 Spring Cloud 的重要知識點同時也會跟隨源碼,與框架設計者共同探索其設計奧妙所在,做到知其然更知其所以然!

實驗介紹

Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的開發便利性巧妙地簡化了分布式系統基礎設施的開發。

我們知道,Spring Cloud 整套微服務方案是基於 Spring Boot 作為架構制成的,那么 SpringBootApplication 啟動類作為 Spring Boot 的項目起點,至關重要,本節就了解一下 SpringBootApplication。

知識點

  • 自定義 SpringApplication
  • 配置 Spring Boot 源
  • SpringApplication 類型推斷
  • Spring Boot 事件

如何創建一個 Spring Boot 項目

1. Spring 官網創建

如圖所示,在 官網 上快速搭建一個 Spring Boot 項目。

我們可以看到上面可以選擇構建工具、語言、Spring Boot 版本、group 和 artifact 以及依賴。這里我們依據上圖所示的選項進行創建項目,點擊 Generate Project。

2. Maven 命令創建

同樣地,我們也可以使用命令在終端上創建一個項目:

mvn archetype:generate -DgroupId=com.test -DartifactId=demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

當我們將新創建后的項目結構展開就會得到:

在我們的環境中已經為大家准備好項目包,同學們執行以下命令便可以把項目下載到 WebIDE 中了。

wget https://labfile.oss.aliyuncs.com/courses/2502/demo.zip && unzip demo.zip

建議同學們直接使用我們的安裝包解壓項目,如果使用命令創建項目的話,在接下來會講解的一些類就需要同學們手動創建了。

如果同學們不清楚詳細的創建過程以及適配環境相關問題,可以先學習 Spring Boot 基礎入門,因為 Spring Boot 是在 Spring 的基礎上建立的。

SpringApplication 的詳細講解

實驗之前,我們首先對新生成的 demo 項目對其做一個調整:將 .mvn 目錄和 .gitignore 目錄以及多余配置項刪除(因為這些配置項目與本次實驗無關),並對配置文件和 pom.xml 文件做一個修改:

  • 將 resources 資源目錄下的 application.properties 文件修改為:
# 聲明開放端口號
server.port = 8080
# 聲明項目名稱
spring.application.name = spring-application

最終的效果如圖所示:

完成以上步驟配置,第一個 Spring Boot 項目的創建到這里就基本結束了,接下來我們分析一下 demo 項目中主函數代碼,即在目錄 com.example.demo 就可以查看到啟動類 DemoApplication

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

這就是最簡化版本的 Spring Boot 啟動類,這里有兩個地方值得我們注意:

一個是類 SpringApplication,另外一個是注解 @SpringBootApplication

Q: 什么是 SpringApplication
A: SpringApplication 是 Spring Boot 驅動 Spring 應用上下文的引導類。

Q:怎么理解注解 @SpringBootApplication
A:直接查看此注解的源碼,源碼如下:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
    ...
}

這里有三個注解值得我們注意:

  1. @ComponentScan 是用於定義掃描的路徑,從中找出標識了需要裝配的類自動裝配到 Spring 的 Bean 容器中。
  2. @EnableAutoConfiguration 是激活自動裝配,用於自動載入應用程序所需的所有 Bean。
  3. @SpringBootConfiguration 用於標注當前類是配置類,並會將當前類內聲明的一個或多個以 @bean 注解標記的方法的實例納入到 Spring 容器中,它與 @Configuration,在功能上是一致的。

Q: 如何理解 @Component 的“派生性”?
A:@Component 是用來把普通 POJO(Plain Ordinary Java Object) 實例化到 Spring 容器中,相當於配置文件中的 <bean id="" class=""/>,通常我們將 @Component 稱之為元注解。所謂的派生性指的是以元注解為基准,其他注解再次調用元注解而產生的派生。

Spring 之注解編程模型

回顧一下 Spring Boot 中常見的注解,諸如 @Service@Repository@Controller@Configuration。Spring 在設計的時候,都是引入了 @component 作為這些注解的元注解。

@component:泛指組件,當組件不好歸類的時候,我們可以使用這個注解進行標注。

  1. @Service:用於標注業務層組件。
@Component
public @interface Service {
        ...
}
  1. @Repository:用於標注數據訪問組件,即 DAO 組件。
@Component
public @interface Repository {
       ...
}
  1. @Controller:用於標注控制層組件。
@Component
public @interface Controller {
       ...
}
  1. @Configuration:允許通過調用同一類中的其他 @Bean 方法來定義 Bean 之間的依賴關系。
@Component
public @interface Configuration {
       ...
}

Q:關於 Spring 之模式注解(Stereotype Annotations)?
A:所謂的模式注解:@component 邏輯上與 @Service@Repository@Controller@Configuration 都是一樣,只是物理層面上不同,但都是為了找到 BeanDefinition。

現在我們來分析一下,@SpringBootApplication 這個注解,下面是通過源碼顯示的調用關系:

  • @SpringBootApplication:引入了 @SpringBootConfiguration 注解。
@SpringBootConfiguration
public @interface SpringBootApplication {
        ...
}
  • @SpringBootConfiguration:又引入了 @Configuration 注解。
@Configuration
public @interface SpringBootConfiguration {
        ...
}
  • @Configuration:最終引入了 @Component 注解。
@Component
public @interface Configuration {
        ...
}

實際上注解 @SpringBootApplication 會標注當前一些功能。我們知道,注解不能像 Java 類一樣繼承,就通過以上的這樣的方式層層調用。而注解的功能基本相似,我們就把注解的這種特性稱之為派生性。

SpringApplication 啟動類的基本寫法

啟動類 SpringApplication 就是 Spring Boot 應用的引導。

  1. 最簡化的 SpringApplication(通過 Spring 官網通過腳手架下載的最簡化的啟動類):
@SpringBootApplication
public class DemoApplication {
        public static void main(String[] args) {
                SpringApplication.run(DemoApplication.class, args);
        }
}
  1. 通過 SpringApplication 增加參數的方式。現在我們在項目目錄 com.test 創建 DemoApplication.java
package com.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.LinkedHashMap;
import java.util.Map;

@SpringBootApplication
public class DemoApplication{
        public static void main(String[] args) {
                SpringApplication springApplication = new SpringApplication(DemoApplication.class);
                Map<String,Object> properties = new LinkedHashMap<>();
                properties.put("server.port",0);
                springApplication.setDefaultProperties(properties);
                ConfigurableApplicationContext context = springApplication.run(args);
        }
  1. SpringApplicationBuilder 方式。現在我們在項目目錄 com.test 創建 SpringBootEventApplication.java
package com.test;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class SpringBootEventApplication{
        public static void main(String[] args) {
                new SpringApplicationBuilder(SpringBootEventApplication.class) // Fluent API
                            // 單元測試是 PORT = RANDOM
                            .properties("server.port=0")  // 隨機向 OS 要可用端口
                            .run(args);
        }
  1. 非 Web 程序方式。現在我們在項目目錄 com.test 創建 MicroservicesProjectApplication.java
package com.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.LinkedHashMap;
import java.util.Map;

@SpringBootApplication
public class MicroservicesProjectApplication {

        public static void main(String[] args) {
                SpringApplication springApplication = new SpringApplication(DemoApplication.class);
                Map<String, Object> properties = new LinkedHashMap<>();
                properties.put("server.port", 0);
                springApplication.setDefaultProperties(properties);
                // 設置為非 web 應用
                      springApplication.setWebApplicationType(WebApplicationType.NONE);
        ConfigurableApplicationContext context = springApplication.run(args);
                // 當前 Spring 應用上下文的類:org.springframework.context.annotation.AnnotationConfigApplicationContext
                System.out.println("當前 Spring 應用上下文的類:" + context.getClass().getName());

點擊實驗樓新課《Spring Cloud 從入門到實戰》,快開始學習之旅!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM