关于后端:Spring-Boot自动化配置为你量身定制

5次阅读

共计 6777 个字符,预计需要花费 17 分钟才能阅读完成。

前言

能自由选择真是太棒了。如果你订过比萨就会晓得,你齐全能够掌控薄饼上放哪些辅料。选定腊肠、意大利辣香肠、青辣椒和额定芝士的时候,你就是在依照本人的要求配置比萨。另一方面,大部分比萨店也提供某种模式的主动配置。你能够点荤比萨、素比萨、香辣意大利比萨,或者是主动配置比萨中的极品——至尊比萨。在下单时,你并没有指定具体的辅料,你所点的比萨品种决定了所用的辅料。但如果你想要至尊比萨上的全副辅料,还想要加墨西哥胡椒,又不想放蘑菇该怎么办?你偏爱辣食又不喜爱吃菌类,主动配置不适宜你的口味,你就只能本人配置比萨了吗?当然不是,大部分比萨店会让你以菜单上已有的选项为根底进行定制。

主动配置

Spring Boot 的主动配置是应用程序启动时的过程,思考了泛滥因素,才决定 Spring 配置应该用哪个,不该用哪个。举几个例子,上面这些状况都是 Spring Boot 的主动配置要思考的。

Spring 的 JdbcTemplate 是不是在 Classpath 里?如果是,并且有 DataSource 的 Bean,则主动配置一个 JdbcTemplate 的 Bean。Spring Security 是不是在 Classpath 里?如果是,则进行一个十分根本的 Web 平安设置。

每当应用程序启动的时候,Spring Boot 的主动配置都要做将近 200 个这样的决定,涵盖平安、集成、长久化、Web 开发等诸多方面。所有这些主动配置就是为了尽量不让你本人写配置。由此可见,Spring Boot 主动配置承当起了配置 Spring 的重任,因而你能专一于编写本人的应用程序。

  • 基于条件的主动配置
    基于条件的主动配置来源于 Spring 框架中“基于条件的配置”这一个性。在 Spring 框架中,咱们能够应用 @Conditional 这个 Annotation 配合 @Configuration 或者 @Bean 等 Annotation 来干涉一个配置或者 bean 定义是否可能失效。
    SpringBoot 可能风靡,很大一部分功绩须要归功于它事后提供的一系列主动配置的依赖模块,而这些依赖模块都是基于以上 @Conditional 复合 Annotation 实现的,这也意味着所有的这些依赖模块都是按需加载的,只有合乎某些特定条件,这些依赖模块才会失效,这也就是咱们所谓的“智能”主动配置。
  • 调整主动配置的程序
    在实现主动配置的过程中,除了能够提供基于条件的配置,咱们还能够对以后要提供的配置或者组件的加载程序进行相应调整,从而让这些配置或者组件之间的依赖剖析和组装能够顺利完成。咱们能够应用 @org.springframework.boot.autoconfigure.AutoConfigureBefore 或者 @org.springframework.boot.autoconfigure.AutoConfigureAfter 让以后配置或者组件在某个其余组件之前或者之后进行。如下配置:

    @Configuration@AutoConfigureAfter(MyTestBefore.class)
    public class MyTestAfter {...} 
    

自定义配置

应用传统 Spring 配置的过程,就如同订比萨的时候本人指定全副的辅料。你能够齐全掌控 Spring 配置的内容,可是显式申明应用程序里全副的 Bean 并不是明智之举。而 Spring Boot 主动配置就像是从菜单上选一份特色比萨,让 Spring Boot 解决各种细节比本人申明上下文里全副的 Bean 要容易很多。
侥幸的是,Spring Boot 主动配置非常灵活。就像比萨厨师能够不在你的比萨里放蘑菇,而是加墨西哥胡椒一样,Spring Boot 能让你参加进来,影响主动配置的施行。

笼罩主动配置

大多数状况下,主动配置的 Bean 刚好能满足你的须要,不须要去笼罩它们。但某些状况下,Spring Boot 在主动配置时还不能很好地进行推断。让咱们看看如何写出 Spring Secuirty 配置,笼罩主动配置的平安设置吧。在编写显式配置时,咱们会专一于 Java 模式的配置。在 Spring Security 的场景下,这意味着写一个扩大了 WebSecurityConfigurerAdapter 的配置类。示例代码如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 省略
    @Override
    public void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers("/js/**");
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/health");
        // 疏忽登录界面
        web.ignoring().antMatchers("/login.html");
        web.ignoring().antMatchers("/index.html");
    }
    
     @Override
    protected void configure(HttpSecurity http) throws Exception {http.csrf().disable();

        http.authorizeRequests()
                .anyRequest().authenticated();
        http.formLogin().loginPage("/login.html").loginProcessingUrl("/user/login")
                .successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler);
        
        // 解决不容许显示在 iframe 的问题
        http.headers().frameOptions().disable();
        http.headers().cacheControl();
    }
    // 省略
}

