zoukankan      html  css  js  c++  java
  • 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的重任,开发者只需专注于自己的应用程序即可。

  • 相关阅读:
    codeforces 617 E. XOR and Favorite Number(莫队算法)
    bzoj 2038 [2009国家集训队]小Z的袜子(hose) 莫队算法
    HDU 6024 Building Shops (简单dp)
    Codeforces Round #417 B. Sagheer, the Hausmeister
    第九届ECNU Coder K.计软联谊
    解决在linux安装网易云音乐无法点击图标打开
    [洛谷P1169] [ZJOI2007]棋盘制作
    [洛谷P2577] [ZJOI2005]午餐
    [洛谷P1941] 飞扬的小鸟
    [洛谷P1600] 天天爱跑步
  • 原文地址:https://www.cnblogs.com/nyatom/p/9051681.html
Copyright © 2011-2022 走看看