聊一下 Spring 的 SmartLifecycle 使用
最近在学习过程中碰到一个比较有意思的Spring特性,就是 SmartLifecycle ,这个可以很轻松的融合进 Spring 生命周期1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public interface SmartLifecycle extends Lifecycle, Phased {
int DEFAULT_PHASE = Integer.MAX_VALUE;
default boolean isAutoStartup() {
return true;
}
default void stop(Runnable callback) {
this.stop();
callback.run();
}
default int getPhase() {
return Integer.MAX_VALUE;
}
}
接口继承了 org.springframework.context.Lifecycle
跟 org.springframework.context.Phased
其中默认实现了 isAutoStartup
, 并且默认是返回 true
,所以相对于 Lifecycle
能更智能些自动启动
然后 Lifecycle 这个接口就比较简单,只有几个接口1
2
3
4
5
6
7public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
我们可以是实现下这个接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MySmartLifecycle implements SmartLifecycle {
private volatile boolean isRunning;
public void start() {
System.out.println("my smart life cycle start");
isRunning = true;
}
public void stop() {
System.out.println("my smart life cycle end");
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
}
这个 bean
会在 Spring
启动后被自动调用 start
方法
这个就是在不深入 bean
的生命周期,并且是在 bean
已经都初始化以后调用
同样会在 spring
容器关闭时调用 stop
方法
如果有此类的需求就可以扩展此接口实现
而这个其实是在 spring 生命周期中的 finishRefresh 方法中进行调用1
2
3
4
5
6
7
8
9
10protected void finishRefresh() {
this.clearResourceCaches();
this.initLifecycleProcessor();
this.getLifecycleProcessor().onRefresh();
this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)));
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}
调用了 LifecycleProcessor
的 onRefresh
方法1
2
3
4public void onRefresh() {
this.startBeans(true);
this.running = true;
}
这其中就会调用 start
方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18private void startBeans(boolean autoStartupOnly) {
// 获取这些bean
Map<String, Lifecycle> lifecycleBeans = this.getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new TreeMap();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || bean instanceof SmartLifecycle && ((SmartLifecycle)bean).isAutoStartup()) {
int phase = this.getPhase(bean);
((LifecycleGroup)phases.computeIfAbsent(phase, (p) -> {
return new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
})).add(beanName, bean);
}
});
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}
会先判断 isAutoStartup
,然后将不同周期加入分组,然后再循环调用start