当前位置: 首页 > 科技观察

SpringBoot如何覆盖自动配置

时间:2023-03-12 11:23:22 科技观察

转载本文请联系七哥聊聊编程公众号。本文提供了完整的代码示例,详见https://gitee.com/isevenluo/spring-road/的spring-road03目录。1.起源众所周知,SpringBoot提供了一个很棒的特性,可以帮助我们少写很多模板化的配置代码。这个特性就是:自动配置。比如SpringDataJPA和SpringSecurity,只要引入相关的依赖包,就会帮我们自动配置数据源bean和安全设置相关的bean,实现相应的功能,而无需我们自己编写配置。但是,在具体的应用中,我们的实际情况往往更加复杂,单靠Spring自动配置是无法满足我们的需求的。以安全配置为例。将SpringSecurity加入Classpath后,默认为我们的应用提供的安全设施就比较基础和简陋了。当我们访问Web上的应用程序时,会看到类似如下的认证对话框:这里的用户名为user,密码比较蛋疼。每次应用启动时随机生成并写入日志:SpringSecurity自动配置生成的密码虽然我们的应用算是一个安全的web应用,但是它也有以下显着的缺点:页面过于简单,这个对话框盒子很不友好;该应用程序只有一个登录用户;用户密码需要在应用启动日志中查看(默认用户名为user,密码是应用启动时随机生成并写入日志);那么如何调整自动配置,让Spring根据我们的需要进行配置呢?别着急,我们往下看。通常,我们有两种方式可以覆盖SpringBoot默认的自动配置:自定义配置Bean,以及通过修改外部属性进行配置。2.自定义配置bean覆盖自动配置第一种覆盖自动配置的方式是我们在不存在自动配置的情况下手动配置对应的SpringBean。配置方式可以选择XML或者Java配置。今天齐哥选择比较流行的Java配置形式来演示如何覆盖我们上面介绍的SpringSecurity的自动配置。我们所要做的就是编写一个扩展类。@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{privateLoggerlogger=LoggerFactory.getLogger(SecurityConfig.class);@ResourceprivateViewerRepositoryviewerRepository;@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.userDetailsS??ervice(用户名">{viewerRepository.save1,"{Viewer}ADMIN"));logger.info(viewerRepository.findViewerByUsername(username).toString());returnviewerRepository.findViewerByUsername(username);});}}上面代码中的SecurityConfig是一个非常基础的SpringSecurity配置,有了它我们SpringBoot应用程序跳过了安全自动配置,不再使用默认的用户名和密码,而是使用我们定义的用户名和密码进行身份验证。当然,上面的代码是不完整的,但剩下的类不是重点。我还定义了一个Viewer类,实现了UserDetails类(SpringSecurity中的用户界面),以及一个SpringDataJPA仓库接口来保存UserInfo。详细代码已经上传到开源仓库,需要的朋友可以自己拿~???这里再次强调:要覆盖SpringBoot的自动配置,我们只需要写一个显式的配置,那么SpringBoot会发现我们的配置,然后降低自动配置的优先级,看我们写哪个。3、通过配置属性来调整这个配置属性文件的自动配置,比上面自定义Bean的配置要简单的多。例如,假设我们只想调整一个数据库的URL,SpringSecurity的默认用户名,以及应用程序日志的级别。如果我们像上面那样重写自动配置,完全自己声明一个Bean,这就有点傻了!毕竟配置一个属性需要比完全写一个Bean配置要简单的多。如何配置属性?SpringBoot应用支持的配置源有很多,比如环境变量、命令行参数,当然还有最常见的属性文件中的配置。接下来,我将向您展示几个非常常见的示例。当SpringBoot应用程序启动时,命令行会打印一个Banner。如果你想禁用这个Banner,你可以将spring.main.banner-mode属性设置为off;添加属性前:在属性文件application.properties中添加属性spring.main.banner-mode=off后:结果已经在控制台打开了,启动时的Banner消失了。调整应用的日志配置;SpringBoot默认使用Logback进行日志记录,并以INFO级别输出到控制台。总的来说,Logback可以很好的满足我们的需求,但是这里为了演示,如果我们想使用Log4j2来替换默认的Logback实现,应该如何配置呢?以Gradle为例,我们只需要修改起始依赖,在构建描述文件中引入相应的日志实现,然后排除Logback即可。configurations{all*.excludegroup:'org.springframework.boot',module:'spring-boot-starter-logging'}我们排除上面默认的日志依赖后,就可以引入我们需要的Log4j2日志依赖了。dependencies{implementation'org.springframework.boot:spring-boot-starter-log4j2'}接下来如果需要做常规操作:修改日志级别,指定日志输出文件。当然,我们以往的做法是增加一个log4j2.xml文件来配置日志相关信息。虽然这样可以让我们完全掌握应用的日志配置,但是仅仅修改日志级别和日志输出文件根本不需要创建。log4j2.xml文件可以使用属性配置来实现。我们可以通过在SpringBoot应用的application.properties文件中添加logging开头的属性来达到我们的预期。//指定日志级别为debuglogging.level.root=debug//指定日志文件路径logging.file.name=/Users/sevenluo/IdeaProjects/spring-road/spring-labs/spring-road03/logs/spring-road03.目前的日志显示,SpringBoot应用自动配置的微调也是通过上述属性配置实现的。4.总结今天我们介绍了两种覆盖SpringBoot自动配置的方法。首先是自定义bean的配置。实现原理是通过Spring的条件配置。这一段有一个很重要的注解是@ConditionalOnMissingBean,意思是如果在我们的classpath中没有找到对应类型的bean,SpringBoot会自动帮我们配置一个。SpringBoot的设计是先加载我们应用中配置的类,然后再考虑自动配置类。二是通过配置属性来调整SpringBoot自动配置。实现的原理是将不同属性源中配置的属性的优先级设置为不同的,而我们应用属性文件中添加的属性配置优先级高于默认属性,从而实现调整自动配置的目的。今天先说到这里,更多关于Spring的内容也在持续更新中,敬请期待!