淺學(xué)Spring Boot
Spring Boot是Spring的擴展萨醒,在保持了Spring原有兩大特性的前提下又提出了新的功能斟珊。
因此,正式介紹Spring Boot之前验靡,我們不妨先來探尋一下Spring是個什么東西倍宾!
Spring
框架開發(fā)的初心都是為了降低程序員寫代碼時的復(fù)雜度,能夠讓程序員將自己的精力盡可能多的集中到自己的邏輯開發(fā)上面胜嗓,而不是在開發(fā)環(huán)境的配置上面高职。為了實現(xiàn)這一點,Spring提出了以下兩個技術(shù):面向切面編程和依賴注入辞州。
面向切面編程(AOP)
面向切面編程怔锌,通俗來說就是把專業(yè)的活交給專業(yè)的人來干。舉個例子变过,就像在學(xué)校里有很多食堂埃元,這些食堂都被不同的餐飲公司所承包,這里被承包了的食堂就是切面媚狰。這樣做有什么好處呢岛杀,很明顯,食堂承包出去之后由于餐飲公司是專門做餐飲的崭孤,那飯菜肯定比學(xué)校自己做的好吃类嗤,而且學(xué)校將餐飲業(yè)務(wù)承包出去之后糊肠,就可以將自己更多的精力放在教書育人上邊,專注于自己的本職業(yè)務(wù)遗锣,如果對承包商不滿意還可以即時的更換其他承包商(更換切面)货裹,真是個一舉多得的好事情,在編程當(dāng)中精偿,什么是這些切面呢弧圆?對象與對象之間,方法與方法之間笔咽,模塊與模塊之間都是一個個這樣的切面搔预。
單一職責(zé)原則:類應(yīng)該是純凈的,不應(yīng)含有與本身無關(guān)的邏輯拓轻。
面向切面編程斯撮,可以帶來代碼的解耦,使得各個模塊專注于自身的業(yè)務(wù)邏輯扶叉,提高開發(fā)效率勿锅。
使用AOP之前,我們需要理解幾個概念枣氧。
傳送門:Spring 之 AOP
- 連接點(Join Point):
所有可能的需要注入切面的地方溢十。比如方法前后,類初始化达吞、屬性初始化前后张弛。
- 切點(Poincut):
需要做某些處理的連接點(連接點有很多,但是真正切入的連接點才叫切點)酪劫,比如打印日志吞鸭、處理緩存等,存在于切面當(dāng)中覆糟。目前刻剥,Spring只支持方法的切點定義。
- 通知(Advice):
定義在什么時候滩字,做什么事情造虏。Spring支持5種方法上的通知類型。
@Before:在目標(biāo)方法被調(diào)用之前調(diào)用麦箍。
@After:通知方法會在目標(biāo)方法返回或拋出異常之后調(diào)用漓藕。
@AfterReturning:通知方法會在目標(biāo)方法返回后調(diào)用。
@AfterThrowing:通知方法會在目標(biāo)方法拋出異常之后調(diào)用挟裂。
@Around:相當(dāng)于Befor和After的結(jié)合享钞。
- 切面(Aspect)
通知+切點的集合,定義在什么地方什么時間做什么事情诀蓉。
@Aspect
public class Audience {
@Autowired
private CriticismEngineImpl criticismEngine;
@Pointcut(
"execution(* com.example.aoptest.impl.Performance.perform(int))"+"&& args(ha)")//將perform函數(shù)視為切點
public void performance(int ha) {}//該方法本身只是個標(biāo)識嫩与,供Advice依附寝姿,對performance函數(shù)的通知相當(dāng)于對切點perform函數(shù)的通知交排。
@Before("performance(ha)")//通知
public void silenceCellPhones(int ha)
{
ha++;
System.out.println(ha);
System.out.println("前置通知:Sillencing cell phones");
}
}
- 引入(Introduction)
允許我們向現(xiàn)有的類添加新方法或?qū)傩曰獭>褪前亚忻嬗玫侥繕?biāo)類當(dāng)中,在不修改目標(biāo)類的條件下為目標(biāo)類添加新的屬性和方法埃篓。
依賴注入
在Java程序中处坪,一個業(yè)務(wù)邏輯經(jīng)常需要兩個或兩個以上的對象協(xié)作來完成,通常每個對象在使用他的合作對象時架专,自己均要使用像new object()這樣的語法來完成合作對象的申請工作同窘,這樣會使得對象之間的耦合度較高,程序結(jié)構(gòu)比較復(fù)雜部脚。而依賴注入的思想是:由Spring來負(fù)責(zé)控制對象的生命周期和對象間的關(guān)系想邦,對象只需要負(fù)責(zé)關(guān)心業(yè)務(wù)邏輯就好了。
創(chuàng)建應(yīng)用對象之間協(xié)作關(guān)系的行為通常稱為裝配(wiring),這也是依賴注入的本質(zhì)委刘。在Spring中依賴注入有多種方式丧没,我們在這里先來介紹一下配置Spring容器最常見的三種方法。
自動化裝配bean
Spring從兩個角度來實現(xiàn)自動化裝配:
組件掃描(component scanning):Spring會自動發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean锡移。
自動裝配(autowiring):Spring自動實現(xiàn)bean之間的依賴呕童。
為了闡述組件掃描和裝配,我們需要裝配幾個bean淆珊,它們代表一個音響系統(tǒng)中的組件夺饲。首先,創(chuàng)建一個CompactDisc接口和它的實現(xiàn)CompactDiscImp,并將其創(chuàng)建為一個bean施符。然后往声,會創(chuàng)建一個CDPlayer類,讓Spring發(fā)現(xiàn)它戳吝,并將bean注入進來浩销。
CompactDisc接口在Java中定義了CD的概念
public interface CompactDisc{
void play();
}
我們將CompactDisc定義為一個接口,它定義了CD播放器的一系列操作骨坑,而且作為接口撼嗓,它將CD的任意實現(xiàn)與CD本身的耦合降低到了最小的程度。這里欢唾,我們還需要一個CD的實現(xiàn)且警,也就是CompactDiscImp類。
CompactDiscImp實現(xiàn)類
@Component
public class CompactDiscImp implements CompactDisc{
private String title = "這是實現(xiàn)類";
public void play()
{
System.out.println(title);
}
}
和接口一樣礁遣,CompactDiscImp的具體內(nèi)容并不重要斑芜,你需要注意的是CompactDiscImp類上使用了@Component注解。這個簡單的注解表明該類會作為組件類祟霍,并告知Spring要為這個類創(chuàng)建bean杏头。不過盈包,組件掃描默認(rèn)是不啟用的。我們還需要顯示配置Spring醇王,從而命令它去尋找?guī)в蠤Component注解的類呢燥,并為其創(chuàng)建bean。
@ComponentScan注解啟用了組件掃描(CDPlayerConfig.class)
@Configurzation
@ComponentScan
public class CDPlayerConfig
{
}
類CDPlayerConfig通過Java代碼定義了Spring的裝配規(guī)則寓娩。在本文后部分叛氨,我們還會更為詳細(xì)的介紹基于Java的Spring配置。不過棘伴,現(xiàn)在我們只需觀察CDPlayerConfig類并沒有顯示地聲明任何bean寞埠,只不過它使用了@ComponentScan注解,這個注解能夠在Spring中啟用組件掃描焊夸,使得Spring去尋找?guī)в蠤ComponentScan注解地類仁连,并為其創(chuàng)建bean。(此處也可以通過使用XML來啟用組件掃描阱穗,但作者更喜歡使用JAVA配置饭冬,這里就不做贅述,如果有對XML配置感興趣的颇象,可以去查看Spring in Action的第二章)
通過自動裝配伍伤,將一個CompactDisc注入到CDPlayer之中
public class CDPlayer
{
@Autowired//由于本實例只有一種實現(xiàn)類,所以默認(rèn)注入對象為CompactDiscImp的實例遣钳,若有多個實現(xiàn)類扰魂,可用@Qualifier注解加以區(qū)分
private CompactDisc cd;//不通過new對象的方式,而是通過注入的形式創(chuàng)建了一個其他類的對象
cd.play();//會打印出“這是實現(xiàn)類”
}
這就實現(xiàn)了蕴茴,自動裝備bean的方式劝评。
通過Java代碼裝配bean
盡管在很多場景下通過組件掃描和自動裝配實現(xiàn)Spring的自動化配置是更為推薦的方式,但有時候自動化配置的方案行不通倦淀,因此需要明確配置Spring蒋畜。比如說,你想要將第三方庫中的組件配到你的應(yīng)用當(dāng)中撞叽,這種情況你無法直接在第三方庫的源碼上添加@Component和@Autowired注解姻成,因此就不能使用自動化裝配的方案了。
在這種情況下愿棋,你必須要采用顯示裝配的方式科展。在進行顯示配置的時候,有兩種方案可選:Java和XML糠雨。XML我在這里不作贅述才睹,有興趣的同學(xué)可以自行查閱《Spring in Action》第二章第四節(jié),在這里我只介紹使用Java進行配置的方式。
進行顯示配置時琅攘,JavaConfig是更好的方案垮庐,因為他更為強大,類型安全而且對于重構(gòu)比較友好坞琴,不同于其他的Java代碼哨查,JavaConfig是配置代碼,它不應(yīng)該含有任何業(yè)務(wù)邏輯置济,最好將其放在業(yè)務(wù)邏輯之外的包中解恰。還是之前的例子。
@ComponentScan注解啟用了組件掃描(CDPlayerConfig.class)
@Configurzation
@ComponentScan
public class CDPlayerConfig
{
}
創(chuàng)建JavaConfig類的關(guān)鍵在于為其添加@Configuration注解浙于,@Configuration注解表明這個類是一個配置類。@ComponentScan啟用了組件掃描挟纱,這是實現(xiàn)自動裝配的關(guān)鍵羞酗。但如果我們將@ComponentScan注解移除,此時的@CDPlayerConfig類就不會有任何作用了紊服,現(xiàn)在再運行主函數(shù)檀轨,會拋出BeanCreation-Exception異常。這是因為主函數(shù)期望被注入CompactDisc,但是這些bean根本就沒有被創(chuàng)建欺嗤,那我們?nèi)绾芜M行顯式的java配置呢参萄?
要在JavaConfig中聲明bean,我們需要編寫一個方法煎饼,這個方法會創(chuàng)建所需類型的實例讹挎,然后給這個方法添加@Bean注解。
使用Javaconfig顯式裝配bean(CDPlayerConfig.class)
@Configurzation
public class CDPlayerConfig
{
@Bean
public CompactDisc javaconfig()
{
return new CompactDiscImp();
}
}
@Bean注解會告訴Spring這個方法會返回一個對象吆玖,該對象要注冊為Spring應(yīng)用上下文中的bean筒溃。
通過Java裝配,將一個CompactDisc注入到CDPlayer之中
public class CDPlayer
{
@Autowired//由于本實例只有一種實現(xiàn)類沾乘,所以默認(rèn)注入對象為CompactDiscImp的實例怜奖,若有多個實現(xiàn)類,可用@Qualifier注解加以區(qū)分
private CompactDisc cd;//不通過new對象的方式翅阵,而是通過注入的形式創(chuàng)建了一個其他類的對象
cd.play();//會打印出“這是實現(xiàn)類”
}
Spring Boot
Spring Boot是Spring的擴展歪玲,在Spring的AOP(面向切面編程)和DI(依賴注入)兩個特性的基礎(chǔ)上又完善了以下四個功能。
自動配置:針對很多Spring應(yīng)用程序所常見的應(yīng)用功能掷匠,Spring boot能自動提供相關(guān)配置滥崩。
起步依賴:告訴Spring Boot需要什么功能,它就能引入需要的庫槐雾。
命令行界面:這是Spring Boot的可選特性夭委,借此你只需寫代碼就能完成完整的應(yīng)用程序,無需傳統(tǒng)項目構(gòu)建。
Actuator:讓你能夠深入運行中的Spring Boot應(yīng)用程序株灸,一探究竟崇摄。
自動配置
在任何Spring應(yīng)用的源碼中,你都會找到Java配置或XML配置(自動化配置難以配置第三方庫中的組件)慌烧,它們?yōu)閼?yīng)用程序開啟了特定的特性和功能逐抑。舉個例子,如果你寫過用JDBC訪問關(guān)系型數(shù)據(jù)庫的應(yīng)用程序屹蚊,那你一定在Spring應(yīng)用程序上下文里配置過JdbcTemplate這個Bean厕氨。
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
這段非常簡單的Bean聲明創(chuàng)建了一個JdbcTemplate的實例,注入了一個DataSource依賴汹粤,這意味著你還需要配置一個DataSource的Bean命斧,這樣才能滿足依賴。
雖然這兩個Bean配置方法都不復(fù)雜嘱兼,也不是很長国葬,但它們只是Spring應(yīng)用程序配置的一小部分。除此之外芹壕,還有無數(shù)Sping應(yīng)用程序有著類似的配置方法汇四,簡而言之,這就是個樣板配置踢涌。
既然它如此常見通孽,那我們有沒有辦法可以自動配置這些Bean而不是每次手動去寫配置代碼呢?
Spring Boot做到了這點睁壁,它會為這些常見配置場景進行自動配置背苦。如果Spring Boot在應(yīng)用程序的ClassPath里發(fā)現(xiàn)了JdbcTemplate,那么它會為你配置一個JdbcTemplate的Bean堡僻,如果在應(yīng)用程序的Classpath里發(fā)現(xiàn)了DataSource,那么他還會為你創(chuàng)建一個DataSource的Bean糠惫。你無需擔(dān)心那些Bean的配置,Spring Boot會做好準(zhǔn)備钉疫,隨時都能將其注入到你的Bean當(dāng)中硼讽。這就是Spring Boot的自動配置.
起步依賴
Spring boot通過起步依賴為項目的依賴管理提供幫助。起步依賴就是特殊的Maven依賴和Gradle依賴牲阁,利用傳遞依賴解析固阁,幫常用庫聚合在一起。舉個例子城菊,假如你正在用Spring MVC構(gòu)造REST API备燃,并使用JSON作為資源表述。此外凌唬,你還想使用JSR-303規(guī)范的聲明式校驗并齐,并使用嵌入式Tomcat服務(wù)器來提供服務(wù)。要實現(xiàn)以上目標(biāo),你在Maven或Gradle里至少需要以下8個依賴:
org.springframework:spring-core
org.springframework:spring-web
org.springframework:spring-webmvc
com.fasterxml.jackson.core:jackson-databind
org.hibernate:hibernate-validator
org.apache.tomcat.embed:tomcat-embed-core
org.apache.tomcat.embed:tomcat-embed-el
org.apache.tomcat.embed:tomcat-embed-logging-juli
如果打算使用Spring Boot的起步依賴况褪,你只需要添加Spring Boot的Web起步依賴(org.springframework.boot:spring-boot-starter-web)撕贞,僅此一個。它會根據(jù)依賴傳遞把其他所需依賴引入項目里测垛。
比起減少依賴數(shù)量捏膨,起步依賴還有一個好處就是:你不再需要考慮支持某種功能需要使用什么庫了,直接引入相關(guān)依賴就行食侮。如果應(yīng)用是個Web應(yīng)用号涯,所以加入了Web起步依賴;如果應(yīng)用程序要用到JPA持久化锯七,那么就可以加入JPA起步依賴链快;需要安全功能,直接加入security起步依賴即可起胰。
命令行界面
除了自動配置和起步依賴久又,Spring Boot還提供了一種很有意思的開發(fā)spring boot應(yīng)用的新方法。Spring Boot Cli讓只寫代碼即可實現(xiàn)應(yīng)用程序成為可能效五。
Spring Boot Cli利用了起步依賴和自動配置,讓你專注于代碼本身炉峰。簡單來說畏妖,CLI能檢測到你使用了哪些類,它知道要向Classpath中添加哪些起步依賴才能讓它運轉(zhuǎn)起來疼阔,一旦那些依賴出現(xiàn)在Classpath中戒劫,一系列自動配置就會接踵而來。
但同時婆廊,Spring Boot Cli是Spring Boot的非必要組成部分迅细,雖然它為Spring帶來了驚人的力量,大大簡化了開發(fā)淘邻,但也引入了一套不太常規(guī)的開發(fā)模型茵典。如果您還是不太適應(yīng)這種開發(fā)模型,可以拋開CLI宾舅,利用Spring Boot提供的其他東西统阿。
Actuator
Spring Boot的最后一個法寶就是Actuator,其他幾個部分旨在簡化Spring配置筹我,而Actuator則要在提供運行時檢查應(yīng)用程序內(nèi)部情況的能力扶平。包括以下細(xì)節(jié):
Spring應(yīng)用程序上下文配置的Bean。
應(yīng)用程序取到的環(huán)境變量蔬蕊、系統(tǒng)屬性结澄、配置屬性和命令行參數(shù)。
應(yīng)用程序中線程的當(dāng)前狀態(tài)。
應(yīng)用程序最近處理過的Http請求追蹤情況麻献。
各種和內(nèi)存用量们妥,垃圾回收、Web請求相關(guān)的指標(biāo)赎瑰。