在服务的启动类上添加@EnableEurekaServer 注解后,这个服务就是一个注册中心。下面分析下为何加了@EnableEurekaServer 注解后为何就成为了服务的注册中心。

    1. @SpringBootApplication
    2. @EnableEurekaServer
    3. public class EurekaApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(EurekaApplication.class, args);
    6. }
    7. }

    下面分析下@EnableEurekaServer 注解

    1. @Target(ElementType.TYPE)
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @Documented
    4. @Import(EurekaServerMarkerConfiguration.class)
    5. public @interface EnableEurekaServer {
    6. }
    7. @Configuration
    8. public class EurekaServerMarkerConfiguration {
    9. @Bean
    10. public Marker eurekaServerMarkerBean() {
    11. return new Marker();
    12. }
    13. class Marker {
    14. }
    15. }

    看上面的代码可以得知通过@Import 注解将EurekaServerMarkerConfiguration这个类导入到spring容器中,

    然后EurekaServerMarkerConfiguration类中声明了Marker类的bean对象。这个bean对象下面会用到。

    当注册中心启动时,了解springboot自动装配我们知道,系统会加载META-INF/spring.factories下的配置

    1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    2. org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration

    根据spring.factories配置文件会加载EurekaServerAutoConfiguration这个类

    1. @Configuration
    2. @Import(EurekaServerInitializerConfiguration.class)
    3. // 有Marker的这个bean才会将EurekaServerAutoConfiguration注入到spring容器中
    4. @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
    5. @EnableConfigurationProperties({ EurekaDashboardProperties.class,
    6. InstanceRegistryProperties.class })
    7. @PropertySource("classpath:/eureka/server.properties")
    8. public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {

    通过代码可以得知,spring会判断是否存在Marker的bean对象,存在则将EurekaServerAutoConfiguration这个类注入到spring容器中。在EurekaServerAutoConfiguration类中我们并没有发现启动Eureka祥光的代码,下面我们看下EurekaServerInitializerConfiguration这个类

    1. @Configuration
    2. public class EurekaServerInitializerConfiguration
    3. implements ServletContextAware, SmartLifecycle, Ordered

    通过上面代码可以看出EurekaServerInitializerConfiguration也是一个配置类,同时它实现了ServletContextAware接口,可以在Servlet容器启动后得到ServletContext容器上下文;它还实现了SmartLifecycle,这样在spring 生命周期中会调用这个类相关的方法。比如在spring初始化时,会调用它start方法。

    1. @Override
    2. public void start() {
    3. new Thread(new Runnable() {
    4. @Override
    5. public void run() {
    6. try {
    7. //TODO: is this class even needed now?
    8. eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
    9. log.info("Started Eureka Server");
    10. publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
    11. EurekaServerInitializerConfiguration.this.running = true;
    12. publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
    13. }
    14. catch (Exception ex) {
    15. // Help!
    16. log.error("Could not initialize Eureka servlet context", ex);
    17. }
    18. }
    19. }).start();
    20. }

    start方法中启动了一个后台线程,它会执行这一行代码。

    1. eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
    1. public void contextInitialized(ServletContext context) {
    2. try {
    3. initEurekaEnvironment();// 初始化eureka环境
    4. initEurekaServerContext();// 初始化eureka上下文
    5. context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
    6. }
    7. catch (Throwable e) {
    8. log.error("Cannot bootstrap eureka server :", e);
    9. throw new RuntimeException("Cannot bootstrap eureka server :", e);
    10. }
    11. }

    上面的代码会调用initEurekaEnvironment方法初始化eureka环境,调用initEurekaServerContext方法初始化eureka上下文, 至此Eureka Server就随着Spring容器的一起启起了。