Spring中的Lifecycle| SmartLifecycle接口使用与源码分析

本文详细介绍了Spring框架中的LifeCycle接口和SmartLifecycle接口,包括它们的声明、使用场景以及调用时机。重点讲解了如何在Spring容器中实现自定义组件的生命周期管理,以及如何控制启动和停止的顺序。
摘要由CSDN通过智能技术生成

【转】 https://www.jb51.net/article/284113.htm

LifeCycle接口定义了Spring容器的生命周期,任何被Spring管理的对象都可以实现该接口。当Spring容器本身启动和停止时,会回调LifeCycle接口中定义的方法。

org.springframework.context.Lifecycle

Lifecycle接口的声明

public interface Lifecycle {
	    /**
     * 启动当前组件,如果组件已经在运行,不应该抛出异常,这样将开始信号传播到应用的所有组件中去。
     */
	void start();
	    /**
     * 通常以同步方式停止该组件,当该方法执行完成后,该组件会被完全停止。当需要异步停止行为时,考虑实现SmartLifecycle和它的 stop(Runnable) 方法变体。 
	 注意,此停止通知在销毁前不能保证到达:
    在常规关闭时,{@code Lifecycle} bean将首先收到一个停止通知,然后才传播常规销毁回调;
    在上下文的生命周期内的刷新或中止时,只调用销毁方法
    对于容器,这将把停止信号传播到应用的所有组件
     */
	void stop();
	    /**
      *  检查此组件是否正在运行。
      *  1. 只有该方法返回false时,start方法才会被执行。
      *  2. 只有该方法返回true时,stop(Runnable callback)或stop()方法才会被执行。
      */
	boolean isRunning();
}

Lifecycle的使用

package com.morris.spring.demo.lifecycle;
import org.springframework.context.Lifecycle;
/**
 * 自定义Lifecycle
 */
public class MyLifecycle implements Lifecycle {
	private boolean isRunning;
	@Override
	public void start() {
		System.out.println("MyLifecycle start");
		isRunning = true;
	}
	@Override
	public void stop() {
		System.out.println("MyLifecycle stop");
		isRunning = false;
	}
	@Override
	public boolean isRunning() {
		return isRunning;
	}
}

测试类1

public class LifecycleDemo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(MyLifecycle.class);
		applicationContext.refresh();
	}
}

启动main()方法后发现并没有调用MyLifecycle的start()和stop()方法。,

测试类2

public class LifecycleDemo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(MyLifecycle.class);
		applicationContext.refresh();
		applicationContext.start();
		applicationContext.stop();
	}
}

执行结果:

DEBUG main DefaultLifecycleProcessor:356 - Starting beans in phase 0
MyLifecycle start
DEBUG main DefaultLifecycleProcessor:188 - Successfully started bean 'myLifecycle'
DEBUG main DefaultLifecycleProcessor:369 - Stopping beans in phase 0
MyLifecycle stop
DEBUG main DefaultLifecycleProcessor:253 - Successfully stopped bean 'myLifecycle'

这时我们看到Spring容器回调了Lifecycle生命周期的方法。

org.springframework.context.SmartLifecycle

SmartLifecycle接口声明

public interface SmartLifecycle extends Lifecycle, Phased {
	int DEFAULT_PHASE = Integer.MAX_VALUE;
	/**
      * 如果该`Lifecycle`类所在的上下文在调用`refresh`时,希望能够自己自动进行回调,则返回`true`* ,
      * false的值表明组件打算通过显式的start()调用来启动,类似于普通的Lifecycle实现。
     */
	default boolean isAutoStartup() {
		return true;
	}
	default void stop(Runnable callback) {
		stop();
		callback.run();
	}
	@Override
	default int getPhase() {
		return DEFAULT_PHASE;
	}
}

SmartLifecycle的使用

package com.morris.spring.demo.lifecycle;
import org.springframework.context.SmartLifecycle;
/**
 * 自定义SmartLifecycle
 */
