闽公网安备 35020302035485号
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
这个接口一共就三个方法:isRunning:这个是返回组件是否已经处于运行状态了,对于容器来说,只有当容器中的所有适用组件都处于运行状态时,这个方法返回 true,否则返回 false。
@Component
public class MyLifeCycle implements Lifecycle {
private volatile boolean running;
@Override
public void start() {
running = true;
System.out.println("start");
}
// 堆代码 duidaima.com
@Override
public void stop() {
running = false;
System.out.println("stop");
}
@Override
public boolean isRunning() {
return running;
}
}
需要自定义一个 running 变量,该变量用来描述当前组件是否处于运行/停止状态,因为系统在调用 start 和 stop 方法的时候,都会先调用 isRunning 方法,用以确认是否需要真的调用 start/stop 方法。@Configuration
@ComponentScan
public class JavaConfig {
}
最后我们启动容器:public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
ctx.start();
ctx.stop();
}
}
启动之后,我们就可以看到控制台打印出来的信息:
public interface SmartLifecycle extends Lifecycle, Phased {
int DEFAULT_PHASE = Integer.MAX_VALUE;
default boolean isAutoStartup() {
return true;
}
default void stop(Runnable callback) {
stop();
callback.run();
}
@Override
default int getPhase() {
return DEFAULT_PHASE;
}
}
大家看一下,这里首先多了一个 isAutoStartup 方法,这个方法就表示是否自动执行 startup 方法,这个方法返回 true,则 startup 方法会被自动触发,这个方法要是返回 false,则 startup 方法就不会被自动触发(那么效果就等同于 LifeCycle 了)。@Component
public class MyLifeCycle implements SmartLifecycle {
private volatile boolean running;
@Override
public void start() {
running = true;
System.out.println("start");
}
@Override
public void stop() {
running = false;
System.out.println("stop");
}
@Override
public boolean isRunning() {
return running;
}
@Override
public boolean isAutoStartup() {
return SmartLifecycle.super.isAutoStartup();
}
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
@Override
public int getPhase() {
return 0;
}
}
public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}
onRefresh:这个是在上下文刷新的时候被触发,例如在容器启动的时候这个方法被触发。@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
@Override
public void onClose() {
stopBeans();
this.running = false;
}
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new TreeMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle smartLifecycle && smartLifecycle.isAutoStartup())) {
int phase = getPhase(bean);
phases.computeIfAbsent(
phase,
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}
在这个方法中,首先调用 getLifecycleBeans 方法,这个方法的作用是去 Spring 容器中查找所有 Lifecycle 类型的 Bean,并把查找结果封装到一个 Map 集合中返回。接下来就去遍历这个 Map,遍历的时候由于 autoStartupOnly 变量传进来的时候是 true,取反之后就是 false 了,所以就会去判断这个 Bean 是否为 SmartLifecycle 类型,如果是该类型并且 isAutoStartup 方法返回 true,就表示要自动执行 start 方法。public void start() {
if (this.members.isEmpty()) {
return;
}
Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
for (String dependency : dependenciesForBean) {
doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() &&
(!autoStartupOnly || !(bean instanceof SmartLifecycle smartLifecycle) || smartLifecycle.isAutoStartup())) {
bean.start();
}
}
}
在 doStart 方法中,从集合中取出来 Lifecycle,然后查找一下该 Lifecycle 是否有依赖的 Bean,如果有,就继续递归调用 doStart 方法。否则,在 isRunning 返回 false(即该组件还没有运行),且 bean 不是 SmartLifecycle 类型(那就只能是 Lifecycle 类型)或者 bean 是 SmartLifecycle 类型且 isAutoStartup 方法为 true 的情况下,调用 bean 的 start 方法。private void stopBeans() {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
int shutdownPhase = getPhase(bean);
LifecycleGroup group = phases.get(shutdownPhase);
if (group == null) {
group = new LifecycleGroup(shutdownPhase, this.timeoutPerShutdownPhase, lifecycleBeans, false);
phases.put(shutdownPhase, group);
}
group.add(beanName, bean);
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
keys.sort(Collections.reverseOrder());
for (Integer key : keys) {
phases.get(key).stop();
}
}
}
这块的逻辑跟 start 差不多,就是排序的方案有一些差别。这里用了 HashMap,没有用 TreeMap,然后在具体调用的时候,再去给 key 排序的。这里调用到的也是 LifecycleGroup 的 stop 方法,我们来看下:public void stop() {
if (this.members.isEmpty()) {
return;
}
this.members.sort(Collections.reverseOrder());
CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>());
Set<String> lifecycleBeanNames = new HashSet<>(this.lifecycleBeans.keySet());
for (LifecycleGroupMember member : this.members) {
if (lifecycleBeanNames.contains(member.name)) {
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
}
else if (member.bean instanceof SmartLifecycle) {
// Already removed: must have been a dependent bean from another phase
latch.countDown();
}
}
try {
latch.await(this.timeout, TimeUnit.MILLISECONDS);
if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isInfoEnabled()) {
logger.info("Failed to shut down " + countDownBeanNames.size() + " bean" +
(countDownBeanNames.size() > 1 ? "s" : "") + " with phase value " +
this.phase + " within timeout of " + this.timeout + "ms: " + countDownBeanNames);
}
}
catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
大家看一下,这里的 doStop 方法,最终就会触发到 Lifecycle 的 stop,这个里边的代码简单,我们就不去细看了。需要提醒大家的时候,这里使用到了这样一个计数器,初始值就是 members 的数量,每当调用一个 member 的 stop 方法之后,这个计数器减一,这样,到下面调用 await 的时候,就刚刚好不用等。@Configuration
@ComponentScan
public class JavaConfig {
@Bean
DefaultLifecycleProcessor lifecycleProcessor() {
DefaultLifecycleProcessor processor = new DefaultLifecycleProcessor();
processor.setTimeoutPerShutdownPhase(2000);
return processor;
}
}
上面这个案例中设置了超时时间为 2s。好啦,这就是关于 Lifecycle 的整体触发流程。接下来我们来看下自动触发和手动触发分别是在哪里触发的。protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
}
这里有两个方法跟本文相关,一个是 initLifecycleProcessor,这个是初始化 LifecycleProcessor,就是去 Spring 容器中查找 LifecycleProcessor,找到就用,没找到就创建新的。然后就是 getLifecycleProcessor().onRefresh(); 方法,这个就是触发了 DefaultLifecycleProcessor#onRefresh 方法,而关于该方法的逻辑,我在前面已经介绍过了。protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
}
}
大家注意,LIFECYCLE_PROCESSOR_BEAN_NAME 常量的值是 lifecycleProcessor,为什么要强调这个,如果我们是自定义 DefaultLifecycleProcessor,那么 beanName 必须是 lifecycleProcessor,否则系统会以为我们没有自定义 DefaultLifecycleProcessor。@Override
public void start() {
getLifecycleProcessor().start();
publishEvent(new ContextStartedEvent(this));
}
相当于直接调用了 DefaultLifecycleProcessor 的 start 方法:@Override
public void start() {
startBeans(false);
this.running = true;
}
这个跟 DefaultLifecycleProcessor 的 onRefresh 方法内容基本一致,唯一的区别在于调用 startBeans 的时候,传入的参数为 false,这个参数带来的变化,这个我在前面的内容中已经分析过了,这里就不再啰嗦啦。