当前位置: 首页 > 后端技术 > Java

SpringBoot自动配置,为你量身定做!

时间:2023-04-01 23:23:21 Java

前言自由选择真好。如果您曾经订购过比萨饼,您就会知道您可以完全控制比萨饼上的配料。当您选择萨拉米香肠、意大利辣香肠、青椒和额外的奶酪时,您就是在按照您想要的方式配置您的披萨。另一方面,大多数比萨店也提供某种形式的自动配置。您可以点肉比萨、素比萨、意大利辣比萨或终极自动配置比萨——至尊比萨。下订单时,您无需指定特定的浇头,您订购的披萨类型决定了使用的浇头。但是,如果您想要顶级披萨的所有配料,加上墨西哥胡椒,但没有蘑菇怎么办?喜欢吃辣不喜欢吃菌类,自动配置不适合你的口味,只能自己配置pizza?当然不是,大多数比萨店都会让您根据菜单上已有的选项进行定制。自动配置SpringBoot的自动配置是应用程序启动时的过程。考虑到很多因素,决定应该使用哪些Spring配置,哪些不应该使用。举几个例子,SpringBoot的自动配置考虑了以下几种情况。Classpath中有Spring的JdbcTemplate吗?如果有,并且有一个DataSource的Bean,那么会自动配置一个JdbcTemplate的Bean。类路径上有SpringSecurity吗?如果是,那么一个非常基本的网络安全设置。每次启动应用程序时,SpringBoot的自动配置都会做出近200个这样的决定,涵盖安全性、集成、持久性、Web开发等。所有这些自动配置都是为了让你尽可能不用自己写配置。可见SpringBoot自动配置承担了配置Spring的重任,让你可以专注于编写自己的应用。Condition-basedautomaticconfigurationCondition-based自动配置来源于Spring框架中的“condition-basedconfiguration”特性。在Spring框架中,我们可以使用@Conditional注解配合@Configuration或者@Bean等注解来干预某个配置或者bean定义是否生效。SpringBoot能够流行起来,很大一部分的功劳需要归功于它提前提供的一系列自动配置的依赖模块,而这些依赖模块都是基于上面的@Conditional复合注解实现的,也意味着这一切依赖模块是根据来加载的,这些依赖模块只有在满足一定条件的情况下才会生效。这就是我们所说的“智能”自动配置。调整自动配置的顺序在自动配置的过程中,除了提供基于条件的配置,我们还可以相应地调整当前配置或要提供的组件的加载顺序,使得这些配置或组件之间的依赖关系可以进行分析和组装可以顺利完成。我们可以使用@org.springframework.boot.autoconfigure.AutoConfigureBefore或@org.springframework.boot.autoconfigure.AutoConfigureAfter让当前配置或组件在其他组件之前或之后执行。配置如下:@Configuration@AutoConfigureAfter(MyTestBefore.class)publicclassMyTestAfter{...}自定义配置使用传统的Spring配置流程,就像订披萨时指定所有配件一样。您可以完全控制Spring配置的内容,但显式声明应用程序中的所有beans是不明智的。而SpringBoot的自动配置就像从菜单中选择一个特别的披萨。让SpringBoot处理各种细节要比自己在上下文中声明所有的bean容易得多。幸运的是,SpringBoot的自动配置非常灵活。就像比萨厨师可以在你的比萨中添加墨西哥辣椒而不是蘑菇一样,SpringBoot让你参与并影响自动配置的实现。覆盖自动配置在大多数情况下,自动配置的bean正是您所需要的,您不需要覆盖它们。但在某些情况下,SpringBoot在自动配置时不能很好地推断。让我们看看如何编写一个SpringSecurity配置来覆盖自动配置的安全设置。在编写显式配置时,我们专注于Java风格的配置。在SpringSecurity的上下文中,这意味着编写一个扩展WebSecurityConfigurerAdapter的配置类。示例代码如下:@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{//省略@Overridepublicvoidconfigure(WebSecurityweb)throwsException{web.ignoring().antMatchers("/js/**");web.ignoring().antMatchers("/css/**");web.ignoring().antMatchers("/health");//忽略登录界面web.ignoring().antMatchers("/login.html");web.ignoring().antMatchers("/index.html");}@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{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();}//Omit}在SecurityConfig中,第一个configure()方法重写了具有默认READER角色的用户的访问权限规则。第二个configure()方法基于安全考虑为特定的http请求重写配置。要覆盖SpringBoot的自动配置,您所要做的就是编写一个显式配置。为了理解它是如何工作的,让我们揭开SpringBoot自动配置的神秘面纱,看看它是如何工作的,以及它如何允许自身被覆盖。自动配置之谜SpringBoot自动配置自带了很多配置类,每一个都可以在你的应用中使用。它们都使用了Spring4.0的条件配置,可以在运行时决定是否应用或忽略这个配置。在大多数情况下,@ConditionalOnMissingBean注释是覆盖自动配置的关键。SpringBoot的DataSourceAutoConfiguration中定义的JdbcTemplateBean是一个很简单的例子:@Bean@ConditionalOnMissingBean(JdbcOperations.class)publicJdbcTemplatejdbcTemplate(){returnnewJdbcTemplate(this.dataSource);}@Bean被添加到jdbcTemplate()方法注可以在需要时配置JdbcTemplateBean。但是它也增加了@ConditionalOnMissingBean注解,要求没有JdbcOperations类型的Bean(JdbcTemplate实现了这个接口)才生效。如果已经有JdbcOperationsBean,则不满足条件,则不会执行jdbcTemplate()方法。什么情况下会有JdbcOperationsBean呢?SpringBoot旨在加载应用程序级别的配置,然后考虑自动配置类。因此,如果你已经配置了一个JdbcTemplateBean,那么自动配置的时候已经存在一个JdbcOperations类型的Bean,所以自动配置的JdbcTemplateBean会被忽略。尽管SpringBoot的自动配置和@ConditionalOnMissingBean允许您显式覆盖那些可以自动配置的bean,但不必每次都这样做。让我们看看如何通过设置一些简单的配置属性来调整自动配置的组件。通过属性文件进行外部配置在处理应用程序安全性时,您当然希望完全控制所有配置。然而,放弃自动配置以微调一些细节,如更改端口号和日志级别,将是一种耻辱。设置数据库URL,是配置一个属性那么简单,还是声明一个数据源bean那么简单?答案是不言自明的,不是吗?事实上,SpringBoot自动配置的beans提供了300多个属性用于微调。当您调整设置时,只需在环境变量、Java系统属性、JNDI(Java命名和目录接口)、命令行参数或属性文件中指定它们。SpringBoot有一个ascii-artBanner。如果要禁用此Banner,可以将spring.main.show-banner属性设置为false。有几种实现方式:在运行应用的命令行参数中指定$java-jarfs-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其实设置SpringBoot应用的方式有很多种。SpringBoot可以从多种属性来源获取属性,包括以下几种。(1)命令行参数(2)操作系统环境变量(3)应用外的application.properties或appliaction.yml文件(4)应用内打包的application.properties或appliaction.yml文件(5)通过@property源由PropertySource(6)标记的默认属性列表按优先级排序,即在高优先级属性源中设置的任何属性将覆盖具有低优先级的相同属性。例如,命令行参数会覆盖其他属性源中的属性。application.properties和application.yml文件可以放在以下四个位置。(1)外部,在应用运行目录相对的/config子目录下。(2)外部,在应用程序运行的目录中。(3)内置,在config包中。(4)内置,在Classpath的根目录下。同样,此列表按优先级排序。也就是说,/config子目录中的application.properties将覆盖应用程序类路径中application.properties中的相同属性。此外,如果application.properties和application.yml具有相同的优先级,application.yml中的属性将覆盖application.properties中的属性。在一个类中收集属性虽然我们可以在服务层或控制器层添加ConfigurationProperties注解,这样它就可以正常工作,但这不是一个理想的解决方案。与其在ReadingListController中加载配置属性,不如创建一个单独的bean,为其添加@ConfigurationProperties注解,让??这个bean收集所有配置属性。如下:@Component@ConfigurationProperties("fs")//注入以fs为前缀的属性publicclassDBConfig{privateStringip;publicStringgetIp(){返回ip;}publicvoidsetIp(Stringip){this.ip=ip;}}使用Profile配置当应用需要部署到不同的运行环境时,一些配置细节通常是不同的。例如,数据库连接的细节在开发环境和测试环境会有所不同,在生产环境也会有所不同。SpringFramework从Spring3.1开始支持基于Profile的配置。Profile是一种条件配置,根据运行时激活的profile使用或忽略不同的bean或配置类。可以通过设置spring.profiles.active属性来激活配置文件。任何设置配置属性的方式都可以用来设置这个值。例如,当在命令行上运行应用程序时,您可以像这样激活生产配置文件:$java-jarfs-base-service-1.0-SNAPSHOT.jar--spring.profiles.active=dev您还可以添加spring到application.yml.profiles.activeproperty:spring:profiles:active:dev使用Profile-specificpropertiesfiles如果你正在使用application.properties,你可以创建额外的属性文件,遵循命名格式application-{profile}.properties,以便现在可以提供特定于配置文件的属性。在日志示例中,开发环境的配置可以放在名为application-dev.properties的文件中,其中包括日志级别和控制台输出:logging.level.root=DEBUG。对于生产环境,application-prod.properties会将日志级别设置为WARN或更高。使用多profileYAML文件进行配置如果使用YAML配置属性,可以遵循与配置文件相同的命名约定,即创建一个YAML文件,如application{profile}.yml,并保留具有的属性与应用程序中的配置文件无关。yml。但是由于使用了YAML,您可以将Profile的所有配置属性放在一个application.yml文件中。例如,我们可以这样声明日志记录配置:您可以看到,application.yml文件分为三个部分,使用一组三个连字符(---)作为分隔符。第二段和第三段分别为spring.profiles指定了一个值,表示这部分配置应该应用到哪个Profile上。第二段定义的属性适用于开发环境,因为spring.profiles设置为dev。同样,spring.profile的最后一段设置为prod,prodProfile激活时生效。另一方面,第一段没有指定spring.profiles,所以这里的properties对所有的Profiles都有效,或者对那些没有设置这个property的activeProfiles有效。总结SpringBoot消除了Spring应用程序中常见的许多样板配置。让SpringBoot处理所有配置,您可以依靠它来配置适合您的应用程序的组件。当自动配置无法满足您的需求时,SpringBoot允许您覆盖和微调它提供的配置。覆盖自动配置实际上就像显式编写没有SpringBoot的Spring配置一样简单。SpringBoot的自动配置旨在优先考虑应用程序提供的配置而不是它自己的自动配置。即使自动配置很好,您仍然需要调整一些细节。SpringBoot会开启多个属性解析器,允许你通过环境变量、属性文件、YAML文件等方式设置属性,从而微调配置。这种基于属性的配置模型也可以用于应用程序本身定义的组件,它可以从外部配置源加载属性并将它们注入到bean中。SpringBoot中的参数传递过程和配置文件加载,特别是profile-based加载机制。至于加载、默认配置、配置优先级等操作,都位于ConfigFileApplicationListener类中,值得读者花时间研究。最后一篇为初学者提供学习指南,对从业者有参考价值。我坚信编码员也有能力产生洞察力。扫描下方二维码关注、学习、交流!