SmartLifecycle是一个扩展了Lifecycle接口,可以跟踪spring容器ApplicationContext刷新或者关闭的接口,实现该接口的实现类有特定的执行顺序。
当ApplicationContext刷新时,所有bean都加载和初始化完成后,根据isAutoStartup和isRunning判断是否自动执行start()
1.新建TestSmartLifecycle类
public class TestSmartLifecycle implements SmartLifecycle {
@Override
public void start() {
System.out.println("TestSmartLifecycle is start");
}
//SmartLifecycle组件停止后的回调,程序被异步关闭
@Override
public void stop() {
System.out.println("SmartLifecycle is stop");
}
//为false,并且isAutoStartup为true,执行start方法
//为true,执行stop方法。
@Override
public boolean isRunning() {
return false;
}
//如果为true,实现了SmartLifecycle 接口的组件,能再ApplicationContext已经刷新的时候,自动执行start方法,
@Override
public boolean isAutoStartup() {
return true;
}
//当running为true时,再应用关闭时会执行stop(Runnable callback)方法,
如果再执行完stop后,running没有设置为false时,应用会卡住一段时间,无法退出
@Override
public void stop(Runnable callback) {
System.out.println("TestSmartLifecycle is stop");
callback.run();
}
@Override
public int getPhase() {
return 0;
}
}
2.配置Bean
@Configuration
public class TestConfiguration {
@Bean
TestSmartLifecycle testSmartLifecycle(){
return new TestSmartLifecycle();
}
}
3.debugger启动应用程序
可以看见如下的调用链,大致是SpringApplication.run(CommonsTestApplication.class, args)-->refreshContext-->refresh-->startBeans-->start,其中,再startBean中获取了所有实现SmartLifecycle的非懒加载的bean,并再start方法中,调用对应实现bean的start方法,执行相应的逻辑,具体可看下面截图。
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}