这些不知道,别说你熟悉 Spring( 四 )


这些不知道,别说你熟悉 Spring

文章插图
上图中的 getSpringFactoriesInstances 方法内部其实就是调用 SpringFactoriesLoader.loadFactoryNames 获取所有 ApplicationContextInitializer 接口的实现类,然后反射创建对象,并对这些对象进行排序(实现了 Ordered 接口或者加了 @Order 注解) 。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances; }至此,项目中所有 ApplicationContextInitializer 的实现已经加载并且创建好了 。在 prepareContext 阶段会进行所有已注册的 ApplicationContextInitializer#initialize() 方法的调用 。在此之前prepareEnvironment 阶段已经准备好了环境信息,此处接入配置中心就可以拉到远程配置信息然后填充到 Spring 环境中供应用使用 。
这些不知道,别说你熟悉 Spring

文章插图
SpringBoot 集成 ApolloApolloApplicationContextInitializer 实现 ApplicationContextInitializer 接口,并且在 spring.factories 文件中配置如下
这些不知道,别说你熟悉 Spring

文章插图
org.springframework.context.ApplicationContextInitializer=\com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializerinitialize() 方法中会根据 apollo.bootstrap.namespaces 配置的 namespaces 进行配置的拉去,拉去到的配置会封装成 ConfigPropertySource 添加到 Spring 环境 ConfigurableEnvironment 中 。具体的拉去流程就不展开讲了,感兴趣的可以自己去阅读源码了解 。
SpringCloud 集成 Nacos、Zk、Consul在 SpringCloud 场景下,SpringCloud 规范中提供了 PropertySourceBootstrapConfiguration 继承 ApplicationContextInitializer,另外还提供了个 PropertySourceLocator,二者配合完成配置中心的接入 。
这些不知道,别说你熟悉 Spring

文章插图
initialize 方法根据注入的 PropertySourceLocator 进行配置的定位获取,获取到的配置封装成 PropertySource 对象,然后添加到 Spring 环境 Environment 中 。
这些不知道,别说你熟悉 Spring

文章插图
Nacos、Zookeeper、Consul 都有提供相应 PropertySourceLocator 的实现
这些不知道,别说你熟悉 Spring

文章插图
我们来分析下 Nacos 提供的 NacosPropertySourceLocator,locate 方法只提取了主要流程代码,可以看到 Nacos 启动会加载以下三种配置文件,也就是我们在 bootstrap.yml 文件里配置的扩展配置 extension-configs、共享配置 shared-configs 以及应用自己的配置,加载到配置文件后会封装成 NacosPropertySource 放到 Spring 的 Environment 中 。
这些不知道,别说你熟悉 Spring

文章插图
public PropertySource<?> locate(Environment env) {loadSharedConfiguration(composite);loadExtConfiguration(composite);loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);return composite; }loadApplicationConfiguration 加载应用配置时,同时会加载以下三种配置,分别是
  1. 不带扩展名后缀,application
  2. 带扩展名后缀,application.yml
  3. 带环境,带扩展名后缀,application-prod.yml
并且从上到下,优先级依次增高

经验总结扩展阅读