在上篇中已經(jīng)說過了 Eureka-Server 本質上是一個 web 應用的項目,今天就來看看 Spring Boot 是怎么啟動 Eureka 的。
Spring Boot 啟動 Eureka 流程
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
}
上面的代碼是最最平常的 Spring Boot 啟動類。Spring Boot 啟動 eureka 的關鍵注解就在 @EnableEurekaServer 上面。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({EurekaServerMarkerConfiguration.class})
public @interface EnableEurekaServer {
}
可以看到這注解導入了一個 EurekaServerMarkerConfiguration 類。
@Configuration
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
}
class Marker {
}
}
EurekaServerMarkerConfiguration 向 Spring 容器注入了一個 EurekaServerMarkerConfiguration.Marker 對象。Maker 是一個空對象,是一個標記開關的類。具體開關的類在上面的注釋中。
/**
* Responsible for adding in a marker bean to activate
* {@link EurekaServerAutoConfiguration}
*
* @author Biju Kunjummen
*/
EurekaServerMarkerConfiguration.Marker 對象用于激活 EurekaServerAutoConfiguration 類。
那 EurekaServerAutoConfiguration 類是在什么時候加載的呢?
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
如上圖,EurekaServerAutoConfiguration 啟動的調用是在 spring.factories 中的,在 Spring Boot 的啟動過程中,會加載所有的 spring.factories。這個時候會讀取并加載里面的內容到 Spring 中。
- @Import(EurekaServerInitializerConfiguration.class):初始化 EurekaServerAutoConfiguration 的時候會導入 EurekaServerInitializerConfiguration 類。
- @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class):當 Spring 中有 EurekaServerMarkerConfiguration.Marker 類的實例存在就把 EurekaServerAutoConfiguration 也導入到 Spring 的容器中。
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered
- ServletContextAware:實現(xiàn)這個類可以獲取到 ServletContext 容器上下文。
- SmartLifecycle:當 Spring 容器加載所有 bean 并完成初始化之后,會接著回調實現(xiàn)該接口的類中對應的 start() 方法
看一下 start() 方法里面調用了什么?
@Override
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try {
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
log.info("Started Eureka Server");
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
EurekaServerInitializerConfiguration.this.running = true;
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
}
catch (Exception ex) {
// Help!
log.error("Could not initialize Eureka servlet context", ex);
}
}
}).start();
}
start() 啟動了一個線程,在線程里面 Start 了 Eureka Server。eurekaServerBootstrap 是一個自動注入 EurekaServerBootstrap 的對象。EurekaServerBootstrap 在上一篇中已經(jīng)說過了,它是 Eureka Server 的啟動類。最后看看它的 contextInitialized() 方法。
public void contextInitialized(ServletContext context) {
try {
initEurekaEnvironment();
initEurekaServerContext();
context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
}
catch (Throwable e) {
log.error("Cannot bootstrap eureka server :", e);
throw new RuntimeException("Cannot bootstrap eureka server :", e);
}
}
contextInitialized 方法調用了 initEurekaEnvironment(),初始化 Eureka 的運行環(huán)境;initEurekaServerContext(),初始化 Eureka 的上下文。
總結
Spring Boot 啟動 Erueka Server 經(jīng)歷了一下步驟:
- @EnableEurekaServer 注解
- 注入了 EurekaServerMarkerConfiguration.Marker 對象
- 判斷容器里是否有 EurekaServerMarkerConfiguration.Marker 對象注入了 EurekaServerAutoConfiguration
- 導入了實現(xiàn) SmartLifecycle 接口的 EurekaServerInitializerConfiguration 類
- Spring 容器在初始化后調用了 EurekaServerInitializerConfiguration 對象的 start() 方法
- start() 中啟動了一個線程,調用了 Erueka Server 的啟動類:EurekaServerBootstrap。
-
Web
+關注
關注
2文章
1266瀏覽量
69564 -
容器
+關注
關注
0文章
498瀏覽量
22086 -
eureka
+關注
關注
0文章
4瀏覽量
1774 -
SpringBoot
+關注
關注
0文章
174瀏覽量
187
發(fā)布評論請先 登錄
相關推薦
評論