歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 理解Spring Boot

理解Spring Boot

日期:2017/3/1 9:10:35   编辑:Linux編程

Spring Boot是一個偏執的開源框架,它可用於創建可執行的Spring應用程序,采用了習慣優於配置的方法。
此框架的神奇之處在於@EnableAutoConfiguration注釋,此注釋自動載入應用程序所需的所有Bean——這依賴於Spring Boot在類路徑中的查找。

一、@Enable*注釋

@Enable*注釋並不是新發明的注釋,早在Spring 3框架就引入了這些注釋,用這些注釋替代XML配置文件。
很多Spring開發者都知道@EnableTransactionManagement注釋,它能夠聲明事務管理;@EnableWebMvc注釋,它能啟用Spring MVC;以及@EnableScheduling注釋,它可以初始化一個調度器。
這些注釋事實上都是簡單的配置,通過@Import注釋導入。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ EnableAutoConfigurationImportSelector.class,
        AutoConfigurationPackages.Registrar.class })
public @interface EnableAutoConfiguration {

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     */
    Class<?>[] exclude() default {};

}

EnableAutoConfigurationImportSelector類使用了Spring Core包的SpringFactoriesLoader類的loadFactoryNamesof()方法。
SpringFactoriesLoader會查詢META-INF/spring.factories文件中包含的JAR文件。
當找到spring.factories文件後,SpringFactoriesLoader將查詢配置文件命名的屬性。在例子中,是org.springframework.boot.autoconfigure.EnableAutoConfiguration。
讓我們來看看spring-boot-autoconfigure JAR文件,它真的包含了一個spring.factories文件,內容如下:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration

在這個文件中,可以看到一系列Spring Boot自動配置的列表。下面我們來看這些配置的細節,以MongoAutoConfiguration為例:

@Configuration
@ConditionalOnClass(Mongo.class)
@EnableConfigurationProperties(MongoProperties.class)
public class MongoAutoConfiguration {

    @Autowired
    private MongoProperties properties;

    private Mongo mongo;

    @PreDestroy
    public void close() throws UnknownHostException {
        if (this.mongo != null) {
            this.mongo.close();
        }
    }

    @Bean
    @ConditionalOnMissingBean
    public Mongo mongo() throws UnknownHostException {
        this.mongo = this.properties.createMongoClient();
        return this.mongo;
    }

}

這個類進行了簡單的Spring配置,聲明了MongoDB所需典型Bean。
這個類跟其它很多類一樣,重度依賴於Spring Boot注釋:
1)@ConditionOnClass激活一個配置,在類路徑中只能存在一到幾個這樣的類。
2)@EnableConfigurationProperties自動映射一個POJO到Spring Boot配置文件(默認是application.properties文件)的屬性集。
3)@ConditionalOnMissingBean啟用一個Bean定義,但必須是這個Bean之前未定義過才有效。
還可以使用@ AutoConfigureBefore注釋、@AutoConfigureAfter注釋來定義這些配置類的載入順序。

二、屬性映射

下面看MongoProperties類,它是一個Spring Boot屬性映射的例子:

@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {

    private String host;
    private int port = DBPort.PORT;
    private String uri = "mongodb://localhost/test";
    private String database;

    // ... getters/ setters omitted
}

@ConfigurationProperties注釋將POJO關聯到指定前綴的每一個屬性。例如,spring.data.mongodb.port屬性將映射到這個類的端口屬性。
強烈建議Spring Boot開發者使用這種方式來刪除與配置屬性相關的瓶頸代碼。

三、@Conditional注釋

Spring Boot的強大之處在於使用了Spring 4框架的新特性:@Conditional注釋,此注釋使得只有在特定條件滿足時才啟用一些配置。
在Spring Boot的org.springframework.boot.autoconfigure.condition包中說明了使用@Conditional注釋能給我們帶來什麼,下面對這些注釋做一個概述:

  • @ConditionalOnBean
  • @ConditionalOnClass
  • @ConditionalOnExpression
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnNotWebApplication
  • @ConditionalOnResource
  • @ConditionalOnWebApplication

以@ConditionalOnExpression注釋為例,它允許在Spring的EL表達式中寫一個條件。

