Spring Cloud源码分析之Eureka篇第二章:注册中心启动类上的注解EnableEurekaServer

 2019-11-02 21:25  阅读(1411)
文章分类:Spring boot

本章是《Spring Cloud源码分析》系列文章的第二篇,我们从注册中心Eureka开始这段历程;

原文地址:https://blog.csdn.net/boling_cavalry/article/details/81809860

Spring Cloud源码下载

今天的源码分析主要是spring-cloud-netflix这个工程的源码,版本为1.4.0.RELEASE,请参照第一篇《Spring Cloud源码分析之Eureka篇第一章:准备工作》中的方法在GiuHub下载;

启动类上的注解

第一篇《Spring Cloud源码分析之Eureka篇第一章:准备工作》中,创建的注册中心应用springclouddeepeureka的启动类SpringclouddeepeurekaApplication.java的源码如下:

package com.bolingcavalry.springclouddeepeureka;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

    @SpringBootApplication
    @EnableEurekaServer
    public class SpringclouddeepeurekaApplication {

        public static void main(String[] args) {
            SpringApplication.run(SpringclouddeepeurekaApplication.class, args);
        }
    }

上面这段代码与一般的SpringBoot启动类不同之处在于多了个注解@EnableEurekaServer,今天的源码分析都是围绕这个类开展的;

  1. 看看此注解的源码:

    /** * Annotation to activate Eureka Server related configuration {@link EurekaServerAutoConfiguration} * * @author Dave Syer * @author Biju Kunjummen * */

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(EurekaServerMarkerConfiguration.class)
    public @interface EnableEurekaServer {
    
    }
    

上述代码中,注解@Import(EurekaServerMarkerConfiguration.class)表示,EurekaServerMarkerConfiguration这个类也会被作为bean做实例化;
另外请注意注释中的内容:注解EnableEurekaServer 用来激活Eureka Server相关的配置:EurekaServerAutoConfiguration,记下这是EurekaServerAutoConfiguration第一次出现在我们面前;

  1. 接下来去看被实例化了的EurekaServerMarkerConfiguration的源码:

    /** * Responsible for adding in a marker bean to activate * {@link EurekaServerAutoConfiguration} * * @author Biju Kunjummen */ @Configuration public class EurekaServerMarkerConfiguration {

        @Bean
        public Marker eurekaServerMarkerBean() {
            return new Marker();
        }
    
        class Marker {
        }
    }
    

如上所示,简单到只有个一内部类EurekaServerMarkerConfiguration.Marker,我的猜测是:有的bean会通过注解ConditionalOnBean作为自己是否实例化的条件,而条件对应的bean就是EurekaServerMarkerConfiguration.Marker;

请注意注释中的内容:注解EurekaServerMarkerConfiguration 用来响应激活EurekaServerAutoConfiguration,这是EurekaServerAutoConfiguration第二次出现在我们面前;

  1. 根据前面两次注释的提示,EurekaServerAutoConfiguration类是必须要看了,打开这个类,先看注解:

    @Configuration @Import(EurekaServerInitializerConfiguration.class) @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class) @EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class }) @PropertySource("classpath:/eureka/server.properties")

符合之前的猜测,通过@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)注解,保证了EurekaServerAutoConfiguration类会被实例化后注册到spring容器中,也就是说这里面的配置都生效了;

  1. 接下来就是spring容器对bean进行实例化和初始化了,重点需要关注的是EurekaServerInitializerConfiguration、EurekaServerContext、EurekaServerBootstrap这三个类;

  2. EurekaServerAutoConfiguration中的@Bean注解会实例化EurekaServerContext、EurekaServerBootstrap,这两个实例已经不是SpringCloud工程的内容了,它们都来自com.netflix.eureka,它们接手了真正的EurekaServer的启动逻辑:

    @Bean public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs, PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) { return new DefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs, registry, peerEurekaNodes, this.applicationInfoManager); }

    @Bean
    public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
            EurekaServerContext serverContext) {
        return new EurekaServerBootstrap(this.applicationInfoManager,
                this.eurekaClientConfig, this.eurekaServerConfig, registry,
                serverContext);
    }
    
  3. EurekaServerInitializerConfiguration这个类出现在EurekaServerAutoConfiguration的注解中,通过@Import注解被实例化,由于实现了Lifecycle接口,因此会被spring容器回调start方法:

    @Override public void start() { new Thread(new Runnable() { @Override public void run() { try { //TODO: is this class even needed now? eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext); log.info("Started Eureka Server");

                    //发送广播,将EurekaServer的配置信息广播给全部订阅了该类型消息的监听
                    publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
                    EurekaServerInitializerConfiguration.this.running = true;
                    //发送广播,将EurekaServer的配置信息广播给全部订阅了该类型消息的监听
                    publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
                }
                catch (Exception ex) {
                    // Help!
                    log.error("Could not initialize Eureka servlet context", ex);
                }
            }
        }).start();
    }
    

如上所示,EurekaServerInitializerConfiguration初始化的时候,除了主动调用bootstrap的初始化方法,还通过广播将eureka的配置信息发出去;

eureka的配置信息EurekaServerConfig来自何处呢?EurekaServerAutoConfiguration的内部类EurekaServerConfigBeanConfiguration 负责生成这些配置信息,实例类型为EurekaServerConfigBean:

@Configuration
    protected static class EurekaServerConfigBeanConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
            EurekaServerConfigBean server = new EurekaServerConfigBean();
            if (clientConfig.shouldRegisterWithEureka()) {
                // Set a sensible default if we are supposed to replicate
                server.setRegistrySyncRetries(5);
            }
            return server;
        }
    }

至此,我们对EnableEurekaServer注解有了更深入的了解,虽然创建注册中心所需代码很少,但是背后隐藏着复杂的初始化服务,感谢大师们杰出的设计,封装了复杂逻辑,让业务测可以轻量级完成这些操作;


来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Spring Cloud源码分析之Eureka篇第二章:注册中心启动类上的注解EnableEurekaServer

相关推荐