本文来分析下spring中如何执行与生命周期相关lifecycle的start和stop方法
下面为getLifecycleProcessor().onRefresh(),在完成刷新spring工厂的finishRefresh方法中执行的
private void startBeans(boolean autoStartupOnly) {
Map lifecycleBeans = getLifecycleBeans();
Map phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
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 keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
首先,会获取程序中配置的所有lifecycle的bean实例,并以map的形式返回,key为beanName,value为bean实例,这里不管bean是否为lazy的,也都会初始化并返回。
根据lifecycle的phase值(getPhase方法的返回值),将phase值相同的封装成一个LifecycleGroup对象,该对象的members成员列表维护着这些lifecycle对象。并且,最终再根据phase和LifecycleGroup放入到map中
对map的key列表进行排序,然后依次执行对应LifecycleGroup对象的start方法
public void start() {
if (this.members.isEmpty()) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Starting beans in phase " + this.phase);
}
Collections.sort(this.members);
for (LifecycleGroupMember member : this.members) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
start方法就是循环每个members成员,并将member的名称与所有的lifecycleBeans列表作为参数,调用doStart方法。
private void doStart(Map 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) bean).isAutoStartup())) {
try {
bean.start();
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
}
}
}
}
lifecycleBeans.remove(beanName),为了防止bean的start方法重复执行,这边执行完就将bean从map中移除,并且还会判断bean != this,因此当前DefaultLifecycleProcessor也实现了lifecycle接口,可能也会在map中,所以多加了这个判断。
接下去会获取bean所依赖的其他bean对象,然后进行递归调用doStart方法,这里是为了确保bean所依赖的其他bean对象(实现了lifecycle接口,如果没实现此接口,那么从map中remove出来的对象一定为null)的start方法优先被执行。
注意,在执行start方法前,还会判断一些其他条件。
private void stopBeans() {
Map lifecycleBeans = getLifecycleBeans();
Map 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 keys = new ArrayList<>(phases.keySet());
keys.sort(Collections.reverseOrder());
for (Integer key : keys) {
phases.get(key).stop();
}
}
}
stopBeans方法也是先对lifecycleBean进行分组放入map中,之后有一个比较大的区别是对map的key进行排序的方式和startBeans方法相反的,也就是说,同一个bean的start方法如果最先被执行,那么stop方法将最后被执行。
defaultLifecycleProcessor的stop方法和start方法也区别较大
public void stop() {
if (this.members.isEmpty()) {
return;
}
this.members.sort(Collections.reverseOrder());
CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
Set countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<>());
Set 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();
}
}
首先会生成一个CountDownLatch对象,每执行完一个lifecycle的stop方法,便会对latch减1
而doStop方法与doStart方法的逻辑也是大体相同的,先根据beanName从map中移除,取出bean,然后优先执行其依赖的bean的stop方法。没执行完stop方法后,对latch进行减1