在 SecurityConfig 里,第一个 configure()办法重写了默认 READER 角色的用户的拜访权限规定。第二个 configure()办法重写了对特定的 http 申请基于平安思考进行配置。

想要笼罩 Spring Boot 的主动配置,你所要做的仅仅是编写一个显式的配置。想弄明确这是如何实现的,让咱们揭开 Spring Boot 主动配置的神秘面纱,看看它是如何运作的,以及它是怎么容许本人被笼罩的。

主动配置的神秘面纱

Spring Boot 主动配置自带了很多配置类,每一个都能使用在你的应用程序里。它们都应用了 Spring 4.0 的条件化配置,能够在运行时判断这个配置是该被使用,还是该被疏忽。大部分状况下 @ConditionalOnMissingBean 注解是笼罩主动配置的要害。Spring Boot 的 DataSourceAutoConfiguration 中定义的 JdbcTemplate Bean 就是一个非常简单的例子:

@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {return new JdbcTemplate(this.dataSource);
}

jdbcTemplate()办法上增加了 @Bean 注解,在须要时能够配置出一个 JdbcTemplate Bean。但它下面还加了 @ConditionalOnMissingBean 注解,要求以后不存在 JdbcOperations 类型(JdbcTemplate 实现了该接口)的 Bean 时才失效。如果以后曾经有一个 JdbcOperations Bean 了,条件即不满足,不会执行 jdbcTemplate()办法。

什么状况下会存在一个 JdbcOperations Bean 呢?Spring Boot 的设计是加载利用级配置,随后再思考主动配置类。因而,如果你曾经配置了一个 JdbcTemplate Bean,那么在执行主动配置时就曾经存在一个 JdbcOperations 类型的 Bean 了,于是疏忽主动配置的 JdbcTemplate Bean。

尽管 Spring Boot 的主动配置和 @ConditionalOnMissingBean 让你能显式地笼罩那些能够主动配置的 Bean,但并不是每次都要做到这种水平。让咱们来看看怎么通过设置几个简略的配置属性调整主动配置组件吧。

通过属性文件外置配置

在解决利用平安时,你当然会心愿齐全掌控所有配置。不过,为了微调一些细节,比方改改端口号和日志级别,便放弃主动配置,这是一件让人惭愧的事。为了设置数据库 URL,是配置一个属性简略,还是残缺地申明一个数据源的 Bean 简略?答案不言自明,不是吗?
事实上,Spring Boot 主动配置的 Bean 提供了 300 多个用于微调的属性。当你调整设置时,只有在环境变量、Java 零碎属性、JNDI(Java Namingand Directory Interface)、命令行参数或者属性文件里进行指定就好了。

Spring Boot 有一个 ascii-artBanner。如果你想禁用这个 Banner,能够将 spring.main.show-banner 属性设置为 false。有几种实现形式:

  • 运行应用程序的命令行参数里指定

    $ java -jar fs-base-service-1.0-SNAPSHOT.jar –spring.main.show-banner=fals

  • 在 application.properties 的文件配置

    spring.main.show-banner=fals

  • 在 application.yml 的文件配置

    spring:

    main:
      show-banner: false
    

实际上,Spring Boot 应用程序有多种设置路径。Spring Boot 能从多种属性源取得属性,包含如下几处。
(1)命令行参数
(2)操作系统环境变量
(3)应用程序以外的 application.properties 或者 appliaction.yml 文件
(4)打包在应用程序内的 application.properties 或者 appliaction.yml 文件
(5)通过 @PropertySource 标注的属性源
(6)默认属性
这个列表依照优先级排序,也就是说,任何在高优先级属性源里设置的属性都会笼罩低优先级的雷同属性。例如,命令行参数会笼罩其余属性源里的属性。application.properties 和 application.yml 文件能放在以下四个地位。
(1)外置,在绝对于利用程序运行目录的 /config 子目录里。
(2)外置,在利用程序运行的目录里。
(3)内置,在 config 包内。
(4)内置,在 Classpath 根目录。
同样,这个列表依照优先级排序。也就是说,/config 子目录里的 application.properties 会笼罩应用程序 Classpath 里的 application.properties 中的雷同属性。
此外,如果你在同一优先级地位同时有 application.properties 和 application.yml,那么 application.yml 里的属性会笼罩 application.properties 里的属性。

