上线重启项目的时候发现了一个报错,因为我们用了redis队列接受消息,用了@PostConstruct注解启动blpop, 然后调数据库。项目一启动,来消息了,这时候要调数据库,发现找不到可用的连接,看日志发现数据库还没有初始化完。
我去看了看同事在其他用@PostConstruct注解的地方是怎么处理的,竟然是sleep20秒,太不优雅,就去翻翻百度,果然有,最后的最后还是被自己的无知打败了,多看源码啊!
使用ApplicationRunner接口或者CommandLineRunner都可以,这两个接口保证在springBoot管理的所有实例加载完后才运行
通过源码一探究竟:
1.首先是启动类:
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
2.进入run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
3.继续进run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
4.继续进run方法
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
5.进入最后的 this.callRunners(context, applicationArguments),看到结果了
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
Iterator var4 = (new LinkedHashSet(runners)).iterator();
while(var4.hasNext()) {
Object runner = var4.next();
if (runner instanceof ApplicationRunner) {
this.callRunner((ApplicationRunner)runner, args);
}
if (runner instanceof CommandLineRunner) {
this.callRunner((CommandLineRunner)runner, args);
}
}
}