public class MySmartLifecycle implements SmartLifecycle {
	private boolean isRunning;
	@Override
	public void start() {
		System.out.println("MyLifecycle start");
		isRunning = true;
	}
	@Override
	public void stop() {
		System.out.println("MyLifecycle stop");
		isRunning = false;
	}
	@Override
	public boolean isRunning() {
		return isRunning;
	}
}

测试类1

package com.morris.spring.demo.lifecycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * 演示SmartLifecycle
 */
public class SmartLifecycleDemo {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(MySmartLifecycle.class);
		applicationContext.refresh();
	}
}

执行结果:

DEBUG main DefaultListableBeanFactory:228 - Creating shared instance of singleton bean 'mySmartLifecycle'
DEBUG main DefaultLifecycleProcessor:357 - Starting beans in phase 2147483647
MyLifecycle start
DEBUG main DefaultLifecycleProcessor:189 - Successfully started bean 'mySmartLifecycle'

容器中多个实现了Lifecycle的类如果希望有顺序的进行回调时,那么启动和关闭调用的顺序可能很重要。如果任何两个对象之间存在依赖关系,那么依赖方将在依赖后开始,在依赖前停止。然而,有时直接依赖关系是未知的。您可能只知道某个类型的对象应该在另一个类型的对象之前开始。
在这些情况下,SmartLifecycle接口定义了另一个选项,即在其超接口上定义的getPhase()方法。

当开始时,getPhase()返回值最小的对象先开始,当停止时,遵循相反的顺序。因此,

  • 实现SmartLifecycle的对象及其getPhase()方法返回Integer.MIN_VALUE将在第一个开始和最后一个停止
  • 相反,MAX_VALUE将指示对象应该在最后启动并首先停止

源码解读

Lifecycle的调用时机

Lifecycle中的方法只有在主动调用容器的start()和stop()方法时才会触发,所以直接看容器的start()或stop()方法即可。

org.springframework.context.support.AbstractApplicationContext#start
public void start() {
	// 获取DefaultLifecycleProcessor
	/**
		 * @see DefaultLifecycleProcessor#start()
		 */
	getLifecycleProcessor().start();
	publishEvent(new ContextStartedEvent(this));
}
org.springframework.context.support.DefaultLifecycleProcessor#start
public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactoryAware {

	public void start() {
		startBeans(false);// 1.autoStartupOnly==false
		this.running = true;
	}

	private void startBeans(boolean autoStartupOnly) {
	        Map<String, Lifecycle> lifecycleBeans = this.getLifecycleBeans();
	        Map<Integer, LifecycleGroup> phases = new TreeMap();
	        lifecycleBeans.forEach((beanName, bean) -> {
	            if (autoStartupOnly) { //autoStartupOnly == true,表示只处理 SmartLifecycle
	                if (!(bean instanceof SmartLifecycle)) {
	                    return;
	                }
	
	                SmartLifecycle smartLifecycle = (SmartLifecycle)bean;
	                if (!smartLifecycle.isAutoStartup()) {
	                    return;
	                }
	            }
	
	            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);
	        }
	
	    }
}

SmartLifecycle的调用时机

org.springframework.context.support.AbstractApplicationContext#finishRefresh
protected void finishRefresh() {
	// Clear context-level resource caches (such as ASM metadata from scanning).
	clearResourceCaches();
	// Initialize lifecycle processor for this context.
	// 1.注入DefaultLifecycleProcessor
	initLifecycleProcessor();
	// 2.执行LifecycleProcessor.onRefresh()方法
	getLifecycleProcessor().onRefresh();
	// Publish the final event.
	publishEvent(new ContextRefreshedEvent(this));
	// Participate in LiveBeansView MBean, if active.
	LiveBeansView.registerApplicationContext(this);
}
org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
	public void start() {
		startBeans(true);// 1.autoStartupOnly==true ,表示只处理SmartLifecycle,前文已有说明;
		this.running = true;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值