Apollo源码阅读(二)Apollo客户端-ApolloAutoConfiguration

1,237 阅读4分钟

一、spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ctrip.framework.apollo.spring.boot.ApolloAutoConfiguration

二、ApolloAutoConfiguration配置

1、ApolloAutoConfiguration

  • 当apollo.bootstrap.enabled注入
  • 注入了ConfigPropertySourcesProcessor
@Configuration
@ConditionalOnProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED)
@ConditionalOnMissingBean(PropertySourcesProcessor.class)
public class ApolloAutoConfiguration {
  @Bean
  public ConfigPropertySourcesProcessor configPropertySourcesProcessor() {
    return new ConfigPropertySourcesProcessor();
  }
}

2、ConfigPropertySourcesProcessor

  • 这里用到了JDK SPI来加载ConfigPropertySourcesProcessorHelper,方便后续扩展
  • Spring触发阶段:AbstractApplicationContext#invokeBeanFactoryPostProcessors,调用所有BeanDefinitionRegistryPostProcessor
public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor
    implements BeanDefinitionRegistryPostProcessor {
  // 使用JDK SPI机制加载第一个ConfigPropertySourcesProcessorHelper, 这里是DefaultConfigPropertySourcesProcessorHelper
  private ConfigPropertySourcesProcessorHelper helper = ServiceBootstrap.loadPrimary(ConfigPropertySourcesProcessorHelper.class);
  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    helper.postProcessBeanDefinitionRegistry(registry);
  }
}

3、DefaultConfigPropertySourcesProcessorHelper负责注入几个bean

@Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap<>();
    propertySourcesPlaceholderPropertyValues.put("order", 0);
	// 1. 注册Spring的PropertySourcesPlaceholderConfigurer,负责操作Spring的PropertySources,是spring配置的来源
    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(),
        PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues);
    // 2. ApolloConfig属性级别注解和ApolloConfigChangeListener方法级别注解的支持
    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(),
        ApolloAnnotationProcessor.class);
    // 3. 解析@Value注解,并抽象为SpringValue,注册到单例的SpringValueRegistry中保存
    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(),
        SpringValueProcessor.class);
    // 4. 方法和属性级别的ApolloJsonValue注解的支持
    BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(),
        ApolloJsonValueProcessor.class);
	// 5. xml的beanDefination处理,抽象每个Field的信息为SpringValueDefinition,保存到SpringValueDefinitionProcessor的一个map中
    // Map<BeanDefinitionRegistry, Multimap<String, SpringValueDefinition>> beanName2SpringValueDefinitions
    processSpringValueDefinition(registry);
  }

4、ApolloProcessor和它的子类

ApolloProcessor是一个抽象类,实现了BeanPostProcessor接口,负责在Bean初始化之前,注入Apollo的配置,并把Spring的@Value抽象成对象,注册到Apollo自己的一个单例SpringValueRegistry中,方便后续的配置更新。processField和processMethod是两个抽象方法,由子类实现属性和方法的处理方式。

public abstract class ApolloProcessor implements BeanPostProcessor, PriorityOrdered {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    Class clazz = bean.getClass();
    for (Field field : findAllField(clazz)) {
      processField(bean, beanName, field);
    }
    for (Method method : findAllMethod(clazz)) {
      processMethod(bean, beanName, method);
    }
    return bean;
  }
}

4-1、ApolloAnnotationProcessor

ApolloAnnotationProcessor主要是处理两个注解

  • 属性级别注解ApploConfig,负责注入阿波罗的Config对象,可以获取某个namespace下的Config
  • 方法级别注解ApolloConfigChangeListener,负责向Config对象中添加监听器,当配置发生变化时可以收到通知
public class ApolloAnnotationProcessor extends ApolloProcessor {

