您好,登錄后才能下訂單哦!
剛關(guān)注的朋友,可以回顧前兩篇文章:
上篇文章總結(jié)了《深入實踐Spring Boot》的第二部分,本篇文章總結(jié)第三部分,也是最后一部分。這部分主要講解核心技術(shù)的源代碼分析,因為篇幅和能力原因,分析的不會太詳細,后續(xù)深入研究后再專門寫文章。希望大家能從「閱讀筆記」3篇文章中,對Spring Boot提供的功能有所了解,在項目中進行實踐,不斷從繁瑣重復(fù)的開發(fā)中解放出來。
我也是最近剛開始了解Spring Boot,計劃今年在項目中實踐,到時會總結(jié)實踐過程中的一些問題和經(jīng)驗,分享給大家。想一起學(xué)習(xí)、實踐、交流的朋友,可以掃描文章下方的二維碼,關(guān)注我的個人公眾號,感謝大家。
本篇主要從以下幾個方面總結(jié):
春節(jié)假期很快過去了,明天就要上班了,相信大家還是意猶未盡,沒吃夠、沒玩夠、沒和家人待夠。今年因為個人原因,沒有回家過年,心理最牽掛的還是爺爺奶奶,他們都80多了,希望她們身體健康,開開心心地度過生命最后的旅程。
不管怎樣,大家要切換頻道了,回歸到正常的工作中,好好努力,一起期待明年和家人更好的團聚。
使用Spring Boot創(chuàng)建一個簡單的Web項目很簡潔,不需要太多配置,編寫一個簡單的主程序就行:
@SpringBootApplication
public class ConfigApplication{
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
}
首先分析下run方法(省略不關(guān)鍵的部分代碼):
public ConfigurableApplicationContext run(String... args) {
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.started();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
listeners.finished(context, null);
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
它首先開啟一個SpringApplicationRunListeners監(jiān)聽器,然后創(chuàng)建一個應(yīng)用上下文ConfigurableApplicationContext,通過這個上下文加載應(yīng)用所需的類和各種環(huán)境配置等。
一個應(yīng)用能夠正常運行起來,需要一些環(huán)境變量、各種資源和一些相關(guān)配置等,下面看下createApplicationContext方法會加載應(yīng)用定義的和需要的類及各種資源。
所有的自動配置都是從注解@SpringBootApplication引入的,它其實又包含了@Configuration、@EnableAutoConfiguration和@ComponentScan,其中,@EnableAutoConfiguration就是啟用自動配置的,并將導(dǎo)入一些自動配置的類定義。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
Class<?>[] exclude() default {};
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
}
EnableAutoConfiguration最終會導(dǎo)入一個自動配置的類列表,列表中的自動配置類很多,這些配置類中大都將被導(dǎo)入,并處于備用狀態(tài),當(dāng)項目中引入了相關(guān)的包時,相關(guān)的功能將被啟用。
例如在項目的maven配置中配置了Redis的引用,Redis的默認配置項將被啟用,首先會讀取項目中的配置,只有項目中沒有相關(guān)配置才啟用配置的默認值,下面代碼是Redis的自動配置,如果配置文件中沒設(shè)置,會使用下面默認設(shè)置。
@ConfigurationProperties(
prefix = "spring.redis"
)
public class RedisProperties {
private int database = 0;
private String host = "localhost";
private String password;
private int port = 6379;
private int timeout;
private RedisProperties.Pool pool;
private RedisProperties.Sentinel sentinel;
private RedisProperties.Cluster cluster;
public RedisProperties() {
}
通過自動配置,就不用重復(fù)定義配置項名稱了,覆蓋約定的配置項即可。可通過查看各個Properties類,查看有哪些配置項。
要使用數(shù)據(jù)庫,首先必須與數(shù)據(jù)庫服務(wù)器建立連接。對于關(guān)系型數(shù)據(jù)庫,Spring Boot 連接數(shù)據(jù)源一般都采用JDBC的方式來實現(xiàn)。其他類型的數(shù)據(jù)庫使用各自獨立的方式來建立連接。
JDBC連接數(shù)據(jù)源必須指定數(shù)據(jù)源類型和數(shù)據(jù)庫驅(qū)動程序,數(shù)據(jù)源主要有4中:
Spring Boot 默認使用org.apache.tomcat.jdbc.pool.DataSource,它使用第2種方式,實現(xiàn)了javax.sql.DataSource接口。數(shù)據(jù)源的類型可以通過配置更改。
另外,Spring Boot 默認幾乎支持現(xiàn)有的所有數(shù)據(jù)庫。
與數(shù)據(jù)庫建立連接后,就可以對數(shù)據(jù)庫執(zhí)行一些存取操作,對數(shù)據(jù)庫實現(xiàn)管理的功能。數(shù)據(jù)存取操作大體上包含兩方面的內(nèi)容,即實體建模和持久化。
不管是關(guān)系型數(shù)據(jù)庫,還是NoSQL數(shù)據(jù)庫,都遵循這一設(shè)計規(guī)范。實體建模即將Java的普通對象和關(guān)系映射為數(shù)據(jù)庫表機器相關(guān)的關(guān)系,在Spring Boot中,主要是通過注解實現(xiàn)。
關(guān)系型數(shù)據(jù)庫都使用了JPA的一套標準,它結(jié)合使用Hibernate實現(xiàn)了實體的持久化。后續(xù)的數(shù)據(jù)庫管理設(shè)計都遵循了JPA這一個標準規(guī)范,提供相同的訪問數(shù)據(jù)庫的API。
Spring Cloud是基于對Netfix開源組件進一步封裝的一套云應(yīng)用開發(fā)工具,可以用來開發(fā)各種微服務(wù)應(yīng)用。
前一篇文章說到,配置管理的在線更新功能使用事件總線,即spring-cloud-bus來發(fā)布狀態(tài)變化,并使用分布式消息來發(fā)布更新事件,分布式消息最終使用RabbitMQ來實現(xiàn)消息收發(fā)。
再來回顧下在線更新流程:
配置管理服務(wù)器中的消息分發(fā)是從spring-cloud-bus中調(diào)用spring-cloud-stream組件實現(xiàn)的,而spring-cloud-stream使用RabbitMQ實現(xiàn)了分布式消息分發(fā)。具體實現(xiàn)就不說了,使用過RabbitMQ的很好理解。
客戶端執(zhí)行注冊使用計劃任務(wù)的方式來實現(xiàn),而客戶端從發(fā)現(xiàn)服務(wù)器中更新其他在線的客戶端列表,也使用了一個定時任務(wù)來管理。
當(dāng)一個應(yīng)用啟用發(fā)現(xiàn)服務(wù)的功能之后,會默認啟用Ribbon的負載均衡服務(wù)。Ribbon通過發(fā)現(xiàn)服務(wù)獲取在線的客戶端,為具有多個實例的客戶端建立起負載均衡管理機制。
使用spirng-cloud-stream可以非常簡單地使用RabbitMQ的異步消息,Spring Cloud的配置管理中的分布式消息分發(fā)也是通過調(diào)用spring-cloud-stream組件來實現(xiàn)的。
下面以消息生產(chǎn)者和消費者的實現(xiàn)說明分布式消息實現(xiàn)
消息生產(chǎn)者:
@EnableBinding(Source.class)
@RestController
@SpringBootApplication
public class SenderApplication {
@Autowired
@Output(Source.OUTPUT)
private MessageChannel channel;
@RequestMapping(method = RequestMethod.POST, path = "/send")
public void write (@RequestBody Map<String, Object> msg){
channel.send(MessageBuilder.withPayload(msg).build());
}
public static void main(String[] args) {
SpringApplication.run(SenderApplication.class, args);
}
}
消息消費者:
@EnableBinding(Sink.class)
@IntegrationComponentScan
@MessageEndpoint
@SpringBootApplication
public class ReceiverApplication {
@ServiceActivator(inputChannel=Sink.INPUT)
public void accept(Map<String, Object> msg){
System.out.println(msg.get("msg").toString() + ":" + msg.get("name"));
}
public static void main(String[] args) {
SpringApplication.run(ReceiverApplication.class, args);
}
}
從上面的分析可以看到,Spring Boot及其一些相關(guān)組件,已經(jīng)盡量把一些可以實現(xiàn)和做到的功能,都幫我們實現(xiàn)了。 雖然使用Spring Boot及其相關(guān)組件看起來非常簡單,但實際上可以實現(xiàn)無比強大的功能,這就是Spring Boot 及其組件的神奇所在。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。