1. 程式人生 > >Spring Boot實戰:Spring Boot核心原理剖析

Spring Boot實戰:Spring Boot核心原理剖析

Spring Boot基本配置介紹

1 關閉某個自動配置

通過上節@SpringBootApplication下的@EnableAutoConfiguration得知,Spring Boot會根據專案中的jar包依賴,自動做出配置,Spring Boot支援的自動配置如下(非常多):

Java

假如我們不需要Spring Boot自動配置,想關閉某一項的自動配置,該如何設定呢?

例如:我們不想自動配置Redis,想自己手動配置呢?通過檢視@SpringBootApplication的原始碼可以看出,關閉特定的自動配置應該使用@SpringBootApplication下的exclude引數,現以關閉Redis自動配置為例:

@SpringBootApplication(exclude={RedisAutoConfiguration.class})

2.定製啟動Banner

在啟動Spring Boot專案的時候我們在控制檯下看到了如下預設的啟動圖案:

圖 2.3 預設啟動圖案

如果想自己來指定啟動的圖案應該如何配置呢?

(1) 在瀏覽器中開啟網站http://patorjk.com/software/taag,如下圖:

Java

(2)在第一步所示範的網站上選擇左下方的“select & copy”按鈕將自定義的banner圖案進行復制,然後新建一個banner.txt檔案,將複製好的圖案寫入到banner.txt檔案中。

(3)將banner.txt檔案放置到專案的src/main/resources目錄下。

Java

(4)重新啟動程式,檢視效果如下:

Java

3. 應用的全域性配置檔案

可以在Spring Boot專案的src/main/resources目錄下或者在類路徑下的/config目錄下建立一個全域性的配置檔案application.properties或者是字尾為.yml的application.yml的檔案用於修改Spring Boot專案的預設配置值,例如修改專案的預設埠,或者進入DispatcherServlet的請求地址規則等。

通常,在實際開發中我們習慣使用application.properties檔案作為應用的全域性配置檔案,一般我們放到src/main/resources目錄下。

例如,在src/main/resources目錄下建立一個名稱為application.properties的檔案,配置內容如下:

server.port=9999

server.servlet-path=*.action

(1)其中, server.port引數用於將Spring Boot專案的預設埠改為9999,啟動應用,埠修改後如下圖所示:

Java

(2) server.servlet-path引數用於將進入DispatcherServlet的規則修改為:*.action,測試如下:

Java

從上面的引數配置可以看出,Spring Boot支援很多引數的配置與引數值的修改,關於其他配置引數的詳細說明和描述可以檢視官方的文件說明:http://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#common-application-properties

4 Starters啟動器

Spring Boot為我們提供了簡化專案開發的Starter啟動器,例如我們在專案中使用的pom.xml檔案下配置:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId></dependency>

Spring Boot就會自動關聯web開發相關的依賴,如Tomcat以及spring-webmvc等,進而對web開發進行支援,同時相關技術的配置也將實現自動配置,程式設計師即可從繁瑣的配置檔案中脫身而出了。除此之外,官方還提供瞭如下Starters:

spring-boot-starter:這是Spring Boot的核心啟動器,包含了自動配置、日誌和YAML檔案的支援。

spring-boot-starter-activemq:為JMS使用Apache ActiveMQ ActiveMQ 是Apache出品,最流行的,能力強勁的開源訊息匯流排

spring-boot-starter-amqp:通過spring-rabbit來支援AMQP協議(Advanced Message Queuing Protocol)。

spring-boot-starter-aop:支援面向方面的程式設計即AOP,包括spring-aop和AspectJ。

spring-boot-starter-artemis:通過Apache Artemis支援JMS的API(Java Message Service API)。

spring-boot-starter-batch:支援Spring Batch,包括HSQLDB資料庫。

spring-boot-starter-cache:支援Spring的Cache抽象。

spring-boot-starter-cloud-connectors:支援Spring Cloud Connectors,簡化了在像Cloud Foundry或Heroku這樣的雲平臺上連線服務。

spring-boot-starter-data-cassandra:使用Cassandra分散式資料庫、Spring Data Cassandra,Apache Cassandra是一套開源分散式NoSQL資料庫系統。

spring-boot-starter-data-couchbase:使用Couchbase 檔案儲存資料庫、Spring Data Couchbase。Spring Data是一個用於簡化資料庫訪問,並支援雲服務的開源框架。

spring-boot-starter-data-elasticsearch:支援ElasticSearch搜尋和分析引擎,包括spring-data-elasticsearch。

spring-boot-starter-data-gemfire:支援GemFire分散式資料儲存,包括spring-data-gemfire。

spring-boot-starter-data-jpa:支援JPA(Java Persistence API),包括spring-data-jpa、spring-orm、Hibernate。

spring-boot-starter-data-ldap:支援 Spring Data LDAP。

spring-boot-starter-data-mongodb:支援MongoDB資料,包括spring-data-mongodb。

spring-boot-starter-data-neo4j:使用Neo4j圖形資料庫、Spring Data Neo4j Neo4j是一個高效能的,NOSQL圖形資料庫,它將結構化資料儲存在網路上而不是表中。