  /**
   * 处理@ApploConfig(namespace)注解的属性,注入Apollo的Config
   */
  @Override
  protected void processField(Object bean, String beanName, Field field) {
    ApolloConfig annotation = AnnotationUtils.getAnnotation(field, ApolloConfig.class);
	// 校验字段必须是Config类型
    Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()),
        "Invalid type: %s for field: %s, should be Config", field.getType(), field);
    String namespace = annotation.value();
    // 根据namespace获取阿波罗Config
    Config config = ConfigService.getConfig(namespace);
    // 反射设置这个field
    ReflectionUtils.makeAccessible(field);
    ReflectionUtils.setField(field, bean, config);
  }

  /**
   * 1、从method上找到ApolloConfigChangeListener注解
   * 2、创建ConfigChangeListener---目的是当配置发生变化时,反射调用ApolloConfigChangeListener注解的方法
   * 3、注册ConfigChangeListener到每个Namespace的Config上
   */
  @Override
  protected void processMethod(final Object bean, String beanName, final Method method) {
    ApolloConfigChangeListener annotation = AnnotationUtils
        .findAnnotation(method, ApolloConfigChangeListener.class);
    Class<?>[] parameterTypes = method.getParameterTypes();
    ReflectionUtils.makeAccessible(method);
    String[] namespaces = annotation.value();
    String[] annotatedInterestedKeys = annotation.interestedKeys();
    String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
    // 监听Apollo配置发生变化的Listener,当有配置发生变化会调用ConfigChangeListener的onChange方法
    ConfigChangeListener configChangeListener = new ConfigChangeListener() {
      @Override
      public void onChange(ConfigChangeEvent changeEvent) {
        ReflectionUtils.invokeMethod(method, bean, changeEvent);
      }
    };
    Set<String> interestedKeys = annotatedInterestedKeys.length > 0 ? Sets.newHashSet(annotatedInterestedKeys) : null;
    Set<String> interestedKeyPrefixes = annotatedInterestedKeyPrefixes.length > 0 ? Sets.newHashSet(annotatedInterestedKeyPrefixes) : null;
    // 循环每个namespace,向他们的Config对象注册ConfigChangeListener
    for (String namespace : namespaces) {
      Config config = ConfigService.getConfig(namespace);
      if (interestedKeys == null && interestedKeyPrefixes == null) {
        config.addChangeListener(configChangeListener);
      } else {
        config.addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
      }
    }
  }
}

4-2、SpringValueProcessor

SpringValueProcessor主要是把类、方法、Spring的@Value注解抽象成SpringValue对象,注册到单例的SpringValueRegistry中,后续配置发生变化时,会从Registry中取出相应的SpringValue,然后通过反射实现@Value注解修饰方法和属性的更新

public class SpringValueProcessor extends ApolloProcessor implements BeanFactoryPostProcessor, BeanFactoryAware {
  // apollo客户端配置
  private final ConfigUtil configUtil;
  // 占位符操作辅助类
  private final PlaceholderHelper placeholderHelper;
  // SpringValue注册中心
  private final SpringValueRegistry springValueRegistry;
  // SpringBean工厂
  private BeanFactory beanFactory;
  // Xml配置的bean key是beanName value是Spring@Value的抽象
  private Multimap<String, SpringValueDefinition> beanName2SpringValueDefinitions;
  
