通过源码查看Spring SmartLifecycle 的执行顺序
Posted sqlven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过源码查看Spring SmartLifecycle 的执行顺序相关的知识,希望对你有一定的参考价值。
最新需要用到SmartLifecycle ,写了一个测试类,打印了一下执行顺序如下:
/** * * * @author cuiyt * @date: 2017年8月31日 上午8:47:54 */ public class TestSmartLifecycle implements SmartLifecycle { private boolean isRunning = false; @Override public void start() { System.out.println("test start-------------------------"); isRunning = true; } @Override public void stop() { System.out.println("test stop-------------------------"); isRunning = false; } @Override public boolean isRunning() { System.out.println("test isRunning-------------------------"); return isRunning; } @Override public int getPhase() { System.out.println("test getPhase-------------------------"); return 0; } @Override public boolean isAutoStartup() { System.out.println("test isAutoStartup-------------------------"); return true; } @Override public void stop(Runnable callback) { System.out.println("test callback-------------------------"); isRunning = false; } }
启动顺序
停止顺序
先来看启动顺序为什么执行了两次
test isAutoStartup-------------------------
test getPhase-------------------------
private void startBeans(boolean autoStartupOnly) { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();//获取Lifecycle实现类的bean Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>(); for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) { Lifecycle bean = entry.getValue();//判断是不是自动启动,这里调用了isAutoStartup if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) { int phase = getPhase(bean);//getPhase()方法内部调用了getPhase return (bean instanceof Phased ? ((Phased) bean).getPhase() : 0); LifecycleGroup group = phases.get(phase); if (group == null) {//如果相同启动顺序的不存在,则新new一个组,并将bean加入到这个组 group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly); phases.put(phase, group); } group.add(entry.getKey(), bean);//如果相同启动顺序的存在,则将bean加入到这个组
}
}
if (phases.size() > 0) {
List<Integer> keys = new ArrayList<Integer>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();//获取所有Lifecyccle并分完组后,则开始真正的执行
}
}
接下来看执行的顺序
test getPhase-------------------------
test isRunning-------------------------
test isAutoStartup-------------------------
test start-------------------------
public void start() { if (this.members.isEmpty()) { return; } if (logger.isInfoEnabled()) { logger.info("Starting beans in phase " + this.phase); } Collections.sort(this.members);//这里进行了排序,查看LifecycleGroupMember的源码(见下面代码),发现他实现了Comparable接口,compareTo方法里面再次调用了getPhase()
for (LifecycleGroupMember member : this.members) {
if (this.lifecycleBeans.containsKey(member.name)) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly); //调用doStart()
}
} }
/** * Adapts the Comparable interface onto the lifecycle phase model. */ private class LifecycleGroupMember implements Comparable<LifecycleGroupMember> { private final String name; private final Lifecycle bean; LifecycleGroupMember(String name, Lifecycle bean) { this.name = name; this.bean = bean; } @Override public int compareTo(LifecycleGroupMember other) { int thisOrder = getPhase(this.bean); int otherOrder = getPhase(other.bean); return (thisOrder == otherOrder ? 0 : (thisOrder < otherOrder) ? -1 : 1); } }
doStart()
/** * Start the specified bean as part of the given set of Lifecycle beans, * making sure that any beans that it depends on are started first. * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param beanName the name of the bean to start */ private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) { Lifecycle bean = lifecycleBeans.remove(beanName); if (bean != null && !this.equals(bean)) { String[] dependenciesForBean = this.beanFactory.getDependenciesForBean(beanName); for (String dependency : dependenciesForBean) { doStart(lifecycleBeans, dependency, autoStartupOnly); }
//这里判断是否在运行,调用了isRunning(),isAutoStartup()
if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
if (logger.isDebugEnabled()) {
logger.debug("Starting bean \'" + beanName + "\' of type [" + bean.getClass() + "]");
}
try {
bean.start(); //调用start()
} catch (Throwable ex) { throw new ApplicationContextException("Failed to start bean \'" + beanName + "\'", ex); } if (logger.isDebugEnabled()) { logger.debug("Successfully started bean \'" + beanName + "\'"); } } } }
停止顺序
test getPhase-------------------------
2017-08-31 09:06:57.581 INFO 11028 --- [on(2)-127.0.0.1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0
test getPhase-------------------------
test isRunning-------------------------
test callback-------------------------
同样是先获取实现bean,并分组,调用了两次getPhase()
private void stopBeans() { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>(); for (Map.Entry<String, Lifecycle> entry : lifecycleBeans.entrySet()) { Lifecycle bean = entry.getValue(); int shutdownOrder = getPhase(bean);//第一次getPhase() LifecycleGroup group = phases.get(shutdownOrder); if (group == null) { group = new LifecycleGroup(shutdownOrder, this.timeoutPerShutdownPhase, lifecycleBeans, false); phases.put(shutdownOrder, group); } group.add(entry.getKey(), bean); } if (phases.size() > 0) { List<Integer> keys = new ArrayList<Integer>(phases.keySet()); Collections.sort(keys, Collections.reverseOrder()); for (Integer key : keys) { phases.get(key).stop();//开始停止 } } }
stop方法
public void stop() { if (this.members.isEmpty()) { return; } if (logger.isInfoEnabled()) { logger.info("Stopping beans in phase " + this.phase); } Collections.sort(this.members, Collections.reverseOrder());//排序调用了一次getPhase()
CountDownLatch latch = new CountDownLatch(this.smartMemberCount);
Set<String> countDownBeanNames = Collections.synchronizedSet(new LinkedHashSet<String>());
for (LifecycleGroupMember member : this.members) {
if (this.lifecycleBeans.containsKey(member.name)) {
doStop(this.lifecycleBeans, member.name, latch, countDownBeanNames); //调用doStop方法
} else if (member.bean instanceof SmartLifecycle) {
// already removed, must have been a dependent latch.countDown(); } }
try { latch.await(this.timeout, TimeUnit.MILLISECONDS);
if (latch.getCount() > 0 && !countDownBeanNames.isEmpty() && logger.isWarnEnabled()) {
logger.warn("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()
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 = this.beanFactory.getDependentBeans(beanName); for (String dependentBean : dependentBeans) { doStop(lifecycleBeans, dependentBean, latch, countDownBeanNames); } try { if (bean.isRunning()) {//判断是都还在运行,调用了isRunning()
if (bean instanceof SmartLifecycle) { if (logger.isDebugEnabled()) { logger.debug("Asking bean \'" + beanName + "\' of type [" + bean.getClass() + "] to stop"); } countDownBeanNames.add(beanName); ((SmartLifecycle) bean).stop(new Runnable() {//调用了stop(Runnable callback)
@Override public void run() { latch.countDown(); countDownBeanNames.remove(beanName); if (logger.isDebugEnabled()) { logger.debug("Bean \'" + beanName + "\' completed its stop procedure"); } } }); } else { if (logger.isDebugEnabled()) { logger.debug("Stopping bean \'" + beanName + "\' of type [" + bean.getClass() + "]"); } 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); } } } }
以上是关于通过源码查看Spring SmartLifecycle 的执行顺序的主要内容,如果未能解决你的问题,请参考以下文章
spring源码转eclipse工程(查看spring源码)
MyEclipse中查看struts_spring_hibernate源码