Java

spring-boot-starter-redis:支援Redis鍵值儲存資料庫,包括spring-redis。

spring-boot-starter-data-rest:通過spring-data-rest-webmvc,支援通過REST暴露Spring Data資料倉庫。

spring-boot-starter-data-solr:支援Apache Solr搜尋平臺,包括spring-data-solr。

spring-boot-starter-freemarker:支援FreeMarker模板引擎。

spring-boot-starter-groovy-templates:支援Groovy模板引擎。

spring-boot-starter-hateoas:通過spring-hateoas支援基於HATEOAS的RESTful Web服務。

spring-boot-starter-integration:支援通用的spring-integration模組。

spring-boot-starter-jdbc:支援JDBC資料庫。

spring-boot-starter-jersey:支援Jersey RESTful Web服務框架。

spring-boot-starter-hornetq:通過HornetQ支援JMS。

spring-boot-starter-jta-atomikos:通過Atomikos支援JTA分散式事務處理。

spring-boot-starter-jta-bitronix:通過Bitronix支援JTA分散式事務處理。

spring-boot-starter-mail:支援javax.mail模組。

spring-boot-starter-mobile:支援spring-mobile。

spring-boot-starter-mustache:支援Mustache模板引擎。

spring-boot-starter-security:支援spring-security。

spring-boot-starter-social-facebook:支援spring-social-facebook

spring-boot-starter-social-linkedin:支援pring-social-linkedin

spring-boot-starter-social-twitter:支援pring-social-twitter

spring-boot-starter-test:支援常規的測試依賴,包括JUnit、Hamcrest、Mockito以及spring-test模組。

spring-boot-starter-thymeleaf:支援Thymeleaf模板引擎,包括與Spring的整合。

spring-boot-starter-velocity:支援Velocity模板引擎。

spring-boot-starter-web:支援全棧式Web開發,包括Tomcat和spring-webmvc。

spring-boot-starter-websocket:支援WebSocket開發。

spring-boot-starter-ws:支援Spring Web Services。

Spring Boot 自動配置的原理

Spring Boot在進行SpringApplication物件例項化時會載入META-INF/spring.factories檔案,將該配置檔案中的配置載入到Spring容器,進行自動配置。

Java

1 原始碼分析

首先進入到啟動Spring Boot專案程式碼SpringApplication.run(App.class, args)的原始碼下:

程式清單:

org/springframework/boot/SpringApplication

public static ConfigurableApplicationContext run(Object[] sources,String[ ] args){

return new SpringApplication(sources).run(args);

}

可以看到run方法實際上在建立SpringApplication物件例項,進入到建立SpringApplication物件例項程式碼中去:

程式清單:

org/springframework/boot/SpringApplication

public SpringApplication(Object... sources){

initialize(sources);

}

接下來就是呼叫initialize(sources)方法,進入到該方法原始碼如下:

程式清單:

org/springframework/boot/SpringApplication

@SuppressWarnings({"unchecked","rawtypes"})

private void initialize(Object[ ]sources){

if(sources !=null && sources.length >0){

this.sources.addAll(Arrays.asList(sources));

}

this.webEnvironment = deduceWebEnvironment();

setInitializers((Collection) getSpringFactoriesInstances(

ApplicationContextInitializer.class));

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

this.mainApplicationClass = deduceMainApplicationClass();

}

initialize方法中呼叫了getSpringFactoriesInstances方法,程式碼如下:

程式清單:

org/springframework/boot/SpringApplication

private<T >Collection<?extends T> getSpringFactoriesInstances(Class<T> type,

Class<?>[] parameterTypes,Object... args){

ClassLoader classLoader =Thread.currentThread().getContextClassLoader();

// Use names and ensure unique to protect against duplicates

Set<String> names = new LinkedHashSet<String>(

SpringFactoriesLoader.loadFactoryNames(type, classLoader));

List<T> instances = createSpringFactoriesInstances(type, parameterTypes,

classLoader, args, names);

AnnotationAwareOrderComparator.sort(instances);

return instances;

}

Java

在getSpringFactoriesInstances中又呼叫了loadFactoryNames方法,繼續進入到該方法中,檢視原始碼如下:

程式清單:org/springframework/boot.SpringApplication

public static List<String> loadFactoryNames(Class<?> factoryClass,ClassLoaderclassLoader){

String factoryClassName = factoryClass.getName();

try{

Enumeration<URL> urls =(classLoader !=null? classLoader.getResources(FACTORIES_RESOURCE_LOCATION):

ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

List<String> result = new ArrayList<String>();

while(urls.hasMoreElements()){

URL url = urls.nextElement();

Properties properties =PropertiesLoaderUtils.loadProperties(new UrlResource(url));

String factoryClassNames = properties.getProperty(factoryClassName);

result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));

}

return result;

}

catch(IOException ex){

throw new IllegalArgumentException("Unable to load ["+ factoryClass.getName() +

"] factories from location ["+ FACTORIES_RESOURCE_LOCATION +"]", ex);