1. 程式人生 > >(轉)Spring Boot(一)

(轉)Spring Boot(一)

new lec 一行 查看 resource 熱啟動 傳統 gmv 其中

(二期)4、springboot的綜合講解

【課程四】springbo...概念.xmind64.5KB

【課程四】spring裝配方式.xmind0.2MB

【課程四預習】spri...解讀.xmind0.1MB

【課程四】springbo...過程.xmind0.3MB

git demo : https://gitee.com/lv-success/git-second/tree/master/course-4-springboot/spring-boot-deep

講課順序:

  • 第一節課程
  • springboot與springmvc的關系
  • springboot與微服務
  • springboot的自動裝配
  • 認識springApplication
  • springboot的啟動過程
  • 第二節課程
  • springboot的異常處理
  • springboot集成redis
  • springboot集成spring session
  • lombok的使用
  • 作業布置
什麽是spring boot

其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。

以前在寫spring項目的時候,要配置各種xml文件。特別是做這種框架集成,比如說ssm框架,就需要配置一堆的xml,還經常會出問題,這樣就降低了開發效率。

隨著spring3,spring4的相繼推出,約定大於配置逐漸成為了開發者的共識,大家也漸漸的從寫xml轉為各種註解的形式,在spring4的項目裏,你甚至可以一行xml都不寫。

但雖然spring4已經可以做到無xml,寫一個大項目需要導入很多的第三方包,maven配置要寫幾百行,這是一件很可怕的事。為了簡化我們的配置,快速集成常用的第三方框架,就有了springboot的誕生。

那麽,spring boot可以做什麽呢?

Spring Boot的功能

Spring Boot實現了自動配置,降低了項目搭建的復雜度。

他本身並不提供Spring框架的核心特性以及擴展功能,只是用於快速、敏捷地開發新的基於Spring框架的應用程序。也就是說,它並不是用來替代Spring的解決方案,而是和Spring框架緊密結合用於提升Spring開發者體驗的工具。同時呢,因為它集成了大量常用的第三方庫配置(例如JDBC, Mongodb, Redis, Mail,rabbitmq等等),所以在Spring Boot應用中這些第三方庫幾乎可以零配置的開箱即用(out-of-the-box),大部分的Spring Boot應用都只需要非常少量的配置代碼,開發者能夠更加專註於業務邏輯。

所以說,Spring Boot只是承載者,輔助你簡化項目搭建過程的。如果承載的是WEB項目,使用Spring MVC作為MVC框架,那麽工作流程和spring mvc是完全一樣的,因為這部分工作是Spring MVC做的而不是Spring Boot。

springboot與springmvc的關系 二者區別

所以說我們談到springboot與spring mvc的關系區別的時候,有這麽一句總結:

Spring 是一個“引擎”;

springmvc是框架,web項目中實際運行的代碼;

spring boot只是一個配置工具,整合工具,輔助工具。是一套快速開發整合包。

Spring Boot :J2EE一站式解決方案

Spring Cloud : 分布式整體解決方案

Spring 最初利用“工廠模式”(DI)和“代理模式”(AOP)解耦應用組件。大家覺得挺好用,於是按照這種模式搞了一個 MVC框架(一些用Spring 解耦的組件),用開發 web 應用( SpringMVC )。然後發現每次開發都寫很多樣板代碼,為了簡化工作流程,於是開發出了一些“懶人整合包”(starter),這套就是 Spring Boot。

springboot與微服務

為什麽說springboot與我們的微服務有關系呢?可以來看下springboot的一些特性~

Spring Boot 特性
  • 使用 Spring 項目引導頁面可以在幾秒構建一個項目
  • 方便對外輸出各種形式的服務,如 REST API、WebSocket、Web、Streaming、Tasks
  • 非常簡潔的安全策略集成
  • 支持關系數據庫和非關系數據庫
  • 支持運行期內嵌容器,如 Tomcat、Jetty
  • 強大的開發包,支持熱啟動
  • 自動管理依賴
  • 自帶應用監控
  • 支持各種 IED,如 IntelliJ IDEA 、NetBeans

