如何在 Spring boot 2.1.0 启动器配置中将 spring.main.allow-bean-definition-overriding 设置为 true
How to set spring.main.allow-bean-definition-overriding to true in a Spring boot 2.1.0 starter configuration
我维护了一个 spring-boot-starter,用于自定义返回的错误属性,例如,调用未知端点时。
这是通过覆盖 org.springframework.boot.web.servlet.error.ErrorAttributes bean 来完成的。
在 2.0.6 上一切正常,但是 2.1.0 disables bean overriding by default,启动器现在失败并显示以下消息。
Invalid bean definition with name 'errorAttributes' defined in class
path resource
[com/mycompany/springboot/starter/config/ErrorsConfig.class]: Cannot
register bean definition [Root bean: class [null]; scope=;
abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0;
autowireCandidate=true; primary=false;
factoryBeanName=com.mycompany.springboot.starter.config.ErrorsConfig;
factoryMethodName=errorAttributes; initMethodName=null;
destroyMethodName=(inferred); defined in class path resource
[com/mycompany/springboot/starter/config/ErrorsConfig.class]] for bean
'errorAttributes': There is already [Root bean: class [null]; scope=;
abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0;
autowireCandidate=true; primary=false;
factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
factoryMethodName=errorAttributes; initMethodName=null;
destroyMethodName=(inferred); defined in class path resource
[org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]]
bound
如文档中所述,将 spring.main.allow-bean-definition-overriding 属性 设置为 true 可解决问题。
我的问题是如何 在 starter 中做到这一点(我不希望我的 starter 的用户必须更改他们的 application.properties 文件,因为这是特定于我的 starter )?
我尝试使用该文件中定义的 属性 对我的 @Configuration 添加 @PropertySource("classpath:/com/mycompany/starter/application.properties") 注释,但它不起作用。
我错过了什么?有什么方法可以让我的配置覆盖那个 bean 吗?
这里是配置的(简化)源代码:
@Configuration
@PropertySource("classpath:/com/mycompany/starter/application.properties")
public class ErrorsConfig {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Bean
public ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {
@SuppressWarnings("unchecked")
@Override
public Map<String, Object> getErrorAttributes(WebRequest request, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(request, includeStackTrace);
// CustomeError is a (simplified) bean of the error attributes we should return.
CustomError err = new CustomError("myErrorCode", (String) errorAttributes.get("error"));
return OBJECT_MAPPER.convertValue(err, Map.class);
}
};
}
}
我的资源文件com/mycompany/starter/application.properties 包含
spring.main.allow-bean-definition-overriding=true
Spring Boot 的 ErrorAttributes
bean 由 ErrorMvcAutoConfiguration
定义。它用 @ConditionalOnMissingBean
注释,因此如果已经定义了 ErrorAttributes
bean,它就会退出。由于您的 ErrorsConfig
class 定义的 bean 试图覆盖 Boot 的 ErrorAttributes
bean 而不是使其后退,因此您的 ErrorsConfig
class 必须得到处理在 Boot 的 ErrorMvcAutoConfiguration
class 之后。这意味着您的启动器中存在排序问题。
可以使用 @AutoConfigureBefore
和 @AutoConfigureAfter
控制处理自动配置 classes 的顺序。假设 ErrorsConfig
本身是在 spring.factories
中注册的自动配置 class,您可以通过使用 @AutoConfigureBefore(ErrorMvcAutoConfiguration.class)
对其进行注释来解决您的问题。通过此更改,ErrorsConfig
将在 ErrorMvcAutoConfiguration
尝试定义其 ErrorAttributes
bean 之前定义它,这将导致 Boot 的 ErrorsAttribute
bean 的自动配置后退。
更简单的解决方案是在 application.properties
.
中添加此 属性 spring.main.allow-bean-definition-overriding=true
我维护了一个 spring-boot-starter,用于自定义返回的错误属性,例如,调用未知端点时。 这是通过覆盖 org.springframework.boot.web.servlet.error.ErrorAttributes bean 来完成的。
在 2.0.6 上一切正常,但是 2.1.0 disables bean overriding by default,启动器现在失败并显示以下消息。
Invalid bean definition with name 'errorAttributes' defined in class path resource [com/mycompany/springboot/starter/config/ErrorsConfig.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=com.mycompany.springboot.starter.config.ErrorsConfig; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/mycompany/springboot/starter/config/ErrorsConfig.class]] for bean 'errorAttributes': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]] bound
如文档中所述,将 spring.main.allow-bean-definition-overriding 属性 设置为 true 可解决问题。 我的问题是如何 在 starter 中做到这一点(我不希望我的 starter 的用户必须更改他们的 application.properties 文件,因为这是特定于我的 starter )?
我尝试使用该文件中定义的 属性 对我的 @Configuration 添加 @PropertySource("classpath:/com/mycompany/starter/application.properties") 注释,但它不起作用。
我错过了什么?有什么方法可以让我的配置覆盖那个 bean 吗?
这里是配置的(简化)源代码:
@Configuration
@PropertySource("classpath:/com/mycompany/starter/application.properties")
public class ErrorsConfig {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Bean
public ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {
@SuppressWarnings("unchecked")
@Override
public Map<String, Object> getErrorAttributes(WebRequest request, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(request, includeStackTrace);
// CustomeError is a (simplified) bean of the error attributes we should return.
CustomError err = new CustomError("myErrorCode", (String) errorAttributes.get("error"));
return OBJECT_MAPPER.convertValue(err, Map.class);
}
};
}
}
我的资源文件com/mycompany/starter/application.properties 包含
spring.main.allow-bean-definition-overriding=true
Spring Boot 的 ErrorAttributes
bean 由 ErrorMvcAutoConfiguration
定义。它用 @ConditionalOnMissingBean
注释,因此如果已经定义了 ErrorAttributes
bean,它就会退出。由于您的 ErrorsConfig
class 定义的 bean 试图覆盖 Boot 的 ErrorAttributes
bean 而不是使其后退,因此您的 ErrorsConfig
class 必须得到处理在 Boot 的 ErrorMvcAutoConfiguration
class 之后。这意味着您的启动器中存在排序问题。
可以使用 @AutoConfigureBefore
和 @AutoConfigureAfter
控制处理自动配置 classes 的顺序。假设 ErrorsConfig
本身是在 spring.factories
中注册的自动配置 class,您可以通过使用 @AutoConfigureBefore(ErrorMvcAutoConfiguration.class)
对其进行注释来解决您的问题。通过此更改,ErrorsConfig
将在 ErrorMvcAutoConfiguration
尝试定义其 ErrorAttributes
bean 之前定义它,这将导致 Boot 的 ErrorsAttribute
bean 的自动配置后退。
更简单的解决方案是在 application.properties
.
spring.main.allow-bean-definition-overriding=true