上一篇文章讲解了SpringBoot在启动时何时选择的容器类型以及相关的配置是何时加载的,接下来再来简单的说说内置Netty容器是何时启动的。希望大家可以根据我上一篇接着看 SpringBoot-内置Netty启动(一)
再谈 AbstractApplicationContext#refresh()
在上一篇中我们了解到当SpringApplication#run();
方法中 调用refreshContext(context);
方法来刷新SpringBoot应用上下文,我们接着再来看看这段代码。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//...省略代码
try {
//...省略代码
//调用onRefresh()方法进行WebServer的实例生成
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//完成上下文的刷新
finishRefresh();
}
//...省略代码
}
我们主要看一下finishRefresh();
@SuppressWarnings("deprecation")
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// 初始化应用上下文的生命周期
initLifecycleProcessor();
// 首先刷新生命周期的处理器
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
if (!IN_NATIVE_IMAGE) {
LiveBeansView.registerApplicationContext(this);
}
}
我们主要关注两个方法 initLifecycleProcessor();
和 getLifecycleProcessor().onRefresh();
我们先来看一下 initLifecycleProcessor()
protected void initLifecycleProcessor() {
//获得BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//从BeanFactory中查看是否有 Bean名称为 lifecycleProcessor 的实例
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
//如果有将lifecycleProcessor 赋值给当前变量 其实这里的Bean就是 DefaultLifecycleProcessor
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
//如果没有将创建 DefaultLifecycleProcessor 赋值给当前变量
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
当获取到了 DefaultLifecycleProcessor的Bean实例后,在调用getLifecycleProcessor().onRefresh();
方法进行所有生命周期处理器的刷新操作,我们直接来看一下DefaultLifecycleProcessor#onRefresh()
方法
/**
* 启动所有实现了Lifecycle并且没有实例化的Bean
* 同时所有实现SmartLifecycle接口的实现类再其从低到高的阶段内开始启动
**/
@Override
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
//从BeanFactory中获取所有Lifecycle实现类的Bean集合
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new TreeMap<>();
//简单的判断和阶段分组
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
phases.computeIfAbsent(
phase,
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
//分阶段开始启动生命周期处理器
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}
/**
* 获取所有继承以及实现Lifecycle的接口下的已经创建的所有单例集合(包括SmartLifecycle)
**/
protected Map<String, Lifecycle> getLifecycleBeans() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
Map<String, Lifecycle> beans = new LinkedHashMap<>();
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
if ((beanFactory.containsSingleton(beanNameToRegister) &&
(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
return beans;
}
在上面代码一系列的处理之后,我们主要关注这段代码即可。
//分阶段开始启动生命周期处理器
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
// 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);
}
}
private void doStart(Map<String, ? extends Lifecycle> 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())) {
if (logger.isTraceEnabled()) {
logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
}
try {
//调用start()启动生命周期处理器,这里包括 WebServerStartStopLifecycle
bean.start();
}
catch (Throwable ex) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
}
if (logger.isDebugEnabled()) {
logger.debug("Successfully started bean '" + beanName + "'");
}
}
}
}
上面代码一系列的操作也是为了针对每一个实现Lifecyle
接口的实例调用start(),来实现所有生命周期管理器的启动。
代码注释中我标注了 WebServerStartStopLifecycle
这个类,为什么特别标注出这个类,因为他就是我们启动Netty内置容器的关键类。但是大家会好奇这个类是何时注入到BeanFactory中的呢,我们来回顾一下上一篇中有一段代码 -- ReactiveWebServerApplicationContext#createWebServer()
private void createWebServer() {
WebServerManager serverManager = this.serverManager;
if (serverManager == null) {
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
String webServerFactoryBeanName = getWebServerFactoryBeanName();
ReactiveWebServerFactory webServerFactory = getWebServerFactory(webServerFactoryBeanName);
createWebServer.tag("factory", webServerFactory.getClass().toString());
boolean lazyInit = getBeanFactory().getBeanDefinition(webServerFactoryBeanName).isLazyInit();
this.serverManager = new WebServerManager(this, webServerFactory, this::getHttpHandler, lazyInit);
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.serverManager));
//获取BeanFatory同时 注入 WebServerStartStopLifecycle
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this.serverManager));
createWebServer.end();
}
initPropertySources();
}
通过上面注释那段方法,我们可以看到 我们将配置好的 WebServerManager作为 WebServerStartStopLifecycle的构造函数参数传入到其中,那么我们具体来看一下WebServerStartStopLifecycle如何处理 WebServerManager的呢。
class WebServerStartStopLifecycle implements SmartLifecycle {
private final WebServerManager weServerManager;
private volatile boolean running;
WebServerStartStopLifecycle(WebServerManager weServerManager) {
this.weServerManager = weServerManager;
}
//调用weServerManager的start()方法来启动Netty容器
@Override
public void start() {
this.weServerManager.start();
this.running = true;
}
@Override
public void stop() {
this.running = false;
this.weServerManager.stop();
}
@Override
public boolean isRunning() {
return this.running;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE - 1;
}
}
虽然简单的几行代码,但是一眼就可以看出其中的玄机,首先它是SmartLifecycle 实现类,这也说明为什么 上一段代码中我们可以获取到这个bean并且调用它的start()的方法,然后我们看一下WeServerManager#start()
class WebServerManager {
//省略代码..
void start() {
this.handler.initializeHandler();
this.webServer.start();
this.applicationContext
.publishEvent(new ReactiveWebServerInitializedEvent(this.webServer, this.applicationContext));
}
//省略代码..
}
我们可以看到这里调用了 this.webServer.start();
同时我们通过上一篇文章我们也可以得到这个webServer就是 NettyWebServer
那么他的start()方法我直接贴出来 大家就可以明白了。
@Override
public void start() throws WebServerException {
if (this.disposableServer == null) {
try {
//启动netty内置容器
this.disposableServer = startHttpServer();
}
catch (Exception ex) {
PortInUseException.ifCausedBy(ex, ChannelBindException.class, (bindException) -> {
if (!isPermissionDenied(bindException.getCause())) {
throw new PortInUseException(bindException.localPort(), ex);
}
});
throw new WebServerException("Unable to start Netty", ex);
}
//这段就是我们熟悉的控制台输出
logger.info("Netty started on port(s): " + getPort());
startDaemonAwaitThread(this.disposableServer);
}
}
小结
到这里基本SpringBoot 如何选择容器类型并且何时启动容器的代码分析大体上简单的介绍完了,可能有些地方逻辑不够严谨或者表达不算清晰,但是大家跟着源码从头走一遍的话,相信就可以理解了。 其实Spring 其中的应用上下文以及各种处理器的初始化等等不是我们看几个月源码就可以理解的,如果我们带着需求去看,应该会记忆的更深,SpringBoot其他的启动逻辑我也没摸透,都需要慢慢的根据需求和目的去了解,这样才可以事倍功半。希望可以帮助到大家。
网友评论