正是因為Spring Boot 的這些特性非常方便、快速構建獨立的微服務。所以我們使用 Spring Boot 開發項目,會給我們傳統開發帶來非常大的便利度,可以說如果你使用過 Spring Boot 開發過項目,就不會再願意以以前的方式去開發項目了。

總結一下,使用 Spring Boot 至少可以給我們帶來以下幾方面的改進:

  • Spring Boot 使編碼變簡單,Spring Boot 提供了豐富的解決方案,快速集成各種解決方案提升開發效率。
  • Spring Boot 使配置變簡單,Spring Boot 提供了豐富的 Starters,集成主流開源產品往往只需要簡單的配置即可。
  • Spring Boot 使部署變簡單,Spring Boot 本身內嵌啟動容器,僅僅需要一個命令即可啟動項目,結合 Jenkins 、Docker 自動化運維非常容易實現。
  • Spring Boot 使監控變簡單,Spring Boot 自帶監控組件,使用 Actuator 輕松監控服務各項狀態。

總結,Spring Boot 是 Java 領域最優秀的微服務架構落地技術,沒有之一。

springboot的三大特性

組件自動裝配:web mvc、jdbc、MongoDB

嵌入式web容器:tomcat、jetty

生產準備特性:指標、健康檢查、外部化配置

  • 不影響功能開發,但是有指導意義
  • 應用是否監控的,微服務是否健康
  • 外部化配置:如server.port,可以改變服務端口等,以前在服務器上改端口
切換web server

tomcat切換成jetty,spring內置的tomcat容器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions><!-- Exclude the Tomcat dependency -->
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency><!-- Use Jetty instead -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

認識springApplication main方法解釋

springboot項目的啟動一般使用Java的main方法來啟動項目,代碼裏面有個run方法,使用SpringBootDeepinApplication來作為參數,為什麽要使用SpringBootDeepinApplication來作為參數,因為@SpringBootApplication也是@Configuration拓展註解,所以初始化的時候其實就是最先加載這個配置類,然後根據註解拓展開來加載各個模塊。

  • 所以,參數不一定是主類。只要是有@SpringBootApplication註解的類都可以成為參數

@SpringBootApplication
public class SpringBootDeepinApplication {

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

boot的準備階段

類加載實現思路:

  1. 實現類
  1. 配置資源META-INF/spring.factories
  1. 排序:@AutoConfigureOrder,@Ordered,實現Ordered接口等方式

  • 加載spring.favorites的自動配置
  • 加載應用監聽器

首先SpringApplication使用主類作為配置參數初始化並加載資源。

SpringApplication application = new SpringApplication(SpringBootDeepinApplication.class);

技術分享圖片

每個模塊中,只要classpath中有spring.favorites就可以裝載有這個兩個配置類的資源。

#加載Spring.favorites中ApplicationContextInitializer的配置類
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));

#加載Spring.favorites中ApplicationListener的配置類
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));

技術分享圖片

關鍵代碼:

#配置加載器,包括註解配置或xml配置
BeanDefinitionLoader

技術分享圖片

boot的運行階段

SpringApplication的run方法就是boot的運行階段的,需要初始化環境,context,發布事件,啟動監聽器等等。

技術分享圖片

spring的手動裝配 spring的模式註解裝配

@Component註解的拓展,“派生註解”-->@Controller、@Service、@Repository、分別和控制層(Web 層)、業務層和持久層相對應...

模式註解的層次性

技術分享圖片

spring的@Enable模塊裝配

激活:@EnableAutoConfiguration

配置:/META-INF/spring.factoryes

實現:XXXAutoConfiguration

框架實現

@Enable 註解模塊 激活模塊

Spring Framework

@EnableWebMvc Web MVC 模塊

@EnableTransaction Management 事務管理模塊

@EnableCaching Caching 模塊

@EnableMBeanExport JMX 模塊

@EnableAsync 異步處理模塊

