20-第19课:Spring Cloud 源码解析
Spring Cloud 集成了很多第三方框架,把它的全部源码拿出来解析几本书都讲不完,也不太现实,本文带领读者分析其中一小部分源码(其余源码读者有兴趣可以继续跟进),包括 Eureka-Server、Config、Zuul 的 starter 部分,分析其启动原理。
如果我们开发出一套框架,要和 Spring Boot 集成,就需要放到它的 starter 里。因此我们分析启动原理,直接从每个框架的 starter 开始分析即可。
Eureka-Server 源码解析
我们知道,要实现注册与发现,需要在启动类加上 @EnableEurekaServer
注解,我们进入其源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}
注意看 @Import
注解,这个注解导入了 EurekaServerMarkerConfiguration 类,继续跟进这个类:
/**
* Responsible for adding in a marker bean to activate
* {@link EurekaServerAutoConfiguration}
*/
{@link EurekaServerAutoConfiguration}
@Configuration
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() { return new Marker(); }
class Marker {
}
}
通过上面的注释,我们继续查看 EurekaServerAutoConfiguration 类的源码:
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
}
这个类上有一个注解:@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
,这后面指定的类就是刚才那个类,而 @ConditionalOnBean
这个注解的作用是:仅仅在当前上下文中存在某个对象时,才会实例化一个 Bean。
因此,启动时就会实例化 EurekaServerAutoConfiguration 这个类。
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
这个注解就是定义了一些 Eureka 的配置项。
Config 源码解析
通过上面的方法,我们找到了 ConfigServerAutoConfiguration 类:
@Configuration
@ConditionalOnBean(ConfigServerConfiguration.Marker.class)
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,
ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class, TransportConfiguration.class })
public class ConfigServerAutoConfiguration {
}
可以发现这个类是空的,只是多了几个注解, @EnableConfigurationProperties(ConfigServerProperties.class)
表示开启 Config 配置属性。
最核心的注解是:@Import
,它将其他一些配置类导入这个类,其中, EnvironmentRepositoryConfiguration 为环境配置类,内置了以下几种环境配置。
Native
@Configuration(proxyBeanMethods = false) @Profile("native") class NativeRepositoryConfiguration { @Bean public NativeEnvironmentRepository nativeEnvironmentRepository( NativeEnvironmentRepositoryFactory factory, NativeEnvironmentProperties environmentProperties) { return factory.build(environmentProperties); } }
git
@Configuration(proxyBeanMethods = false) @Profile("git") class GitRepositoryConfiguration extends DefaultRepositoryConfiguration { }
subversion
@Configuration(proxyBeanMethods = false) @Profile("subversion") class SvnRepositoryConfiguration { @Bean public SvnKitEnvironmentRepository svnKitEnvironmentRepository( SvnEnvironmentRepositoryFactory factory, SvnKitEnvironmentProperties environmentProperties) { return factory.build(environmentProperties); } }
vault
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(VaultTemplate.class) @Profile("vault") class SpringVaultRepositoryConfiguration { @Bean public SpringVaultEnvironmentRepository vaultEnvironmentRepository( SpringVaultEnvironmentRepositoryFactory factory, VaultEnvironmentProperties environmentProperties) { return factory.build(environmentProperties); } }
从代码可以看到 Git 是配置中心默认环境。
@Bean
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
return gitEnvironmentRepositoryFactory.build(environmentProperties);
}
我们进入 MultipleJGitEnvironmentRepository 类:
public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository {
}
这个类表示可以支持配置多个 Git 仓库,它继承自 JGitEnvironmentRepository 类:
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository implements EnvironmentRepository, SearchPathLocator, InitializingBean {
/**
* Get the working directory ready.
*/
public String refresh(String label) {
}
}
refresh 方法的作用就是 ConfigServer 会从我们配置的 Git 仓库拉取配置下来。
Zuul 源码解析
同理,我们找到 Zuul 的配置类 ZuulProxyAutoConfiguration:
@Configuration
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class })
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
}
通过 @Import
注解可以找到几个类:
- RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration
- RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration
- RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration
我们知道 Zuul 提供网关能力,通过上面这几个类就能分析到,它内部其实也是通过接口请求,找到每个服务提供的接口地址。
进入 RibbonCommandFactoryConfiguration 类:
public class RibbonCommandFactoryConfiguration {
}
总结
前面带领大家分析了一小段源码,Spring Cloud 很庞大,不可能一一分析,本文的主要目的就是教大家如何分析源码,从何处下手,以便大家可以按照这种思路继续跟踪下去。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:20-第19课:Spring Cloud 源码解析
文章字数:856
本文作者:神秘的小岛岛
发布时间:2020-07-07, 14:26:47
最后更新:2020-07-14, 23:05:36
原始链接:https://www.tuyrk.cn/gitchat/springcloud-quickly/20-springcloud-source/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。