为什么自动配置类的顺序有所不同?

时间:2019-05-10 14:40:35

标签: java spring-boot gradle

我正在使用Spring Boot 2.1.4.RELEASE。

我有三个gradle模块:应用程序,集成测试和Web。应用程序和集成测试都取决于Web,Web取决于我编写的库。该库具有以下类:

@Configuration
public class WebErrorAutoConfiguration {

    @Bean
    public CatchAllExceptionHandler catchAllExceptionHandler() {
        return new CatchAllExceptionHandler();
    }

    @ConditionalOnBean(ErrorAttributes.class)
    @Bean
    public ErrorController errorController(ErrorAttributes errorAttributes) {
        return new ErrorController(errorAttributes);
    }
}

上述类包含在spring.factories中。

应用程序模块中的@SpringBootApplication可以很好地部署,但是集成测试模块中的@SpringBootApplication不能。错误是:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'errorController' method 
public org.springframework.http.ResponseEntity<?> com.sample.package.ErrorController.handleError(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
to { /error}: There is already 'basicErrorController' bean method

我理解原因:我的ErrorController无法实例化,因为已经为/ error定义了处理程序。我不明白为什么在集成测试之外部署应用程序时不会发生这种情况。

Spring如何确定自动配置类的执行顺序?我可以通过将@AutoConfigureBefore(ErrorMvcAutoConfiguration.class)添加到我的WebErrorAutoConfiguration.class来解决此问题,但我想了解两个模块之间的行为差​​异。我已经查看了在ClassLoader中加载的jar的顺序,但是在这两个实例中,我的库都是在Spring之前加载的。

1 个答案:

答案 0 :(得分:0)

spring boot自动配置中的顺序是不同的,因为除非放置@AutoConfigureBefore@AutoConfigureAfter等注释,否则它们无法确保顺序。

当您不指定它们时,它很大程度上取决于您的类路径(在OS,env,build-tools等之间可能有所不同),并且spring命令会读取模块列表。在每种环境中,它可能会略有不同,并且如果要确保执行所需的订单,则需要指定订单。

请注意,您的主应用程序中的任何内容(包中带有@SpringBootApplication的类中的任何内容)都将首先加载,并且提及的支持自动配置模块顺序的注释不会影响这些配置