spring cloud源码分析
Posted lodor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring cloud源码分析相关的知识,希望对你有一定的参考价值。
概述
从服务发现注解
@EnableDiscoveryClient入手,剖析整个服务发现与注册过程
一,spring-cloud-common包
针对服务发现,本jar包定义了
DiscoveryClient 接口
public interface DiscoveryClient { /** * A human readable description of the implementation, used in HealthIndicator * @return the description */ String description(); /** * @deprecated use the {@link org.springframework.cloud.client.serviceregistry.Registration} bean instead * * @return ServiceInstance with information used to register the local service */ @Deprecated ServiceInstance getLocalServiceInstance(); /** * Get all ServiceInstances associated with a particular serviceId * @param serviceId the serviceId to query * @return a List of ServiceInstance */ List<ServiceInstance> getInstances(String serviceId); /** * @return all known service ids */ List<String> getServices(); }
EnableDiscoveryClient注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(EnableDiscoveryClientImportSelector.class) //关键在这句话 public @interface EnableDiscoveryClient { /** * If true, the ServiceRegistry will automatically register the local server. */ boolean autoRegister() default true; }
@Import注解:支持导入普通的java类,并将其声明成一个bean
现在看EnableDiscoveryClientImportSelector类实现
@Order(Ordered.LOWEST_PRECEDENCE - 100) //指定实例化bean的顺序 public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> { @Override public String[] selectImports(AnnotationMetadata metadata) { String[] imports = super.selectImports(metadata); AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(getAnnotationClass().getName(), true)); boolean autoRegister = attributes.getBoolean("autoRegister"); if (autoRegister) { List<String> importsList = new ArrayList<>(Arrays.asList(imports)); importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration"); imports = importsList.toArray(new String[0]); } return imports; }
EnableDiscoveryClientImportSelector类继承SpringFactoryImportSelector类,该类是重点,如下:
public abstract class SpringFactoryImportSelector<T> implements DeferredImportSelector, BeanClassLoaderAware, EnvironmentAware { private ClassLoader beanClassLoader; private Class<T> annotationClass; private Environment environment; private final Log log = LogFactory.getLog(SpringFactoryImportSelector.class); @SuppressWarnings("unchecked") protected SpringFactoryImportSelector() { this.annotationClass = (Class<T>) GenericTypeResolver .resolveTypeArgument(this.getClass(), SpringFactoryImportSelector.class); } @Override public String[] selectImports(AnnotationMetadata metadata) { if (!isEnabled()) { return new String[0]; } AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(this.annotationClass.getName(), true)); Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName() + " annotated with @" + getSimpleName() + "?"); // Find all possible auto configuration classes, filtering duplicates 重点在这个地方 List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader .loadFactoryNames(this.annotationClass, this.beanClassLoader))); if (factories.isEmpty() && !hasDefaultFactory()) { throw new IllegalStateException("Annotation @" + getSimpleName() + " found, but there are no implementations. Did you forget to include a starter?"); } if (factories.size() > 1) { // there should only ever be one DiscoveryClient, but there might be more than // one factory log.warn("More than one implementation " + "of @" + getSimpleName() + " (now relying on @Conditionals to pick one): " + factories); } return factories.toArray(new String[factories.size()]); }
SpringFactoriesLoader调用loadFactoryNames其实加载META-INF/spring.factories下的class。
spring-cloud-netflix-eureka-client\src\main\resources\META-INF\spring.factories中配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration org.springframework.cloud.bootstrap.BootstrapConfiguration=org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration org.springframework.cloud.client.discovery.EnableDiscoveryClient=org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration
该类调用了DeferredImportSelector接口,即ImportSelector接口
,继承了selectImport方法,关于ImportSelector的具体作用,参考下面链接
http://www.jianshu.com/p/7fd7eeeccad0
对于selectImport的调用,是在spring context 包中的ConfigurationClassParser进行解析
先流程走到EurekaClientAutoConfiguration类与EurekaDiscoveryClientConfiguration类
以上是关于spring cloud源码分析的主要内容,如果未能解决你的问题,请参考以下文章
Spring cloud 中@EnableEurekaClient源码分析
Spring Cloud Eureka 源码分析 —— Client端