Python 官方文档:入门教程 => 点击学习
目录前言Lifecycle自定义Lifecycle实现类测试SmartLifecycle自定义SmartLifecycle实现类多个实现类源码分析LifecycleProcessor
小杰在前面的文章讲过可以使用 @PostConstruct
、InitializingBean
、xml init
、 @PreDestroy
、DisposableBean
、xml destroy
来处理 Bean 的初始化和销毁,上述这些操作是属于 Bean 生命周期的。
那如果我想在容器本身的生命周期(比如容器启动、停止)上做一些工作怎么办呢?spring 提供了以下接口。
定义启动/停止生命周期方法的通用接口。
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
@Component
public class CustomizeLifecycle implements Lifecycle {
private volatile boolean running = false;
@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;
}
}
@ComponentScan(basePackages = {"com.Gongj.lifecycle"})
public class AppApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppApplication.class);
context.start();
context.stop();
}
}
结果:
isRunning ====> false
start ====>
isRunning ====> true
stop ====>
使用 Lifecycle
这种方式,需要显示的调用容器的 start
、stop
方法。 显得笨重,所以我们使用另外一种方式 :SmartLifecycle
。
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;
}
}
看到的源码定义,SmartLifecycle
除了继承Lifecycle
之外,还继承了 Phased
。并且新增了几个方法:
start()
;为 false,则需要显示调用 start()
。Phased
接口,当容器中有多个实现了 SmartLifecycle
的类,这个时候可以依据 getPhase
方法返回值来决定start
方法、 stop
方法的执行顺序。 start
方法执行顺序按照 getPhase
方法返回值从小到大执行,而 stop
方法则相反。比如: 启动时:1 比 3 先执行,-1 比 1 先执行,退出时:3 比 1 先退出,1 比 -1 先退出。@Component
public class CustomizeSmartLifecycle implements SmartLifecycle {
private volatile boolean running = false;
@Override
public void start() {
running = true;
System.out.println("CustomizeSmartLifecycle start()");
}
@Override
public void stop() {
System.out.println("CustomizeSmartLifecycle stop()");
running = false;
}
@Override
public boolean isRunning() {
System.out.println("CustomizeSmartLifecycle isRunning() ==== " + running);
return running;
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable callback) {
System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");
callback.run();
}
@Override
public int getPhase() {
return 1;
}
}
将代码进行启动,控制台打印如下内容:
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppApplication.class);
//context.start();
//context.stop();
}
结果:
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
发现并没有执行 stop
方法,这是因为容器问题。如果在Spring Boot
项目会自动执行的,小伙伴可以试一试。
在本例中,还是需要显示调用 stop
方法。
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppApplication.class);
//context.start();
context.stop();
}
结果:
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
发现执行了stop(Runnable callback)
,并没有执行 stop
方法。这是因为当前类是 SmartLifecycle
的子类,如果要执行 stop
方法,需要在stop(Runnable callback)
显示调用。
@Override
public void stop(Runnable callback) {
System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");
stop();
callback.run();
}
或者
@Override
public void stop(Runnable callback) {
SmartLifecycle.super.stop(callback);
}
启动结果如下:
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
CustomizeSmartLifecycle stop()
注意:在stop(Runnable callback)
方法中不要忘记调用 callback.run()
方法。否则DefaultLifecycleProcessor
会认为这个SmartLifecycle
没有stop
完成,程序会等待一定时间,默认30秒后才会自动结束。
@Override
public void stop(Runnable callback) {
System.out.println("CustomizeSmartLifecycle stop(Runnable callback)");
//stop();
//callback.run();
}
@Component
public class CustomizeSmartLifecycle2 implements SmartLifecycle {
private volatile boolean running = false;
@Override
public void start() {
running = true;
System.out.println("CustomizeSmartLifecycle2 start() =====>");
}
@Override
public void stop() {
System.out.println("CustomizeSmartLifecycle1 stop() =====>");
running = false;
}
@Override
public boolean isRunning() {
System.out.println("CustomizeSmartLifecycle2 isRunning() =====> " + running);
return running;
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable callback) {
System.out.println("CustomizeSmartLifecycle2 stop(Runnable callback) =====>");
callback.run();
}
@Override
public int getPhase() {
return -1;
}
}
getPhase
方法返回 -1。按照前面所说的结论,那就是 CustomizeSmartLifecycle2
的start
方法会先执行,然后 CustomizeSmartLifecycle2
的stop
方法最后执行。我们一起来看看执行结果吧!
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppApplication.class);
//context.start();
context.stop();
}
执行结果:
CustomizeSmartLifecycle2 isRunning() =====> false
CustomizeSmartLifecycle2 start() =====>
CustomizeSmartLifecycle isRunning() ==== false
CustomizeSmartLifecycle start()
CustomizeSmartLifecycle isRunning() ==== true
CustomizeSmartLifecycle stop(Runnable callback)
CustomizeSmartLifecycle2 isRunning() =====> true
CustomizeSmartLifecycle2 stop(Runnable callback) =====>
跟结论保持一致。
基本的使用就到此结束啦!我们来结合源码分析分析吧!
我们来到 finishRefresh
方法的 getLifecycleProcessor().onRefresh();
方法。
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.
// 默认调用 DefaultLifecycleProcessor 的 onRefresh 方法
// 找出 Lifecycle Bean 执行 start 方法,默认情况下是没有Lifecycle Bean的,需要自己定义
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布事件 ContextRefreshedEvent 是一个事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.reGISterApplicationContext(this);
}
getLifecycleProcessor()
方法获得容器中的 LifecycleProcessor
对象,默认就是 DefaultLifecycleProcessor
。
public interface LifecycleProcessor extends Lifecycle {
void onRefresh();
void onClose();
}
接口中就定义的两个方法。onRefresh
、onClose
。
我们先来看一下 onRefresh
方法的内部逻辑,分析它是如何自动调用 start
方法的。
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
// 获取所有的Lifecycle Bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
// 将Lifecycle Bean 按阶段分组,阶段通过实现 Phased 接口得到
Map<Integer, LifecycleGroup> phases = new HashMap<>();
// 遍历所有Lifecycle Bean 按阶段值进行分组
lifecycleBeans.forEach((beanName, bean) -> {
// 当autoStartupOnly=false,显示调用 start()方法进行启动,会触发全部的Lifecycle;
// 当autoStartupOnly=true,调用容器的 refresh 方法启动,只会触发isAutoStartup方法返回true的SmartLifecycle
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) {
// 调用 Lifecycle 的 start 方法
phases.get(key).start();
}
}
}
这里注意一下 autoStartupOnly
的值为 true
。
refresh
方法,由容器调用 onRefresh
方法自动启动,只会触发 isAutoStartup
方法返回 true
的SmartLifecycle
。而 isAutoStartup
属性,小杰在分析SmartLifecycle
的时候已经讲过。start()
方法进行启动,会触发全部的Lifecycle
@Override
public void start() {
getLifecycleProcessor().start();
publishEvent(new ContextStartedEvent(this));
}
//传入 false
@Override
public void start() {
startBeans(false);
this.running = true;
}
onClose
在我没有找到调用点,但是 onClose
内部会调用stopBeans()
方法。我们直接分析stopBeans
方法。
stopBeans
方法跟 startBeans
的逻辑大体差不多,然后调用 stop
方法。
@Override
public void onClose() {
stopBeans();
this.running = false;
}
private void stopBeans() {
// 获取所有的Lifecycle Bean
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
// 获得 phase 的值
int shutdownPhase = getPhase(bean);
LifecycleGroup group = phases.get(shutdownPhase);
// 按阶段值进行分组
if (group == null) {
// this.timeoutPerShutdownPhase 就是等待时间
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) {
//调用 stop 方法
phases.get(key).stop();
}
}
}
创建一个 CountDownLatch
对象,如果 count
不为 0 ,则线程进行等待,默认等待 30 s。
public void stop() {
if(this.members.isEmpty()) {
return;
}
if(logger.isDebugEnabled()) {
logger.debug("Stopping beans in phase " + this.phase);
}
this.members.sort(Collections.reverseOrder());
// 创建 CountDownLatch 对象 ,count 为 smartMemberCount
// smartMemberCount 为 SmartLifecycle Bean的个数
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 方法
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames);
} else if(member.bean instanceof SmartLifecycle) {
// Already removed: must have been a dependent bean from another phase
//将count值减1
latch.countDown();
}
}
try {
//调用 await() 方法的线程会被挂起,等待一定的时间后,如果 count值还没有为 0 才继续执行
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 + ": " + countDownBeanNames);
}
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
doStop
方法的逻辑很简单。区分是否是SmartLifecycle
类型,如果是执行stop(Runnable callback)
方法,反之执行 stop()
方法。
private void doStop(Map<String, ? extends Lifecycle> lifecycleBeans, final String beanName,
final CountDownLatch latch, final Set<String> countDownBeanNames) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null) {
String[] dependentBeans = getBeanFactory().getDependentBeans(beanName);
for (String dependentBean : dependentBeans) {
doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames);
}
try {
// 判断 isRunning 的值
if (bean.isRunning()) {
// 如果是 SmartLifecycle 类型,则执行 stop(Runnable callback) 方法
if (bean instanceof SmartLifecycle) {
if (logger.isTraceEnabled()) {
logger.trace("Asking bean '" + beanName + "' of type [" +
bean.getClass().getName() + "] to stop");
}
countDownBeanNames.add(beanName);
// 这里就是为什么要调用 callback.run() 的原因
// 传入的是一个 lambad 表达式,所以需要调用callback.run(),才会执行 lambad 体
// 在lambad 体才会执行 latch.countDown()
((SmartLifecycle) bean).stop(() -> {
//将count值减1
latch.countDown();
countDownBeanNames.remove(beanName);
if (logger.isDebugEnabled()) {
logger.debug("Bean '" + beanName + "' completed its stop procedure");
}
});
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Stopping bean '" + beanName + "' of type [" +
bean.getClass().getName() + "]");
}
// 否则执行 stop() 方法
bean.stop();
if (logger.isDebugEnabled()) {
logger.debug("Successfully stopped bean '" + beanName + "'");
}
}
}
else if (bean instanceof SmartLifecycle) {
// Don't wait for beans that aren't running...
latch.countDown();
}
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to stop bean '" + beanName + "'", ex);
}
}
}
}
关于Lifecycle
的使用与源码分析就到这啦!
到此这篇关于Spring Lifecycle的使用的文章就介绍到这了,更多相关Spring Lifecycle使用内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: Spring Lifecycle的使用小结
本文链接: https://lsjlt.com/news/148104.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0