@EnableWebFlux Web Flux 模塊

@EnableAspectJAutoProxy AspectJ 代理模塊

Spring Boot

@EnableAutoConfiguration 自動裝配模塊

@EnableManagementContext Actuator 管理模塊

@EnableConfigurationProperties 配置屬性綁定模塊

@EnableOAuth2Sso OAuth2 單點登錄模塊

Spring Cloud

@EnableEurekaServer Eureka服務器模塊

@EnableConfigServer 配置服務器模塊

@EnableFeignClients Feign客戶端模塊

@EnableZuulProxy 服務網關 Zuul 模塊

@EnableCircuitBreaker 服務熔斷模塊

自定義@Enable模塊

1、基於註解驅動實現,可參考@EnableWebMvc註解

第一步:自定義@EnableXXX註解,其中@Import表示把用到的資源導入到當前容器中,相當於導入一個@Configuration配置類

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({SayHelloWorldConfiguration.class})
public @interface EnableSayHelloWorld {

}

第二步、編寫配置類,配置類中把需要的bean註入到spring容器中,因為已經有了第一步的@Import,所以這裏不再需要@Configuration註解。

//@Configuration
public class SayHelloWorldConfiguration {

    @Bean
    SayHelloWorld sayHelloWorld() {
        System.out.println("here to loading bean sayhelloworld!");
        return new SayHelloWorld();
    }
}

//需要初始化的bean
public class SayHelloWorld {

    public String say() {
        return "hello world";
    }

}

第三步、在啟動項目時候加上@EnableSayHelloWorld註解,表示加載自定義的配置。@EnableSayHelloWorld是@Import的拓展註解,實際起作用的是@Import註解。

@EnableSayHelloWorld
@SpringBootApplication
public class SpringBootDeepinApplication {

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

2、基於接口驅動實現,參考@EnableCaching註解

相比註解形式,接口驅動實現更加靈活,可以添加分支或根據條件判斷來初始化程序。

大概步驟:

HelloWorldImportSelector -> HelloWorldConfiguration -> HelloWorld

第一步、自定義註解@EnableSeletorHelloWorld

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({HelloWorldImportSeletor.class})
public @interface EnableSeletorHelloWorld {

    String model() default "first";
}

第二步、編寫Seletor,實現ImportSeletor這個借口,並重寫SelectImports方法,返回的數組表示需要初始化註入到spring容器的中的bean名稱。

public class HelloWorldImportSeletor implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {

        //獲取註解上的屬性的值
        Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableSeletorHelloWorld.class.getName());
        String model = (String) annotationAttributes.get("model");
        System.out.println(model);

        //可以返回多個加載的配置或bean
        return new String[]{SayHelloWorldConfiguration.class.getName()};
    }
}

其余與註解形式相同,這裏略~

spring條件裝配

定義:Bean裝配的前置條件

舉例:@Profile、@Conditional

1、註解方式

@Profile 配置條件裝配

略~

2、編程方式

@Conditional 編程條件裝配,

可參考org.springframework.boot.autoconfigure.condition.ConditionalOnProperty

第一步、編寫條件註解。用於判斷系統是否是linux,當linux的時候初始化對應的配置。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnSystemPropertyCondition.class})
public @interface ConditionalOnSystemProperty {

    String value();
}

第二步、編寫條件判斷類OnSystemPropertyCondition,實現org.springframework.context.annotation.Condition接口,重寫match方法用於判斷條件返回true或false;

public class OnSystemPropertyCondition implements Condition {

