Spring官方文档重点摘录系列三:lifeCycle与SmartLifeCycle
public interface Lifecycle { void start();
void stop();
boolean isRunning();
}
LifecycleProcessor
Spring容器是通过LifecycleProcessor代理方式实现这个功能。而LifecycleProcessor本身也是实现了LifeCycle接口,并且提供多两个方法:
public interface LifecycleProcessor extends Lifecycle { void onRefresh();
void onClose();
}
Spring官方文档中比较重点的两段描述:
Note that the regular org.springframework.context.Lifecycle interface is a plain contract for explicit start and stop notifications and does not imply auto-startup at context refresh time. For fine-grained control over auto-startup of a specific bean (including startup phases), consider implementing org.springframework.context.SmartLifecycle instead.
Also, please note that stop notifications are not guaranteed to come before destruction. On regular shutdown, all Lifecycle beans first receive a stop notification before the general destruction callbacks are being propagated. However, on hot refresh during a context’s lifetime or on aborted refresh attempts, only destroy methods are called.
总结为LifeCycle只会感知容器开始和启动生命周期,在自动startUp(后续章节提到的onRefresh)的容器刷新时期时不会被调用的。 同时stop通知也不一定保证会触发的,具体原因上面有描述。
SmartLifeCycle
SmartLifeCycle 在LifeCycle的基础上增加了对容器上下文的刷新感知能力。同时继承了Phase接口提供了Bean 创建和销毁一定的干预能力。SmartLifeCycle定义如下:
public interface SmartLifecycle extends Lifecycle, Phased { boolean isAutoStartup();
void stop(Runnable callback);
}
Bean创建和销毁的顺序
之前提到可以通过depends-on来确定两个bean之间的依赖顺序,从而控制通过depends-on连接性bean之间的创建以及销毁顺序。然而很多时候,你可能只想着有写Bean需要先创建,某些bean需要最后销毁。这个时候,可以通过实现SmartLifeCycle,通过getPhases方法来控制bean创建和销毁顺序。
对于没有实现SmartLifeCycle接口的bean,可以看为默认Phase是0。也就是说如果getPhase方法返回值小于0,那么就会优先被创建。与depends-on一样,优先被创建的bean会晚被销毁。
需要注意的是,depens-on的优先级可以认为是最高的。查看源码实现时会发现,当startor stop的时候,会优先检查depends-on关系。
关于Stop与Timeout
SmartLifeCycle的stop方法传入了一个Runnable方法,实现方是必须要调用runnable的run方法。其实查看lifecycleProcessor的默认实现DefaultLifecycleProcessor就可以知道其原因。
DefaultLifecycleProcessor中通过不同的phase进行分组排序,对于每个分组会创建一个CountdownLatch。传入的callback中会对countdownLatch进行countdown操作。
这样做是为了这个操作可能会采用多线程执行,需要通过countdownLatch进行并发控制,同时提供了timeout参数控制每个group的启动以及销毁超时。
目前默认实现中都是没有使用到线程池,可能是为了日后的扩展?
onRefresh与isAutoStartup
SmartLifeCycle的isAutoStartup方法用于表明bean是否希望接受onRefresh回调。如果返回true的话,那么在容器refresh的时候,就会触发这个回调方法。Spring文档中提到,不是每一个context都一定会实现start方法进行调用。获取refresh回调的时候就可以提前感知而不需要等待start事件的触发。
When the context is refreshed (after all objects have been instantiated and initialized), that callback is invoked. At that point, the default lifecycle processor checks the boolean value returned by each SmartLifecycle object’s isAutoStartup() method. If true, that object is started at that point rather than waiting for an explicit invocation of the context’s or its own start() method (unlike the context refresh, the context start does not happen automatically for a standard context implementation). The phase value and any “depends-on” relationships determine the startup order as described earlier.
我们通过源码来分析一下这个过程。Spring的ApplicationContext 构造函数中调用onRefresh方法进行容器的初始化,如下:
@Overridepublic void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset "active" flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring"s core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
可以看到,在容器的onRefresh(context的入口)方法中,在完成了bean的加载,解析,factory的初始化,BeanFactoryPostProcessor,BeanPostProcessor,listner的注册,以及初始化(依赖注入,bean的初始化完成)之后,调用finishRefresh方法。finishRefresh代码逻辑如下:
protected void finishRefresh() { // Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first. --- 调用LifeCycle的onRefresh方法
getLifecycleProcessor().onRefresh();
// Publish the final event. ---- 发送事件广播
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
先执行LifeCycleProcessor的初始化,注册到容器中,然后执行LifeCycleProcessor的onRefresh方法。注意,这里其实还没有调用start方法的。所以说onRefresh是先于start的。
- 容器实现了lifeCycle接口
我们可以发现ConfigurableApplicationContext也实现了lifeCycle接口(但此时调用LifeCycleProcessor获取lifeCycle的接口Bean时,是没有ConfigurableApplicationContext实现类的),context的start方法就是通过这个接口获得的。并且context的start方法是需要创建context的调用方手动调用的,所以也就是说context的start并不会调用。而LifeCycleProcessor的start就是在context 的start中触发的。这个也就是上面官方文档里面说到的,start对于context并不一定会实现以及进行调用。
这个是需要十分关注的点。就是对于容器context来说,onRefresh是创建context实例的构造函数就会调用的。而start需要通过实现了lifeCycle接口的context才会具有这个能力,并且还需要client主动调用start方法,lifeCycle的start方法才会被调用。
- SmartLifeCycle与事件监听机制
通过实现ApplicationListener接口,可以获取容器的生命周期事件通知。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
与事件监听的方式感知容器事件的方式相比,实现SmartLifeCycle接口可以获取整个生命周期的能力,包括启动和关闭等各个方法的回调。事件监听的广播可以看到其实和lifeCycle的调用是前后调用的。事件监听一样可以获取容器的各个阶段的事件,但是需要判断事件的类型处理不同的事件逻辑。
ps:
- refresh可能会由于在多个factory context(比如web)的时候,lifeCycle以及事件会接收多次。
- 对于SmartLifeCycle,在LifeCycle的基础上,增加了refresh以及isAutoRefresh方法。如果isAutoRefresh方法返回true的话,那么在LifeCycleProcessor的onRefresh就会被调用到。
以上是 Spring官方文档重点摘录系列三:lifeCycle与SmartLifeCycle 的全部内容, 来源链接: utcz.com/z/513130.html