  // BeanFactory后置处理,从SpringValueDefinitionProcessor获取到BeanName和所有SpringValueDefinition的映射关系,SpringValueDefinition是对xml配置的value属性的一层抽象
  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
      throws BeansException {
      beanName2SpringValueDefinitions = SpringValueDefinitionProcessor
          .getBeanName2SpringValueDefinitions((BeanDefinitionRegistry) beanFactory);
  }
  // 重写了ApolloProcessor的postProcessBeforeInitialization
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    // ApolloProcessor#postProcessBeforeInitialization
    // 1. processField field级别的@Value,放到SpringValueRegistry中
    // 2. processMethod 方法级别的@Value,放到SpringValueRegistry中
    super.postProcessBeforeInitialization(bean, beanName);
    // 3. 处理xml注册的bean的配置
    processBeanPropertyValues(bean, beanName);
    return bean;
  }


  @Override
  protected void processField(Object bean, String beanName, Field field) {
    // register @Value on field
    Value value = field.getAnnotation(Value.class);
    // 解析@Value的value属性,因为@Value可能有多个占位符等原因,获取到所有需要配置的key
    Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
    // 循环注册到springValueRegistry
    for (String key : keys) {
      SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false);
      springValueRegistry.register(beanFactory, key, springValue);
    }
  }

  @Override
  protected void processMethod(Object bean, String beanName, Method method) {
    //register @Value on method
    Value value = method.getAnnotation(Value.class);
    // 跳过了@Bean注解的方法
    if (method.getAnnotation(Bean.class) != null) {
      return;
    }
    // 解析@Value的value属性,因为@Value可能有多个占位符等原因,获取到所有需要配置的key
    Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
    // 循环注册到springValueRegistry
    for (String key : keys) {
      SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, method, false);
      springValueRegistry.register(beanFactory, key, springValue);
    }
  }
 // 处理xml注册的bean的配置
  private void processBeanPropertyValues(Object bean, String beanName) {
    Collection<SpringValueDefinition> propertySpringValues = beanName2SpringValueDefinitions
        .get(beanName);
    for (SpringValueDefinition definition : propertySpringValues) {
      PropertyDescriptor pd = BeanUtils
          .getPropertyDescriptor(bean.getClass(), definition.getPropertyName());
      Method method = pd.getWriteMethod();
      SpringValue springValue = new SpringValue(definition.getKey(), definition.getPlaceholder(),
          bean, beanName, method, false);
      springValueRegistry.register(beanFactory, definition.getKey(), springValue);
    }
    // clear
    beanName2SpringValueDefinitions.removeAll(beanName);
  }
 }

4-3、ApolloJsonValueProcessor

  • 负责处理方法和属性级别的@ApolloJsonValue,把配置通过反射注入bean
  • 抽象为SpringValue注册到SpringValueRegistry,处理以后的配置更新
public class ApolloJsonValueProcessor extends ApolloProcessor implements BeanFactoryAware {
 @Override
 protected void processField(Object bean, String beanName, Field field) {
   // 1. 解析ApolloJsonValue
   ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(field, ApolloJsonValue.class);
   String placeholder = apolloJsonValue.value();
   Object propertyValue = placeholderHelper
       .resolvePropertyValue(beanFactory, beanName, placeholder);
   // 2. 反射执行setter
   boolean accessible = field.isAccessible();
   field.setAccessible(true);
   ReflectionUtils
       .setField(field, bean, parseJsonValue((String)propertyValue, field.getGenericType()));
   field.setAccessible(accessible);
   // 3. 注册到SpringValueRegistry
   if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
     Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeholder);
     for (String key : keys) {
       SpringValue springValue = new SpringValue(key, placeholder, bean, beanName, field, true);
       springValueRegistry.register(beanFactory, key, springValue);
     }
   }
 }

 @Override
 protected void processMethod(Object bean, String beanName, Method method) {
     // 1. 解析ApolloJsonValue
   ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(method, ApolloJsonValue.class);
   String placeHolder = apolloJsonValue.value();
   Object propertyValue = placeholderHelper
       .resolvePropertyValue(beanFactory, beanName, placeHolder);
   // 2. 反射执行方法
   Type[] types = method.getGenericParameterTypes();
   boolean accessible = method.isAccessible();
   method.setAccessible(true);
   ReflectionUtils.invokeMethod(method, bean, parseJsonValue((String)propertyValue, types[0]));
   method.setAccessible(accessible);
  // 3. 注册到SpringValueRegistry
   if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
     Set<String> keys = placeholderHelper.extractPlaceholderKeys(placeHolder);
     for (String key : keys) {
       SpringValue springValue = new SpringValue(key, apolloJsonValue.value(), bean, beanName,
           method, true);
       springValueRegistry.register(beanFactory, key, springValue);
     }
   }
 }

 private Object parseJsonValue(String json, Type targetType) {
   return gson.fromJson(json, targetType);
 }
}