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

举报
程序员欣宸 发表于 2022/07/05 12:55:01 2022/07/05
【摘要】 主要注解EnableEurekaServer的详细分析

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

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

Spring Cloud源码下载

启动类上的注解

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,今天的源码分析都是围绕这个类开展的;

  • 看看此注解的源码:

/**
 * 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第一次出现在我们面前;

  • 接下来去看被实例化了的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第二次出现在我们面前;

  • 根据前面两次注释的提示,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容器中,也就是说这里面的配置都生效了;
  • 接下来就是spring容器对bean进行实例化和初始化了,重点需要关注的是EurekaServerInitializerConfiguration、EurekaServerContext、EurekaServerBootstrap这三个类;
  • 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);
}
  • 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注解有了更深入的了解,虽然创建注册中心所需代码很少,但是背后隐藏着复杂的初始化服务,感谢大师们杰出的设计,封装了复杂逻辑,让业务测可以轻量级完成这些操作;

欢迎关注华为云博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴…

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。