在一个类里收集属性

尽管咱们能够在 service 或 controller 层加上 ConfigurationProperties 注解,这样运行起来也没问题,但这不是一个现实的计划。与其在 ReadingListController 里加载配置属性,还不如创立一个独自的 Bean,为它加上 @ConfigurationProperties 注解,让这个 Bean 收集所有配置属性。如下所示:

@Component
@ConfigurationProperties("fs")    // 注入带 fs 前缀的属性
public class DBConfig {
      private String ip;
    
        public String getIp() {return ip;}

    public void setIp(String ip) {this.ip = ip;}
}

应用 Profile 进行配置

当应用程序须要部署到不同的运行环境时,一些配置细节通常会有所不同。比方,数据库连贯的细节在开发环境下和测试环境下就会不一样,在生产环境下又不一样。Spring Framework 从 Spring 3.1 开始反对基于 Profile 的配置。Profile 是一种条件化配置,基于运行时激活的 Profile,会应用或者疏忽不同的 Bean 或配置类。设置 spring.profiles.active 属性就能激活 Profile,任意设置配置属性的形式都能用于设置这个值。例如,在命令行里运行应用程序时,能够这样激活 production Profile:

$ java -jar fs-base-service-1.0-SNAPSHOT.jar -- spring.profiles.active=dev

也能够向 application.yml 里增加 spring.profiles.active 属性:

spring:
  profiles:    
      active: dev
  • 应用特定于 Profile 的属性文件

如果你正在应用 application.properties,能够创立额定的属性文件,遵循 application-{profile}.properties 这种命名格局,这样就能提供特定于 Profile 的属性了。在日志这个例子里,开发环境的配置能够放在名为 application-dev.properties 的文件里,配置蕴含日志级别和输入到控制台:logging.level.root=DEBUG。对于生产环境,application-prod.properties 会将日志级别设置为 WARN 或更高级别。

  • 应用多 Profile YAML 文件进行配置

如果应用 YAML 来配置属性,则能够遵循与配置文件雷同的命名标准,即创立 application{profile}.yml 这样的 YAML 文件,并将与 Profile 无关的属性持续放在 application.yml 里。
但既然用了 YAML,你就能够把所有 Profile 的配置属性都放在一个 application.yml 文件里。举例来说,咱们能够像上面这样申明日志配置:

logging:
  level:
    root: INFO
---
spring:  
    profiles: dev
logging:
  level:
    root: DEBUG
---spring:  
    profiles: prod
logging:
   level:
     root: WARN

如你所见,这个 application.yml 文件分为三个局部,应用一组三个连字符(—)作为分隔符。第二段和第三段别离为 spring.profiles
指定了一个值,这个值示意该局部配置应该利用在哪个 Profile 里。第二段中定义的属性利用于开发环境,因为 spring.profiles
设置为 dev。与之相似,最初一段的 spring.profile 设置为 prod,在 prodProfile 被激活时失效。
另一方面,第一段并未指定 spring.profiles,因而这里的属性对全副 Profile 都失效,或者对那些未设置该属性的激活 Profile 失效。

总结

Spring Boot 打消了 Spring 应用程序中常常要用到的很多样板式配置。让 Spring Boot 解决全副配置,你能够凭仗它来配置那些适宜你的应用程序的组件。当主动配置无奈满足需要时,Spring Boot 容许你笼罩并微调它提供的配置。

笼罩主动配置其实很简略,就是显式地编写那些没有 Spring Boot 时你要做的 Spring 配置。Spring Boot 的主动配置被设计为优先应用应用程序提供的配置,而后才轮到本人的主动配置。
即便主动配置适合,你依然须要调整一些细节。Spring Boot 会开启多个属性解析器,让你通过环境变量、属性文件、YAML 文件等多种形式来设置属性,以此微调配置。这套基于属性的配置模型也能用于应用程序本人定义的组件,能够从内部配置源加载属性并注入到 Bean 里。

Spring Boot 中参数的传递过程和配置文件的加载,特地是基于 profile 的加载机制。而对于加载、默认配置、配置优先级等操作,都位于 ConfigFileApplicationListener 类中,该类还是值得读者敌人花工夫钻研一下的。

最初的最初

为初学者提供学习指南,为从业者提供参考价值。我深信码农也具备产生洞见的能力。扫描下图二维码关注,学习和交换!

正文完
 0