    /**
     * 判斷是否滿足條件
     * @param conditionContext
     * @param annotatedTypeMetadata 註解的元信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> attrs = annotatedTypeMetadata.getAnnotationAttributes(ConditionalOnSystemProperty.class.getName());

        String system = String.valueOf(attrs.get("value"));
        String currentOs = System.getProperty("os.name");
        return currentOs.endsWith(system);
    }
}

第三步、在需要做判斷才能初始化的bean上添加此註解即可完成條件裝配

@ConditionalOnSystemProperty(value = "linux")
springboot的自動裝配模式 Java SPI機制

Java SPI是什麽?

SPI的全名為Service Provider Interface.大多數開發人員可能不熟悉,因為這個是針對廠商或者插件的。

我們系統裏抽象的各個模塊,往往有很多不同的實現方案,比如日誌模塊的方案,xml解析模塊、jdbc模塊的方案等。

面向的對象的設計裏,我們一般推薦模塊之間基於接口編程,模塊之間不對實現類進行硬編碼。一旦代碼裏涉及具體的實現類,就違反了可拔插的原則,如果需要替換一種實現,就需要修改代碼。為了實現在模塊裝配的時候能不在程序裏動態指明,這就需要一種服務發現機制。

Java SPI就是提供這樣的一個機制:為某個接口尋×××實現的機制。

Java SPI的約定

當服務的提供者,提供了服務接口的一種實現之後,在jar包的META-INF/services/目錄裏同時創建一個以服務接口命名的文件。

該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能通過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的註入。

基於這樣一個約定就能很好的找到服務接口的實現類,而不需要再代碼裏制定。

SpringBoot中的SPI機制

在Spring中也有一種類似與Java SPI的加載機制。它在META-INF/spring.factories文件中配置接口的實現類名稱,然後在程序中讀取這些配置文件並實例化。

這種自定義的SPI機制是Spring Boot Starter實現的基礎。

實現原則

理念:約定大於配置原則

裝配:模式裝配、@Enable註解裝配、條件裝配

步驟:激活自動裝配、實現自動裝配、配置自動裝配

starter:啟動器

底層裝配技術
  • Spring 模式註解裝配
  • Spring @Enable 模塊裝配
  • Spring 條件裝配裝配
  • Spring 工廠加載機制
  • 實現類: SpringFactoriesLoader (類似與Java SPI機制的一個加載類)
  • 配置資源: META-INF/spring.factories

加載類SpringFactoriesLoader說明:

spring的工廠加載類SpringFactoriesLoader,用於加載自動配置,主要方法loadFactories(),參數factoryClass表示要加載的工廠配置類,classLoader表示類加載器。

配置文件META-INF/spring.factories說明:

技術分享圖片

技術分享圖片

自定義自動條件裝配

步驟:

  • HelloWorldAutoConfiguration
  • 條件判斷: user.name == "Mercy"
  • 模式註解: @Configuration @Enable 模塊: @EnableHelloWorld -> HelloWorldImportSelector -> HelloWorldConfiguration - > helloWorld

查看這個類WebMvcAutoConfiguration,可以看到這個配置類就用了條件裝配。

@Configuration
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
 ...
}

@ConditionalOnMissingBean表示當容器中沒有這個bean的時候

@ConditionalOnClass表示對應的類在classpath目錄下存在時

@ConditionalOnWebApplication表示當前項目是個servlet項目的時候

第一步、編寫需要自動裝載的配置類,因為@Configuration註解的存在,因此我把需要自動裝載的配置類放在了springboot掃描不到的包上。

說明:

@Configuration表示是個配置類

@ConditionalOnSystemProperty表示需要滿足當前系統是win10系統

@EnableSeletorHelloWorld表示啟動這個模塊的加載

@Configuration
@ConditionalOnSystemProperty(value = "Windows 10")
@EnableSeletorHelloWorld
public class SayHelloWorldAutoConfiguration {


    @Bean
    SayHelloWorld autoSayHelloWorld() {
        System.out.println("here to !!auto!! loading bean autoSayHelloWorld!");
        return new SayHelloWorld();
    }
}

第二步、在resources目錄下新建META-INF文件夾,編寫spring.factories。

# Auto Configure 自動裝配自定義的配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.other.configuration.SayHelloWorldAutoConfiguration

啟動springboot之後就會自動加載這個配置類~

第二天的課程內容:

springboot的異常處理 springboot集成redis springboot集成spring session springboot的打包方式

(轉)Spring Boot(一)