Java開發大型互聯網架構spring Boot自動配置原理之實戰剖析

編程語言 Java NoSQL 腳本語言 圖靈學院 圖靈學院 2017-11-02

引言

Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。通過這種方式,Spring Boot致力於在蓬勃發展的快速應用開發領域(rapid application development)成為領導者。

Spring Boot介紹

Spring Boot使開發獨立的,產品級別的基於Spring的應用變得非常簡單,你只需"just run"。 我們為Spring平臺及第三方庫提供開箱即用的設置,這樣你就可以有條不紊地開始。多數Spring Boot應用需要很少的Spring配置。

你可以使用Spring Boot創建Java應用,並使用java -jar啟動它或採用傳統的war部署方式。我們也提供了一個運行"spring腳本"的命令行工具。

我們主要的目標是:

為所有的Spring開發提供一個從根本上更快的和廣泛使用的入門經驗。

開箱即用,但你可以通過不採用默認設置來擺脫這種方式。

提供一系列大型項目常用的非功能性特徵(比如,內嵌服務器,安全,指標,健康檢測,外部化配置)。

絕對不需要代碼生成及XML配置。

系統要求

默認情況下,Spring Boot 1.3.0.BUILD-SNAPSHOT 需要Java7和Spring框架4.1.3或以上。你可以在Java6下使用Spring Boot,不過需要添加額外配置。具體參考Section 73.9, “How to use Java 6” 。構建環境明確支持的有Maven(3.2+)和Gradle(1.12+)。

注:儘管你可以在Java6或Java7環境下使用Spring Boot,通常我們建議你如果可能的話就使用Java8。

.Servlet容器

下列內嵌容器支持開箱即用(out of the box):

名稱Servlet版本Java版本

Tomcat 83.1Java 7+

Tomcat 73.0Java 6+

Jetty 93.1Java 7+

Jetty 83.0Java 6+

Undertow 1.13.1Java 7+

你也可以將Spring Boot應用部署到任何兼容Servlet 3.0+的容器。

Spring Boot安裝

Spring Boot可以跟典型的Java開發工具一塊使用或安裝為一個命令行工具。不管怎樣,你將需要安裝Java SDK v1.6 或更高版本。在開始之前,你需要檢查下當前安裝的Java版本:

$ java -version

自動配置原理

通過@EnableAutoConfiguration啟用Spring應用程序上下文的自動配置,這個註解會導入一個EnableAutoConfigurationImportSelector的類,而這個類會去讀取一個spring.factories下key為EnableAutoConfiguration對應的全限定名的值。

這個spring.factories裡面配置的那些類,主要作用是告訴Spring Boot這個stareter所需要加載的那些xxxAutoConfiguration類,也就是你真正的要自動註冊的那些bean或功能。然後,我們實現一個spring.factories指定的類,標上@Configuration註解,一個starter就定義完了。

如果想從自己的starter種讀取應用的starter工程的配置,只需要在入口類上加上如下註解即可:

@EnableConfigurationProperties(MyProperties.class)

讀取spring.factories文件的實現

是通過org.springframework.core.io.support.SpringFactoriesLoader實現。

SpringFactoriesLoader的實現類似於SPI(Service Provider Interface,在java.util.ServiceLoader的文檔裡有比較詳細的介紹。java SPI提供一種服務發現機制,為某個接口尋找服務實現的機制。有點類似IOC的思想,就是將裝配的控制權移到程序之外,在模塊化設計中這個機制尤其重要[3])。

SpringFactoriesLoader會加載classpath下所有JAR文件裡面的META-INF/spring.factories文件。

其中加載spring.factories文件的代碼在loadFactoryNames方法裡:

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

....

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

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<>();

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);

}

}

通過org.springframework.boot.autoconfigure.AutoConfigurationImportSelector裡面的getCandidateConfigurations方法,獲取到候選類的名字List<String>。該方法代碼如下:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,

AnnotationAttributes attributes) {

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(

getSpringFactoriesLoaderFactoryClass(), 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;

}

其中,getSpringFactoriesLoaderFactoryClass()方法直接返回的是EnableAutoConfiguration.class, 代碼如下:

protected Class<?> getSpringFactoriesLoaderFactoryClass() {

return EnableAutoConfiguration.class;

}

所以,getCandidateConfigurations方法裡面的這段代碼:

List<String> configurations = SpringFactoriesLoader.loadFactoryNames(

getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());

會過濾出key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定名對應的值。全限定名都使用如下命名方法:

包名.外部類名

包名.外部類名$內部類名

e.g:

org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration

SpringBoot中的META-INF/spring.factories(完整路徑:spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories)中關於EnableAutoConfiguration的這段配置如下:

# Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\

org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\

org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\

org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\

org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\

org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\

org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\

org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\

org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\

org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\

org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\

org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\

org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\

org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\

org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\

org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\

org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\

org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\

org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\

org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\

org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\

org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\

org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\

org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\

org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\

org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\

org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\

org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\

org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\

org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\

org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\

org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\

org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\

org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\

org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\

org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\

org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\

org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\

org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\

org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\

org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\

org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\

org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\

org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\

org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\

org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration,\

org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\

org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\

org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\

org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\

org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\

org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\

org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\

org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\

org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\

org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\

org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\

org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\

org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\

org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\

org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\

org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\

org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\

org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\

org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\

org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\

org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerAutoConfiguration,\

org.springframework.boot.autoconfigure.web.reactive.WebFluxAnnotationAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\

org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\

org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\

org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

當然了,這些AutoConfiguration不是所有都會加載的,會根據AutoConfiguration上的@ConditionalOnClass等條件,再進一步判斷是否加載。我們下文通過FreeMarkerAutoConfiguration實例來分析整個自動配置的過程。

自動配置實戰

所以,瞭解了自動配置的原理,來自己實現一個自動配置的玩意其實很簡單。

添加配置類:

import org.slf4j.Logger;

import org.springframework.context.EnvironmentAware;

import org.springframework.core.env.Environment;

import com.oceanpayment.common.utils.logger.LoggerUtils;

public class EnvConfig implements EnvironmentAware {

private final Logger logger = LoggerUtils.getLogger(this);

private Environment env;

public String getStringValue(String key) {

return env.getProperty(key);

}

public Long getLongValue(String key) {

String value = getStringValue(key);

try {

return Long.parseLong(value);

} catch (Exception e) {

logger.error("字符串轉換Long失敗:{} = {}", key, value);

}

return 0L;

}

public int getIntValue(String key) {

return getLongValue(key).intValue();

}

@Override

public void setEnvironment(Environment environment) {

this.env = environment;

}

}

添加自動配置類:

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.env.PropertyResolver;

@Configuration

@ConditionalOnClass(PropertyResolver.class)

public class EnvAutoConfig {

@Bean

public EnvConfig envConfig() {

return new EnvConfig();

}

}

創建META-INF/spring.factories文件,添加自動配置映射:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\

com.oceanpayment.common.config.env.EnvAutoConfig

這樣就搞定了。

總結

以 上就是我對Java開發大型互聯網架構spring Boot自動配置原理之實戰剖析問題及其優化總結,分享給大家,希望大家知道什麼是Java開發大型互聯網架構spring Boot自動配置原理之實戰剖析問題及其優化。覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持!

  • 1、多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

  • 2、可以去百度搜索騰訊課堂圖靈學院的視頻來學習一下java架構實戰案例,還挺不錯的。

  • 最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步!

  • 3丶想了解學習以上課程內容可加群:469717771 驗證碼頭條(06 必過)

Java開發大型互聯網架構spring Boot自動配置原理之實戰剖析

相關推薦

推薦中...