Spring Boot實戰:Spring Boot核心原理剖析
Spring Boot基本配置介紹
1 關閉某個自動配置
通過上節@SpringBootApplication下的@EnableAutoConfiguration得知,Spring Boot會根據專案中的jar包依賴,自動做出配置,Spring Boot支援的自動配置如下(非常多):
假如我們不需要Spring Boot自動配置,想關閉某一項的自動配置,該如何設定呢?
例如:我們不想自動配置Redis,想自己手動配置呢?通過檢視@SpringBootApplication的原始碼可以看出,關閉特定的自動配置應該使用@SpringBootApplication下的exclude引數,現以關閉Redis自動配置為例:
@SpringBootApplication(exclude={RedisAutoConfiguration.class})
2.定製啟動Banner
在啟動Spring Boot專案的時候我們在控制檯下看到了如下預設的啟動圖案:
圖 2.3 預設啟動圖案
如果想自己來指定啟動的圖案應該如何配置呢?
(1) 在瀏覽器中開啟網站http://patorjk.com/software/taag,如下圖:
(2)在第一步所示範的網站上選擇左下方的“select & copy”按鈕將自定義的banner圖案進行復制,然後新建一個banner.txt檔案,將複製好的圖案寫入到banner.txt檔案中。
(3)將banner.txt檔案放置到專案的src/main/resources目錄下。
(4)重新啟動程式,檢視效果如下:
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,啟動應用,埠修改後如下圖所示:
(2) server.servlet-path引數用於將進入DispatcherServlet的規則修改為:*.action,測試如下:
從上面的引數配置可以看出,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圖形資料庫,它將結構化資料儲存在網路上而不是表中。
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容器,進行自動配置。
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;
}
在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);