@Conditional(OnExpressionCondition.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface ConditionalOnExpression {

    /**
     * The SpEL expression to evaluate. Expression should return {@code true} if the
     * condition passes or {@code false} if it fails.
     */
    String value() default "true";

}

在這個類中,我們想利用@Conditional注釋,條件在OnExpressionCondition類中定義:

public class OnExpressionCondition extends SpringBootCondition {

    @Override
    public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // ...
        // we first get a handle on the EL context via the ConditionContext

        boolean result = (Boolean) resolver.evaluate(expression, expressionContext);

        // ...
        // here we create a message the user will see when debugging

        return new ConditionOutcome(result, message.toString());
    }
}

在最後,@Conditional通過簡單的布爾表達式(即ConditionOutcome方法)來決定。

四、應用程序上下文初始化器

spring.factories還提供了第二種可能性,即定義應用程序的初始化。這使得我們可以在應用程序載入前操縱Spring的應用程序上下文ApplicationContext。
特別是,可以在上下文創建監聽器,使用ConfigurableApplicationContext類的addApplicationListener()方法。
AutoConfigurationReportLoggingInitializer監聽到系統事件時,比如上下文刷新或應用程序啟動故障之類的事件,Spring Boot可以執行一些工作。這有助於我們以調試模式啟動應用程序時創建自動配置的報告。
要以調試模式啟動應用程序,可以使用-Ddebug標識,或者在application.properties文件這添加屬性debug= true。

五、調試Spring Boot自動配置

Spring Boot的官方文檔(http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-troubleshoot-auto-configuration)有助於理解自動配置期間發生了什麼。當以調試模式運行時,Spring Boot會產生一個報告,如下:

Positive matches:
-----------------

   MessageSourceAutoConfiguration
      - @ConditionalOnMissingBean (types: org.springframework.context.MessageSource; SearchStrategy: all) found no beans (OnBeanCondition)

   JmxAutoConfiguration
      - @ConditionalOnClass classes found: org.springframework.jmx.export.MBeanExporter (OnClassCondition)
      - SpEL expression on org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration: ${spring.jmx.enabled:true} (OnExpressionCondition)
      - @ConditionalOnMissingBean (types: org.springframework.jmx.export.MBeanExporter; SearchStrategy: all) found no beans (OnBeanCondition)

   DispatcherServletAutoConfiguration
      - found web application StandardServletEnvironment (OnWebApplicationCondition)
      - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition)


Negative matches:
-----------------

   DataSourceAutoConfiguration
      - required @ConditionalOnClass classes not found: org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType (OnClassCondition)

   DataSourceTransactionManagerAutoConfiguration
      - required @ConditionalOnClass classes not found: org.springframework.jdbc.core.JdbcTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition)

   MongoAutoConfiguration
      - required @ConditionalOnClass classes not found: com.mongodb.Mongo (OnClassCondition)

   FallbackWebSecurityAutoConfiguration
      - SpEL expression on org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration: !${security.basic.enabled:true} (OnExpressionCondition)

   SecurityAutoConfiguration
      - required @ConditionalOnClass classes not found: org.springframework.security.authentication.AuthenticationManager (OnClassCondition)

   EmbeddedServletContainerAutoConfiguration.EmbeddedJetty
      - required @ConditionalOnClass classes not found: org.eclipse.jetty.server.Server,org.eclipse.jetty.util.Loader (OnClassCondition)

   WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#localeResolver
      - @ConditionalOnMissingBean (types: org.springframework.web.servlet.LocaleResolver; SearchStrategy: all) found no beans (OnBeanCondition)
      - SpEL expression: '${spring.mvc.locale:}' != '' (OnExpressionCondition)

   WebSocketAutoConfiguration
      - required @ConditionalOnClass classes not found: org.springframework.web.socket.WebSocketHandler,org.apache.tomcat.websocket.server.WsSci (OnClassCondition)

對於每個自動配置,可以看到它啟動或失敗的原因。

六、結論

Spring Boot很好地利用了Spring 4框架的功能,可以創建一個自動配置的可執行JAR。
不要忘記,可以使用自己的配置來替代自動配置,見: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-replacing-auto-configuration
over!

Spring Boot入門學習筆記 http://www.linuxidc.com/Linux/2016-10/135889.htm

Spring Boot+Nginx+Tomcat+SSL配置筆記 http://www.linuxidc.com/Linux/2016-01/127134.htm

Spring Boot 的詳細介紹:請點這裡
Spring Boot 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved