Spring是一個開源框架,2003 年興起的一個輕量級的Java 開發框架,作者:Rod Johnson 。
Spring是為了解決企業級應用開發的復雜性而創建的,簡化開發。
java筆記總結,為了降低Java開發的復雜性,Spring采用了以下4種關鍵策略:
1、基于POJO的輕量級和最小侵入性編程,所有東西都是bean;
2、通過IOC,依賴注入(DI)和面向接口實現松耦合;
javaweb筆記,3、基于切面(AOP)和慣例進行聲明式編程;
4、通過切面和模版減少樣式代碼,RedisTemplate,xxxTemplate;
學過javaweb的同學就知道,開發一個web應用,從最初開始接觸Servlet結合Tomcat, 跑出一個Hello Wolrld程序,是要經歷特別多的步驟;后來就用了框架Struts,再后來是SpringMVC,到了現在的SpringBoot,過一兩年又會有其他web框架出現;你們有經歷過框架不斷的演進,然后自己開發項目所有的技術也在不斷的變化、改造嗎?建議都可以去經歷一遍;
Springboot注解,言歸正傳,什么是SpringBoot呢,就是一個javaweb的開發框架,和SpringMVC類似,對比其他javaweb框架的好處,官方說是簡化開發,約定大于配置, you can “just run”,能迅速的開發web應用,幾行代碼開發一個http接口。
所有的技術框架的發展似乎都遵循了一條主線規律:從一個復雜應用場景 衍生 一種規范框架,人們只需要進行各種配置而不需要自己去實現它,這時候強大的配置功能成了優點;發展到一定程度之后,人們根據實際生產應用情況,選取其中實用功能和設計精華,重構出一些輕量級的框架;之后為了提高開發效率,嫌棄原先的各類配置過于麻煩,于是開始提倡“約定大于配置”,進而衍生出一些一站式的解決方案。
是的這就是Java企業級應用->J2EE->spring->springboot的過程。
redis實踐?隨著 Spring 不斷的發展,涉及的領域越來越多,項目整合開發需要配合各種各樣的文件,慢慢變得不那么易用簡單,違背了最初的理念,甚至人稱配置地獄。Spring Boot 正是在這樣的一個背景下被抽象出來的開發框架,目的為了讓大家更容易的使用 Spring 、更容易的集成各種常用的中間件、開源軟件;
Spring Boot 基于 Spring 開發,Spirng Boot 本身并不提供 Spring 框架的核心特性以及擴展功能,只是用于快速、敏捷地開發新一代基于 Spring 框架的應用程序。也就是說,它并不是用來替代 Spring 的解決方案,而是和 Spring 框架緊密結合用于提升 Spring 開發者體驗的工具。Spring Boot 以約定大于配置的核心思想,默認幫我們進行了很多設置,多數 Spring Boot 應用只需要很少的 Spring 配置。同時它集成了大量常用的第三方庫配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 應用中這些第三方庫幾乎可以零配置的開箱即用。
簡單來說就是SpringBoot其實不是什么新的框架,它默認配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架 。
Spring Boot 出生名門,從一開始就站在一個比較高的起點,又經過這幾年的發展,生態足夠完善,Spring Boot 已經當之無愧成為 Java 領域最熱門的技術。
Spring Boot的主要優點:
為所有Spring開發者更快的入門
開箱即用,提供各種默認配置來簡化項目配置
內嵌式容器簡化Web項目
沒有冗余代碼生成和XML配置的要求
真的很爽,我們快速去體驗開發個接口的感覺吧!
官方文檔: https://spring.io/projects/spring-boot
中文文檔: https://www.springcloud.cc/spring-boot.html
2、微服務介紹
2.1、什么是微服務
? 隨著互聯網的發展,網站應用的規模不斷擴大,常規的垂直應用架構已無法應對,分布式服務架構以及流動計算架構勢在必行,亟需一個治理系統確保架構有條不紊的演進。
? 微服務是一種架構風格,他要求我們在開發一個應用的時候,這個應用必須構建成一系列小服務的組合;可以通過http的方式進行互通。要說微服務架構,先得說說過去的單體應用架構。
單一應用架構
? 所謂單體應用架構(all in one)是指,我們將一個應用的中的所有應用服務都封裝在一個應用中。
? 無論是ERP.CRM或是其他什么系統,你都把數據庫訪問,web訪問,等等各個功能放到一個war包內。
垂直應用架構
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,提升效率的方法之一是將應用拆成互不相干的幾個應用,以提升效率。此時,用于加速前端頁面開發的Web框架(MVC)是關鍵。
分布式服務架構
當垂直應用越來越多,應用之間交互不可避免,將核心業務抽取出來,作為獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。此時,用于提高業務復用及整合的分布式服務框架(RPC)是關鍵。
流動計算架構
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增加一個調度中心基于訪問壓力實時管理集群容量,提高集群利用率。此時,用于提高機器利用率的資源調度和治理中心(SOA)是關鍵。
微服務架構
all in one的架構方式,我們把所有的功能單元放在一個應用里面。然后我們把整個應用部署到服務器上。如果負載能力不行,我們將整個應用進行水平復制,進行擴展,然后在負載均衡。
所謂微服務架構,就是打破之前all in one的架構方式,把每個功能元素獨立出來。把獨立出來的功能元素的動態組合,需要的功能元素才去拿來組合。需要多一些時可以整合多個功能元素。所以微服務架構是對功能元素進行復制,而沒有對整個應用進行復制。
這樣做的好處是:
2.2、如何構建微服務
一個大型系統的微服務架構,就像一個復雜交織的神經網絡,每一個神經元就是一個功能元素,它們各自完成自己的功能,然后通過http相互請求調用。比如一個電商系統,查緩存、連數據庫、瀏覽頁面、結賬、支付等服務都是一個個獨立的功能服務,都被微化了,它們作為一個個微服務共同構建了一個龐大的系統。如果修改其中的一個功能,只需要更新升級其中一個功能服務單元即可。
但是這種龐大的系統架構給部署和運維帶來很大的難度。于是,spring為我們帶來了構建大型分布式微服務的全套、全程產品:
構建一個個功能獨立的微服務應用單元,可以使用springboot,可以幫我們快速構建一個應用;
大型分布式網絡服務的調用,這部分由spring cloud來完成,實現分布式;
在分布式中間,進行流式數據計算、批處理,我們有spring cloud data flow,
spring為我們想清楚了整個從開始構建應用到大型分布式應用全流程方案。
3、第一個SpringBoot程序
Spring官方提供了非常方便的工具讓我們快速構建應用
Spring Initializr: https://start.spring.io/
3.1、創建SpringBoot項目
創建方式一:使用Spring Initializr 的 Web頁面創建項目
**創建方式二:**使用 IDEA 直接創建項目
3.2、解決idea2020.2版本創建SpringBoot項目卡死在Reading pom.xml
移除工程目錄/.mvn/maven-wrapper.properties 文件,
刪除項目目錄下不需要的文件
重新打開idea,再根據路徑open一下項目
但是感覺好麻煩!!!!
找了解決方法: 找到 C:\Users\22315.m2\wrapper\dists
將maven換做自己的,并且配置阿里云鏡像
補充: 后來發現創建創建項目時存放路徑變了,還是會有同樣的問題,所以建議換2019.3 或者 2020.1版本
啟動后
啟動成功后訪問 localhost:8080
項目結構分析:
通過上面步驟完成了基礎項目的創建。就會自動生成以下文件。
1、程序的主啟動類
2、一個 application.properties 配置文件
3、一個 測試類
4、一個 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><!-- 父依賴 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>hello</artifactId><version>0.0.1-SNAPSHOT</version><name>hello</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!-- web場景啟動器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- springboot單元測試 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><!-- 打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
3.3、Hello World
在主程序的同級目錄下,新建一個controller包,一定要在同級目錄下,否則識別不到
@RestController
public class HelloSpringBoot {//接口 http://localhost:8080/hello@RequestMapping("/hello")public String hello(){return "Hello World";}
}
訪問 http://localhost:8080/hello
3.4、將項目打成jar包
如果遇到 錯誤,可以配置打包時 跳過項目運行測試用例
<!-- 在工作中,很多情況下我們打包是不想執行測試用例的可能是測試用例不完事,或是測試用例會影響數據庫數據跳過測試用例執
-->
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><!--跳過項目運行測試用例--><skipTests>true</skipTests></configuration>
</plugin>
如果打包成功,則會在target目錄下生成一個 jar 包
打成了jar包后,就可以在任何地方運行了!OK
3.5、彩蛋
1、修改項目的端口號
2、更改啟動時顯示的字符拼成的字母
只需一步:到項目下的 resources 目錄下新建一個banner.txt 即可。
圖案可以到:https://www.bootschool.net/ascii 這個網站生成,然后拷貝到文件中即可!
SpringBoot這么簡單的東西背后一定有故事,我們一起去進行一波源碼分析!
4、運行原理初探
4.1、父依賴
其中它主要是依賴一個父項目,主要是管理項目的資源過濾及插件!
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version><relativePath/> <!-- lookup parent from repository -->
</parent>
點進去,發現還有一個父依賴
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.5.RELEASE</version><relativePath>../../spring-boot-dependencies</relativePath>
</parent>
這里才是真正管理SpringBoot應用里面所有依賴版本的地方,SpringBoot的版本控制中心;
我們是寫或者引入一些SpringBoot依賴的時候,不需要指定版本,因為有這些版本倉庫
以后我們導入依賴默認是不需要寫版本;但是如果導入的包沒有在依賴中管理著就需要手動配置版本了;
4.2、啟動器 spring-boot-starter
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
啟動器:說白了就是SpringBoot的啟動場景;
springboot-boot-starter-xxx:就是spring-boot的場景啟動器
spring-boot-starter-web:幫我們導入了web模塊正常運行所依賴的組件;
SpringBoot將所有的功能場景都抽取出來,做成一個個的starter (啟動器),只需要在項目中引入這些starter即可,所有相關的依賴都會導入進來 , 我們要用什么功能就導入什么樣的場景啟動器即可 ;我們未來也可以自己自定義 starter;
4.3、主啟動類
默認的主啟動類
//@SpringBootApplication 來標注一個主程序類
//說明這是一個Spring Boot應用
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {//以為是啟動了一個方法,沒想到啟動了一個服務SpringApplication.run(SpringbootApplication.class, args);}
}
但是一個簡單的啟動類并不簡單!
@SpringBootApplication
作用:標注在某個類上說明這個類是SpringBoot的主配置類 , SpringBoot就應該運行這個類的main方法來啟動SpringBoot應用;
進入這個注解:可以看到上面還有很多其他注解!
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}
), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {// ......
}
@ComponentScan
這個注解在Spring中很重要 ,它對應XML配置中的元素。
作用:自動掃描并加載符合條件的組件或者bean , 將這個bean定義加載到IOC容器中
@SpringBootConfiguration
作用:SpringBoot的配置類 ,標注在某個類上 , 表示這是一個SpringBoot的配置類;
// 點進去得到下面的 @Component
@Configuration
public @interface SpringBootConfiguration {}@Component //說明這也是一個spring的組件
public @interface Configuration {}
這里的 @Configuration,說明這是一個配置類 ,配置類就是對應Spring的xml 配置文件;
里面的 @Component 這就說明,啟動類本身也是Spring中的一個組件而已,負責啟動應用!
@EnableAutoConfiguration 自動配置功能
以前我們需要自己配置的東西,而現在SpringBoot可以自動幫我們配置 ;@EnableAutoConfiguration告訴SpringBoot開啟自動配置功能,這樣自動配置才能生效;
點進注解接續查看:
@AutoConfigurationPackage :自動配置包
@Import({Registrar.class}) //導入選擇器包注冊
public @interface AutoConfigurationPackage {String[] basePackages() default {};Class<?>[] basePackageClasses() default {};
}
@import :Spring底層注解@import , 給容器中導入一個組件
Registrar.class 作用:將主啟動類的所在包及包下面所有子包里面的所有組件掃描到Spring容器 ;
這個分析完了,退到上一步,繼續看
@Import({AutoConfigurationImportSelector.class}) :給容器導入組件 ;
AutoConfigurationImportSelector :自動配置導入選擇器,那么它會導入哪些組件的選擇器呢?我們點擊去這個類看源碼:
1、這個類中有一個這樣的方法
// 獲得候選的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {//這里的getSpringFactoriesLoaderFactoryClass()方法//返回的就是我們最開始看的啟動自動導入配置文件的注解類;EnableAutoConfigurationList<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");return configurations;
}
2、這個方法又調用了 SpringFactoriesLoader 類的靜態方法!我們進入SpringFactoriesLoader類loadFactoryNames() 方法
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName();//這里它又調用了 loadSpringFactories 方法return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
3、我們繼續點擊查看 loadSpringFactories 方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {//獲得classLoader , 我們返回可以看到這里得到的就是EnableAutoConfiguration標注的類本身MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);if (result != null) {return result;} else {try {//去獲取一個資源 "META-INF/spring.factories"Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");LinkedMultiValueMap result = new LinkedMultiValueMap();//將讀取到的資源遍歷,封裝成為一個Propertieswhile(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();String factoryClassName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryName = var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}}
}
4、發現一個多次出現的文件:spring.factories,全局搜索它
spring.factories
我們根據源頭打開spring.factories , 看到了很多自動配置的文件;這就是自動配置根源所在!
WebMvcAutoConfiguration
我們在上面的自動配置類隨便找一個打開看看,比如 :WebMvcAutoConfiguration
可以看到這些一個個的都是JavaConfig配置類,而且都注入了一些Bean,可以找一些自己認識的類,看著熟悉一下!
所以,自動配置真正實現是從classpath中搜尋所有的META-INF/spring.factories配置文件 ,并將其中對應的org.springframework.boot.autoconfigure. 包下的配置項,通過反射實例化為對應標注了 @Configuration的JavaConfig形式的IOC容器配置類 , 然后將這些都匯總成為一個實例并加載到IOC容器中。
Properties properties = PropertiesLoaderutils.loadProperties(resource);
//所有的資源加載到配置類中
SpringBoot所有自動裝配都是在啟動的時候掃描并加載:spring.factories所有的自動配置類都在這里面,但是不一定生效,要判斷條件是否成立,只要導入了對應的start,就有對應的啟動器了,有了啟動器,我們自動裝配就會生效,然后就配置成功!
結論:
SpringApplication
不簡單的方法
我最初以為就是運行了一個main方法,沒想到卻開啟了一個服務;
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {SpringApplication.run(SpringbootApplication.class, args);}
}
SpringApplication.run分析
分析該方法主要分兩部分,一部分是SpringApplication的實例化,二是run方法的執行;
SpringApplication
這個類主要做了以下四件事情:
1、推斷應用的類型是普通的項目還是Web項目
2、查找并加載所有可用初始化器 , 設置到initializers屬性中
3、找出所有的應用程序監聽器,設置到listeners屬性中
4、推斷并設置main方法的定義類,找到運行的主類
查看構造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {// ......this.webApplicationType = WebApplicationType.deduceFromClasspath();this.setInitializers(this.getSpringFactoriesInstances();this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = this.deduceMainApplicationClass();
}
4.4、run方法流程分析
5、yaml配置注入
5.1、配置文件
SpringBoot使用一個全局的配置文件 , 配置文件名稱是固定的
語法結構 :key=value
語法結構 :key:空格 value
配置文件的作用: 修改SpringBoot自動配置的默認值,因為SpringBoot在底層都給我們自動配置好了;
比如我們可以在配置文件中修改Tomcat 默認啟動的端口號!測試一下!
server.port=8081
5.2、yaml概述
YAML是 “YAML Ain’t a Markup Language” (YAML不是一種標記語言)的遞歸縮寫。在開發的這種語言時,YAML 的意思其實是:“Yet Another Markup Language”(仍是一種標記語言)
這種語言以數據作為中心,而不是以標記語言為重點!
以前的配置文件,大多數都是使用xml來配置;比如一個簡單的端口配置,我們來對比下yaml和xml
傳統xml配置:
<server><port>8081<port>
</server>
yaml配置:
server: prot: 8080
5.2.1、yaml基礎語法
說明:語法要求嚴格!
1、空格不能省略
2、以縮進來控制層級關系,只要是左邊對齊的一列數據都是同一個層級的。
3、屬性和值的大小寫都是十分敏感的。
字面量:普通的值 [ 數字,布爾值,字符串 ]
字面量直接寫在后面就可以 , 字符串默認不用加上雙引號或者單引號;
k: v
注意:
“ ” 雙引號,不會轉義字符串里面的特殊字符 , 特殊字符會作為本身想表示的意思;
比如 :name: “kuang \n shen” 輸出 :kuang 換行 shen
‘’ 單引號,會轉義特殊字符 , 特殊字符最終會變成和普通字符一樣輸出
比如 :name: ‘kuang \n shen’ 輸出 :kuang \n shen
對象、Map(鍵值對)
#對象、Map格式
k: v1:v2:
在下一行來寫對象的屬性和值得關系,注意縮進;比如:
student:name: qinjiangage: 3
數組( List、set )
用 - 值表示數組中的一個元素,比如:
pets:- cat- dog- pig
行內寫法
student: {name: qinjiang,age: 3}
pets: [cat,dog,pig]
修改SpringBoot的默認端口號
配置文件中添加,端口號的參數,就可以切換端口;
server:port: 8082
5.3、yaml注入配置文件
yaml文件更強大的地方在于,他可以給我們的實體類直接注入匹配值!
1、在springboot項目中的resources目錄下新建一個文件 application.yml
2、編寫一個實體類 Dog;
ackage com.kuang.springboot.pojo;@Component //注冊bean到容器中
public class Dog {private String name;private Integer age;//有參無參構造、get、set方法、toString()方法
}
3、思考,我們原來是如何給bean注入屬性值的!@Value,給狗狗類測試一下:
@Component //注冊bean
public class Dog {@Value("阿黃")private String name;@Value("18")private Integer age;
}
4、在SpringBoot的測試類下注入狗狗輸出一下;
@SpringBootTest
class DemoApplicationTests {@Autowired //將狗狗自動注入進來Dog dog;@Testpublic void contextLoads() {System.out.println(dog); //打印看下狗狗對象}}
結果成功輸出,@Value注入成功,這是我們原來的辦法。
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态