如何为 TomcatServletWebServerFactory 禁用 SpringBoot 自动配置以便自定义 spring-starter 提供它?
How to disable SpringBoot autoconfiguration for TomcatServletWebServerFactory in order for a custom spring-starter to provide it?
所以我正在编写自己的 SpringBootStarter,它应该在 SpringBoot 应用程序的嵌入式 tomcat 中启用 JNDI 查找。
我的示例 SpringBoot 应用程序依赖于我的自定义 SpringBootStarter,而后者又依赖于 spring-boot-starter-web。如果我在示例 SpringBoot 应用程序中创建如下配置 class,则一切正常:
@Configuration
public class SampleSpringBootAppConfig {
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(org.apache.catalina.startup.Tomcat tomcat) {
System.out.println("CONFIGURING CUSTOM TOMCAT WEB SERVER FACTORY ");
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "org.postgresql.Driver");
resource.setProperty("url", "jdbc:postgresql://localhost:5432/postgres");
resource.setProperty("username", "postgres");
resource.setProperty("password", "postgres");
context.getNamingResources()
.addResource(resource);
}
};
}
因为SpringBoot找到了一个自定义Bean,所以不会有一个自动配置的默认Bean/它被覆盖并且成功启用了JNDI。
但是,一旦我将此 Bean 配置提取到我的自定义 SpringBoot Starter 的自动配置模块中,尝试启动示例 SpringBoot 应用程序时就会抛出以下异常:
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : tomcatServletWebServerFactory,tomcatFactory
我认为这是由于 SpringBoot 没有找到自定义的 Bean,因此创建了一个自动配置的默认 Bean,它也不会被覆盖。所以现在将有两个 ServletWebServerFactory beans,默认的一个和我的自动配置模块中的一个。
到目前为止我尝试了什么(无济于事):
- 用@Primary 注释我的自定义 Bean
- 将 spring.main.allow-bean-definition-overriding 设置为 true
有没有办法让 SpringBoot 不初始化自动配置的默认 bean,或者任何其他可能的解决方案?
我能够通过排除负责的自动配置来自己解决这个问题 class:
@SpringBootApplication ( exclude = ServletWebServerFactoryAutoConfiguration.class)
试试这个
@AutoConfigureBefore(ServletWebServerFactoryAutoConfiguration.class)
所以我正在编写自己的 SpringBootStarter,它应该在 SpringBoot 应用程序的嵌入式 tomcat 中启用 JNDI 查找。
我的示例 SpringBoot 应用程序依赖于我的自定义 SpringBootStarter,而后者又依赖于 spring-boot-starter-web。如果我在示例 SpringBoot 应用程序中创建如下配置 class,则一切正常:
@Configuration
public class SampleSpringBootAppConfig {
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(org.apache.catalina.startup.Tomcat tomcat) {
System.out.println("CONFIGURING CUSTOM TOMCAT WEB SERVER FACTORY ");
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "org.postgresql.Driver");
resource.setProperty("url", "jdbc:postgresql://localhost:5432/postgres");
resource.setProperty("username", "postgres");
resource.setProperty("password", "postgres");
context.getNamingResources()
.addResource(resource);
}
};
}
因为SpringBoot找到了一个自定义Bean,所以不会有一个自动配置的默认Bean/它被覆盖并且成功启用了JNDI。
但是,一旦我将此 Bean 配置提取到我的自定义 SpringBoot Starter 的自动配置模块中,尝试启动示例 SpringBoot 应用程序时就会抛出以下异常:
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : tomcatServletWebServerFactory,tomcatFactory
我认为这是由于 SpringBoot 没有找到自定义的 Bean,因此创建了一个自动配置的默认 Bean,它也不会被覆盖。所以现在将有两个 ServletWebServerFactory beans,默认的一个和我的自动配置模块中的一个。
到目前为止我尝试了什么(无济于事):
- 用@Primary 注释我的自定义 Bean
- 将 spring.main.allow-bean-definition-overriding 设置为 true
有没有办法让 SpringBoot 不初始化自动配置的默认 bean,或者任何其他可能的解决方案?
我能够通过排除负责的自动配置来自己解决这个问题 class:
@SpringBootApplication ( exclude = ServletWebServerFactoryAutoConfiguration.class)
试试这个 @AutoConfigureBefore(ServletWebServerFactoryAutoConfiguration.class)