如何在注入 bean 失败时使 spring 启动 Web 应用程序退出非零

How to make spring boot web app exit non-zero when failing injecting a bean

我的应用程序中有一个 bean(基于 Spring Boot 1.5.3),由于加载大量资源,它需要时间来初始化。虽然该 bean 的初始化 Web 应用程序已经开始侦听端口,但 spring 启动应用程序仍然是 运行 即使该 bean 的初始化失败然后抛出异常。

但是应用程序仍然是 运行 尽管 bean 注入失败。

如果 bean 注入失败,使用错误代码退出 spring 网络应用程序的任何方法。

下面是注入我的bean的方法,

@Component
@Slf4j
@RefreshScope
@Profile("!integTest")
public class NoteSpellChecker {

private Directory spellIndexDirectory;
private SpellChecker spellChecker;

public NoteSpellChecker(@Value("${app.spellcheck.indexPath:build/suggest}") String spellIndexPath,
                        @Value("${app.spellcheck.accuracy:0.5f}") float spellAccuracy,
                        @Value("${app.spellcheck.suggestDirectory:${spring.cloud.config.uri}/${spring.application.name}" +
                                "/${spring.profiles.active}/${spring.cloud.config.label:master}/spellcheck/note.txt},")
                                String[] spellSuggestDirectories,
                        OkHttpClient httpClient) throws IOException {
**here run some initialization task that takes some time**
}

还有另一个 bean 依赖于 NoteSpellChecker。请参阅下面的代码片段,

@Configuration
@Slf4j
public class NoteDBConfig {

@Bean
public List<NoteRecognizer> noteRecognizers(NoteSpellChecker noteSpellChecker,
                                            NoteDBRepository noteDBRepository) {
    return noteDBRepository.findByEnabled(true).sorted((n1, n2) -> n1.getOrder() - n2.getOrder())
            .map(note -> new NoteRecognizerImpl(note, noteSpellChecker))
            .collect(Collectors.toList());
}
}

由于bean初始化错误导致spring启动应用程序启动失败,但JVM仍然运行没有退出。所以守护程序应用程序(启动 spring 启动应用程序)不知道我的应用程序的致命异常。

下面是控制台输出,

2017-04-28 17:36:54.483 ERROR [magiceye-server,,,] 32444 --- [
main] o.s.boot.SpringApplication : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.noteSpellChecker' defined in file [/.../service/impl/NoteSpellChecker.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [service.impl.NoteSpellChecker]: Constructor threw exception; nested exception is java.io.IOException at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:345) at org.springframework.cloud.context.scope.GenericScope$BeanLifecycleWrapper.getBean(GenericScope.java:359) at org.springframework.cloud.context.scope.GenericScope.get(GenericScope.java:176) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081) at org.springframework.cloud.context.scope.refresh.RefreshScope.start(RefreshScope.java:121) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:253) at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:174) at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:137) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:337) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:882) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) at BackendApplication.main(BackendApplication.java:21) Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [service.impl.NoteSpellChecker]: Constructor threw exception; nested exception is java.io.IOException at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271) ... 32 common frames omitted Caused by: java.io.IOException: null at service.impl.NoteSpellChecker.(NoteSpellChecker.java:69) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142) ... 34 common frames omitted

我发现这是由第三方库启动的守护线程引起的。