MENU

Spring Boot 之 Configuration

June 24, 2017 • Read: 839 • Spring

在上一篇的Starter项目中,加入了两三个依赖就完成了一个CRUD的Web项目;Spring Boot是如何实现自动配置的呢?

如果是一个普通的Spring项目,我们需要较多的配置,比如web.xml中配置ContextLoaderListener,配置DispatcherServlet等,在Spring的配置文件中配置数据源、页面模版、JOSN序列化、静态资源等等;而在Spring Boot项目中,这些都在内部进行了配置,完全的约定优于配置,像端口监听8080、把/static目录暴露为静态资源、Thymeleaf模版文件要放在/templates目录。

在项目的依赖中找到spring-boot-autoconfigure这个jar,会发现很多配置类,挑个简单的打开看看,就ThymeleafProperties吧,下面是代码片段:

@ConfigurationProperties("spring.thymeleaf")
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");
    private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML5";
    private Charset encoding;
    private MimeType contentType;
    private boolean cache;
    private Integer templateResolverOrder;
    private String[] viewNames;
    private String[] excludedViewNames;
    private boolean enabled;

看到这大概就明白这些自动配置是怎么回事了,配置一个都没少只是换地方了;不过,还有一个问题,这么配置项都在项目启动时进行配置肯定是不行;一定是按需配置的,依赖了Thymeleaf才去启动Thymeleaf的配置。这就用到了Spring 4.0的新特性,条件化配置;条件成立时才启用配置。

Spring Boot中定义了很多条件化配置的注解,用于配置类;配置类和条件化注解共同构成了自动配置。

条件化注解配置生效条件
@ConditionalOnBean配置了某个特定Bean
@ConditionalOnMissingBean没有配置特定的Bean
@ConditionalOnClassClasspath里有指定的类
@ConditionalOnMissingClassClasspath里缺少指定的类

以上列举了几个简单的注解,还是Thymeleaf自动配置为例,以下为ThymeleafAutoConfiguration代码片段

    @Configuration
    @ConditionalOnWebApplication
    protected static class ThymeleafResourceHandlingConfig {
        protected ThymeleafResourceHandlingConfig() {
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnEnabledResourceChain
        public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
            return new ResourceUrlEncodingFilter();
        }
    }

    @Configuration
    @ConditionalOnJava(JavaVersion.EIGHT)
    @ConditionalOnClass({Java8TimeDialect.class})
    protected static class ThymeleafJava8TimeDialect {
        protected ThymeleafJava8TimeDialect() {
        }

        @Bean
        @ConditionalOnMissingBean
        public Java8TimeDialect java8TimeDialect() {
            return new Java8TimeDialect();
        }
    }

@ConditionalOnWebApplication表示在web应用中生效,ConditionalOnMissingBean表示不存在这个Bean时才生效,@ConditionalOnJava(JavaVersion.EIGHT)表示在Java8中生效;根据注解名字基本就能了解其条件含义。

Last Modified: July 21, 2019