源码剖析 启动Eureka Server(一)@EnableEurekaServer注解

Spring Cloud Netflix Eureka项目将Netflix公司的Eureka项目加以封装,以适配Spring Boot自动化配置的机制,通过注解在Spring Boot项目启动时启动Eureka Server。
我们通过阅读相关源码,看看这一过程是如何实现的。


回顾我们的eureka-demo中的eureka-server项目,在我们的项目启动类Server上有一个@EnableEurekaServer注解。

@SpringBootApplication
@EnableEurekaServer
public class Server {
    //...
}

查看这个注解的定义

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

可以看到它Import导入了EurekaServerMarkerConfiguration类

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

这个EurekaServerMarkerConfiguration会往Spring容器中注入一个eurekaServerMarkerBean,这个Marker是一个空类,那在这里起到什么作用呢?
仔细查看这个类的注释,可以看到它只是一个开关标记,用来激活EurekaServerAutoConfiguration类的。

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

查看EurekaServerAutoConfiguration类的定义

@Configuration
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
        InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter
  • @Configuration注解表示这是一个配置类,通过@Bean注解声明一些注入到Spring IOC容器中的Bean。
  • @ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class),表示只要Spring容器中有EurekaServerMarkerConfiguration.Marker.class类的实例存在,那么就会将这个EurekaServerAutoConfiguration也注入到Spring容器中。
  • @Import(EurekaServerInitializerConfiguration.class)表明它导入了EurekaServerInitializerConfiguration这个类。
  • 此外,这个EurekaServerAutoConfiguration继承自WebMvcConfigurer,可以用来定义Spring MVC的一些配置。

在这个类中,我们并没有发现与启动Eureka相关的代码,那么我们来看看它引入的这个EurekaServerInitializerConfiguration。

@Configuration
public class EurekaServerInitializerConfiguration
        implements ServletContextAware, SmartLifecycle, Ordered {

可以看到,这也是一个配置类,同时它实现了ServletContextAware接口,可以在Servlet容器启动后得到ServletContext容器上下文;它还实现了SmartLifecycle,这样在spring 生命周期中会调用这个类相关的方法。比如在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");
                    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方法中启动了一个后台线程,它会执行这一行代码。

eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);

eurekaServerBootstrap是EurekaServerInitializerConfiguration类的成员变量,对应的类是EurekaServerBootstrap。
来看看这个类的contextInitialized方法

public void contextInitialized(ServletContext context) {
        try {
            initEurekaEnvironment();//初始化Eureka运行环境
            initEurekaServerContext();//初始化Eureka运行上下文
            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);
        }
    }

这个方法调用了initEurekaEnvironment(),初始化Eureka运行环境;调用了initEurekaServerContext(),初始化Eureka运行上下文。关于这两个方法的细节,我们在后面的文章再细说。

至此Eureka Server就随着Spring容器的一起启起了。


相关流程图如下:

Eureka源码剖析(一)注解方式启动Eureka Server.png

你可能感兴趣的:(源码剖析 启动Eureka Server(一)@EnableEurekaServer注解)