Spring Boot自動配置與Spring 條件化配置


SpringBoot自動配置

  SpringBoot的自動配置是一個運行時(應用程序啟動時)的過程,簡化開發時間,無需浪費時間討論具體的Spring配置,只需考慮如何利用SpringBoot的自動配置即可。

  Spring 4.0的條件化配置

  SpringBoot中包含一個spring-boot-autoconfigure的JAR文件,其中包含一應配置類。每個配置類都在應用程序的Classpath里,包括Thymeleaf/Spring Data JPA/Spring MVC等,開發者根據需求選擇使用。

  自動配置-設計基礎:Spring4.0引入的新特性--條件化配置。條件化配置允許配置存在於應用程序中,但在滿足某些特定條件之前都忽略這些配置。

  在Spring里可以很方便地編寫自定義的條件,只需要實現Condition接口,覆蓋它的matches()方法。

  具體條件化配置使用示例:

/**
 * 具體條件類,需實現Condition接口,並重寫matchs(.. , ..)方法
*/
public class JdbcTemplateCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { try{ context.getClassLoader().loadClass( "org.springframework.jdbc.core.JdbcTemplate"); return true; } catch (Exception e){ return false; } } } --------------------------------------------------------------------- /** * 聲明bean時,使用自定義條件類,作為@Conditional的參數value */ @Conditional(JdbcTemplateCondition.class) public MyService myService(){....}

  在這個例子中,只有當JdbcTemplateCondition類的條件成立時才會創建MyService這個Bean。即MyService Bean創建的條件是Classpath里有JdbcTemplate。否則,這個Bean的聲明就會被忽略掉。

  Spring 4.0源碼支持:

  @Conditional注解 + Condition接口

/**
 * Condition接口,編寫自定義條件
 */
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2); } --------------------------------------------------------------- /** * Conditional注解 */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional { Class<? extends Condition>[] value(); }

  spring-boot-autoconfigure實現分析

  上例相當簡單,但SpringBoot定義了很多更有趣的條件,並將其運用到了配置類上,這些配置類構成了SpringBoot的自動配置。SpringBoot運用條件化配置的方法是,定義多個特殊的條件化注解,並將其用到配置類上。

  SpringBoot提供的條件化注解:

自動配置中使用的條件化注解
條件化注解 配置生效條件
@ConditionalOnBean 配置了某個特定Bean
@ConditionalOnMissingBean 沒有配置特定的Bean
@ConditionalOnClass Classpath里有指定的類
@ConditionalOnMissingClass Classpath里缺少指定的類
@ConditionalOnExpression 給定的SpEL表達式計算結果為true
@ConditionalOnJava Java的版本匹配特定值或者一個范圍值
@ConditionalOnJndi 參數中給定的JNDI位置必須存在一個,如果沒有參數,則需要JNDI InitialContext
@ConditionalOnProperty 指定的配置屬性要有一個明確的值
@ConditionalOnResource Classpath里有指定的資源
@ConditionalOnWebApplication 這是一個Web應用程序
@ConditionalOnNotWebApplication 這不是一個Web應用程序

  源碼剖析,DataSourceAutoConfiguration代碼片段:

@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class}) public class DataSourceAutoConfiguration {     ... ...
  
  @Configuration
  @ConditionalOnProperty(prefix = "spring.datasource", name = "jmx-enabled")
  @ConditionalOnClass(name = "org.apache.tomcat.jdbc.pool.DataSourceProxy")
  @Conditional(DataSourceAutoConfiguration.DataSourceAvailableCondition.class)
  @ConditionalOnMissingBean(name = "dataSourceMBean")
  protected static class TomcatDataSourceJmxConfiguration {
  
  @Bean
  public Object dataSourceMBean(DataSource dataSource) {
   if (dataSource instanceof DataSourceProxy) {
   try {
   return ((DataSourceProxy) dataSource).createPool().getJmxPool();
   }
   catch (SQLException ex) {
   logger.warn("Cannot expose DataSource to JMX (could not connect)");
   }
   }
   return null;
   }

  }
    ... ...
}

  分析:DataSourceAutoConfiguration添加了@Configuration注解,它從其他配置類里導入了一些額外配置,本身也定義了一些Bean。最重要的是,DataSourceAutoConfiguration上添加了@ConditionalOnClass注解,要求Classpath中必須要有DataSource和EmbeddedDatabaseType。如果這兩個類不存在,條件就不成立,DataSourceAutoConfiguration提供的配置都會被忽略掉。

  DataSourceAutoConfiguration里嵌入了一個 TomcatDataSourceJmxConfiguration 類,自動配置一個 dataSourceMBean Bean。

  TomcatDataSourceJmxConfiguration 使用了@Conditional注解,判斷 DataSourceAvailableCondition 條件是否成立——要有一個DataSource Bean或者要自動配置創建一個。

  總結

  SpringBoot利用Spring 4.0提供的條件化配置支持,實現了自動配置。其它應用樣例如下:

  1. 因為Classpath里有H2,所以會創建一個嵌入式的H2數據庫Bean,類型為javax.sql.DataSource,JPA實現(Hibernate)需要它來訪問數據庫;
  2. 因為Classpath里有Hibernate(Spring Data JPA傳遞引入的)的實體管理器,所以自動配置會配置與Hibernate相關的Bean,包括Spring的LocalContainerEntityManagerFactoryBean和JpaVendorAdapter;
  3. 因為Classpath里有SpringDataJPA,所以它會自動配置為根據數據庫的接口創建倉庫實現;
  4. 因為Classpath里有Thymeleaf,所以Thymeleaf會配置為SpringMVC的視圖,包括一個Thymeleaf的模板解析器、模板引擎及視圖解析器。視圖解析器會解析相對於Classpath根目錄的 /templates目錄里的模板;
  5. 因為Classpath里有SpringMVC(歸功於Web起步依賴),所以會配置Spring的DispatcherServlet並啟動SpringMVC;
  6. 因為這是一個Spring MVC Web應用程序,所以會注冊一個資源處理器,把相對於Classpath根目錄的 /static目錄里的靜態資源提供出來(還能處理 /public、/resources和 /META-INF/resources的靜態內容);
  7. 因為Classpath里有Tomcat,所以會啟動一個嵌入式的Tomcat容器,監聽8080端口(默認)。

  Spring Boot自動配置承擔起了配置Spring的重任,開發者只需專注於自己的應用程序即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM