前言
上文我們說到SpringBoot整合Nacos在服務啟動時候會往容器中註入
NacosAutoServiceRegistration對象,它是實現註冊的關鍵組件,下面我們重點分析一下它的源碼。
源碼分析
NacosAutoServiceRegistration的繼承關系圖如下所示:
![](https://news.xinpengboligang.com/upload/keji/2f19589bf7075b5ca20cec063cf0a1d3.jpeg)
NacosAutoServiceRegistration繼承關系圖
由類圖可以看出它繼承了
AbstractAutoServiceRegistration類,而
AbstractAutoServiceRegistration又實現了ApplicationListener接口,可以看出它是一個監聽的類,它會監聽什麼事件那?讓我們看看它的onApplicationEvent的定義:
@Override
@SuppressWarnings("deprecation")
public void onApplicationEvent(WebServerInitializedEvent event) {
bind(event);
}
可以看出它監聽WebServerInitializedEvent事件,這個事件是在什麼時候發佈的那?
這個類是SpringBoot下面定義的類,來看看它的代碼:
package org.springframework.boot.web.context;
import org.springframework.boot.web.server.WebServer;
import org.springframework.context.ApplicationEvent;
@SuppressWarnings("serial")
public abstract class WebServerInitializedEvent extends ApplicationEvent {
protected WebServerInitializedEvent(WebServer webServer) {
super(webServer);
}
public WebServer getWebServer() {
return getSource();
}
public abstract WebServerApplicationContext getApplicationContext();
@Override
public WebServer getSource() {
return (WebServer) super.getSource();
}
}
給它的解釋是在容器刷新以後並且是WebServer準備好了以後會發佈這個事件。
在SpringBoot啟動階段最終會調用
AbstractApplicationContext的finishRefresh方法,在該方法內部會循環調用所有實現了SmartLifecycle接口的bean並調用它的start方法,其中有一個類實現了SmartLifecycle接口,它是
WebServerStartStopLifecycle,該類的start方法代碼如下:
@Override
public void start() {
this.webServer.start();
this.running = true;
this.applicationContext
.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
}
可以看出它發佈了一個
ServletWebServerInitializedEvent事件,該事件正好是WebServerInitializedEvent的子類,知道這一點就好辦了,那麼我們的
AbstractAutoServiceRegistration就會監聽到這個事件,調用bind方法,最終會調用到start方法,然後調用到register方法,該方法的代碼如下:
protected void register() {
this.serviceRegistry.register(getRegistration());
}
這個serviceRegistry的類型是ServiceRegistry,它的實現類是NacosServiceRegistry,就是我們第一篇文章說的,它已經註入到容器中了,getRegistration獲取到的對象是NacosRegistration,這個對象同樣也註入到容器中了,我們重點來看NacosServiceRegistry的register方法:
@Override
public void register(Registration registration) {
if (StringUtils.isEmpty(registration.getServiceId())) {
log.warn("No service to register for nacos client...");
return;
}
NamingService namingService = namingService();
String serviceId = registration.getServiceId();
String group = nacosDiscoveryProperties.getGroup();
Instance instance = getNacosInstanceFromRegistration(registration);
try {
namingService.registerInstance(serviceId, group, instance);
log.info("nacos registry, {} {} {}:{} register finished", group, serviceId,
instance.getIp(), instance.getPort());
}
catch (Exception e) {
if (nacosDiscoveryProperties.isFailFast()) {
log.error("nacos registry, {} register failed...{},", serviceId,
registration.toString(), e);
rethrowRuntimeException(e);
}
else {
log.warn("Failfast is false. {} register failed...{},", serviceId,
registration.toString(), e);
}
}
}
這段代碼邏輯是從NacosServiceManager中獲取NamingService,這個對象相當於是和服務器的一個長連接,把實例註冊到服務器端的,這塊的邏輯我在Nacos單服務的時候已經分析過了,感興趣的朋友可以移駕Nacos源碼分析(二)NacosNamingService初始化以及註冊過程。
到此為止這個註冊就算完成了,邏輯比較簡單,註冊的具體邏輯都在Nacos那塊,感興趣的朋友可以到我Nacos源碼合集專題那塊去看一下具體是怎麼註冊到服務器端的。
總結:
註冊流程可以分為以下幾個步驟:
1.SpringBoot完成容器的刷新以後發佈WebServerInitializedEvent事件。
2.NacosAutoServiceRegistration監聽這個事件處理註冊邏輯。
3.封裝配置文件中配置的信息為Instance對象,調用Nacos底層邏輯進行服務註冊。
下一節我將分析Nacos和Ribbon的源碼,還請大傢持續關註,好了,我是愛好編程的程序員老徐,如果喜歡我的文章請點贊關註,我們下期見。