启动时,配置:@EnableApolloConfig
......
@SpringBootApplication
// 启用apollo-client
@EnableApolloConfig
public class ApolloApplication {
public static void main(String[] args) {
SpringApplication.run(ApolloApplication.class, args);
}
}
......
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({ApolloConfigRegistrar.class})
public @interface EnableApolloConfig {
// 默认的命名空间:application
String[] value() default {"application"};
// 默认的order,等于后文的:Ordered.LOWEST_PRECEDENCE
int order() default 2147483647;
}
注解生效时,注入了:ApolloConfigRegistrar 类
......
// ImportBeanDefinitionRegistrar是 Spring 框架中的一个接口,主要作用是在运行时动态地向 Spring 容器中注册 Bean 定义。
// 与@Import注解配合:通常与@Import注解一起使用,当一个配置类使用@Import引入了一个实现了ImportBeanDefinitionRegistrar接口的类时,Spring 在处理这个配置类时会调用ImportBeanDefinitionRegistrar的实现方法来注册 Bean 定义。
public interface ImportBeanDefinitionRegistrar {
// 注册一个Bean
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, //表示引入这个注册器的配置类的注解元数据
BeanDefinitionRegistry registry, // BeanDefinitionRegistry是一个用于注册 bean 定义的接口
BeanNameGenerator importBeanNameGenerator) { // 用于生成导入的 bean 的名称。如果需要自定义 bean 的名称,可以使用这个生成器
this.registerBeanDefinitions(importingClassMetadata, registry);
}
// 注册一个Bean
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
}
}
....
// 用于排序
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
......
//
public interface ApolloConfigRegistrarHelper extends Ordered {
void registerBeanDefinitions(AnnotationMetadata var1, BeanDefinitionRegistry var2);
}
......
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Singleton;
......
// 这个SpringInjector类的作用是提供一种通过 Guice 进行依赖注入的方式,确保在多线程环境下安全地创建和获取注入器实例,并提供了获取特定类型实例的方法。
// 内部的SpringModule类用于配置具体的依赖绑定,将一些关键的类绑定为单例模式,以便在整个应用中共享实例。
// 这种设计模式有助于管理应用中的依赖关系,提高代码的可维护性和可测试性。
public class SpringInjector {
private static volatile Injector s_injector;
private static final Object lock = new Object();
public SpringInjector() {
}
// 这个方法用于获取 Guice 注入器实例
private static Injector getInjector() {
// 如果Injector实例为null,则进入同步块以确保只有一个线程进行初始化。
if (s_injector == null) {
synchronized(lock) {
// 在同步块中再次检查Injector是否为null,如果是,则尝试创建一个新的注入器实例。
if (s_injector == null) {
try {
// 创建注入器时,使用Guice.createInjector方法,并传入一个包含SpringModule的模块数组。
s_injector = Guice.createInjector(new Module[]{new SpringInjector.SpringModule()});
} catch (Throwable var4) {
// 如果在创建过程中出现异常,会捕获异常并抛出一个ApolloConfigException,同时记录错误日志。
ApolloConfigException exception = new ApolloConfigException("Unable to initialize Apollo Spring Injector!", var4);
Tracer.logError(exception);
throw exception;
}
}
}
}
return s_injector;
}
// 这个方法用于获取指定类型的实例
public static <T> T getInstance(Class<T> clazz) {
try {
return getInjector().getInstance(clazz);
} catch (Throwable var2) {
Tracer.logError(var2);
throw new ApolloConfigException(String.format("Unable to load instance for %s!", clazz.getName()), var2);
}
}
// 定义了一个内部静态类SpringModule,它继承自AbstractModule,用于配置 Guice 的依赖注入。
private static class SpringModule extends AbstractModule {
private SpringModule() {
}
// 重写了configure方法,在这个方法中进行依赖绑定,定制绑定类...
protected void configure() {
this.bind(PlaceholderHelper.class).in(Singleton.class);
this.bind(ConfigPropertySourceFactory.class).in(Singleton.class);
this.bind(SpringValueRegistry.class).in(Singleton.class);
}
}
}
......
public class PropertySourcesProcessor implements
// 允许在 Spring 的 Bean 工厂(BeanFactory)初始化所有 Bean 定义之后,但在 Bean 实例化之前,对 Bean 工厂进行后处理。
// 可以通过这个接口修改 Bean 定义、添加新的属性源等。
BeanFactoryPostProcessor,
// 实现这个接口的类可以获取到 Spring 的Environment对象,从而可以访问应用的环境变量、属性文件等配置信息。
EnvironmentAware,
// 表示这个类具有优先级顺序。在多个实现了相同接口的类中,可以根据优先级顺序来确定执行的先后顺序。
PriorityOrdered
{
// 命名空间
private static final Multimap<Integer, String> NAMESPACE_NAMES = LinkedHashMultimap.create();
// 自动更新BeanFactory
private static final Set<BeanFactory> AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES = Sets.newConcurrentHashSet();
// 自定义注射器类:SpringInjector,线程安全获取指定类型的实例
// apollo自定义属性配置工厂类(???)
private final ConfigPropertySourceFactory configPropertySourceFactory = (ConfigPropertySourceFactory)
SpringInjector.getInstance(ConfigPropertySourceFactory.class);
// apollo自定义配置工具(???)
private final ConfigUtil configUtil = (ConfigUtil)ApolloInjector.getInstance(ConfigUtil.class);
// apollo自定义环境配置类(???)
private ConfigurableEnvironment environment;
public PropertySourcesProcessor() {
}
public static boolean addNamespaces(Collection<String> namespaces, int order) {
return NAMESPACE_NAMES.putAll(order, namespaces);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 初始化属性
this.initializePropertySources();
// 初始化自动更新属性的特性(能力装配)
this.initializeAutoUpdatePropertiesFeature(beanFactory);
}
// 初始化属性
private void initializePropertySources() {
if (!this.environment.getPropertySources().contains("ApolloPropertySources")) {
CompositePropertySource composite = new CompositePropertySource("ApolloPropertySources");
ImmutableSortedSet<Integer> orders = ImmutableSortedSet.copyOf(NAMESPACE_NAMES.keySet());
UnmodifiableIterator iterator = orders.iterator();
while(iterator.hasNext()) {
int order = (Integer)iterator.next();
Iterator i$ = NAMESPACE_NAMES.get(order).iterator();
while(i$.hasNext()) {
String namespace = (String)i$.next();
Config config = ConfigService.getConfig(namespace);
composite.addPropertySource(this.configPropertySourceFactory.getConfigPropertySource(namespace, config));
}
}
NAMESPACE_NAMES.clear();
if (this.environment.getPropertySources().contains("ApolloBootstrapPropertySources")) {
this.ensureBootstrapPropertyPrecedence(this.environment);
this.environment.getPropertySources().addAfter("ApolloBootstrapPropertySources", composite);
} else {
this.environment.getPropertySources().addFirst(composite);
}
}
}
// 确保名为 “ApolloBootstrapPropertySources” 的属性源在环境属性源中的优先级最高(即排在首位)。如果不是,则将其移除并重新添加到首位。
private void ensureBootstrapPropertyPrecedence(ConfigurableEnvironment environment) {
MutablePropertySources propertySources = environment.getPropertySources();
PropertySource<?> bootstrapPropertySource = propertySources.get("ApolloBootstrapPropertySources");
if (bootstrapPropertySource != null && propertySources.precedenceOf(bootstrapPropertySource) != 0) {
propertySources.remove("ApolloBootstrapPropertySources");
propertySources.addFirst(bootstrapPropertySource);
}
}
// 初始化自动更新属性的特性(能力装配)
private void initializeAutoUpdatePropertiesFeature(ConfigurableListableBeanFactory beanFactory) {
if (this.configUtil.isAutoUpdateInjectedSpringPropertiesEnabled() && AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.add(beanFactory)) {
AutoUpdateConfigChangeListener autoUpdateConfigChangeListener = new AutoUpdateConfigChangeListener(this.environment, beanFactory);
List<ConfigPropertySource> configPropertySources = this.configPropertySourceFactory.getAllConfigPropertySources();
Iterator i$ = configPropertySources.iterator();
while(i$.hasNext()) {
ConfigPropertySource configPropertySource = (ConfigPropertySource)i$.next();
configPropertySource.addChangeListener(autoUpdateConfigChangeListener);
}
}
}
// 环境数据能力植入
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment)environment;
}
//
@Override
public int getOrder() {
return -2147483648;
}
// 重置
static void reset() {
NAMESPACE_NAMES.clear();
AUTO_UPDATE_INITIALIZED_BEAN_FACTORIES.clear();
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.ctrip.framework.apollo.spring.util;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
public class BeanRegistrationUtil {
public BeanRegistrationUtil() {
}
// 注册Bean1
public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry,
String beanName,
Class<?> beanClass) {
return registerBeanDefinitionIfNotExists(registry, beanName, beanClass, (Map)null);
}
// 注册Bean2
public static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry,
String beanName,
Class<?> beanClass,
Map<String, Object> extraPropertyValues) {
if (registry.containsBeanDefinition(beanName)) {
return false;
} else {
String[] candidates = registry.getBeanDefinitionNames();
String[] arr$ = candidates;
int len$ = candidates.length;
for(int i$ = 0; i$ < len$; ++i$) {
String candidate = arr$[i$];
BeanDefinition beanDefinition = registry.getBeanDefinition(candidate);
if (Objects.equals(beanDefinition.getBeanClassName(), beanClass.getName())) {
return false;
}
}
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(beanClass).getBeanDefinition();
if (extraPropertyValues != null) {
Iterator i$ = extraPropertyValues.entrySet().iterator();
while(i$.hasNext()) {
Entry<String, Object> entry = (Entry)i$.next();
beanDefinition.getPropertyValues().add((String)entry.getKey(), entry.getValue());
}
}
registry.registerBeanDefinition(beanName, beanDefinition);
return true;
}
}
}
public class DefaultApolloConfigRegistrarHelper implements ApolloConfigRegistrarHelper {
public DefaultApolloConfigRegistrarHelper() {
}
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, //表示引入这个注册器的配置类的注解元数据
BeanDefinitionRegistry registry // BeanDefinitionRegistry是一个用于注册 bean 定义的接口
) {
// 获取apollo启动生效注解信息
// 从传入的注解元数据中提取EnableApolloConfig注解的属性,并存储在AnnotationAttributes对象中。这可以用于获取注解中定义的配置信息,如命名空间和顺序等。
AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableApolloConfig.class.getName()));
// 获取注解的value值即apollo的namespaces
String[] namespaces = attributes.getStringArray("value");
// 获取注解的order
int order = (Integer)attributes.getNumber("order");
// 使用apollo自定义的属性处理器,把@EnableApolloConfig的配置信息,灌入属性处理机制中,数据喂养~
PropertySourcesProcessor.addNamespaces(Lists.newArrayList(namespaces), order);
Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap();
propertySourcesPlaceholderPropertyValues.put("order", 0);
// Bean注册:(前面都是数据准备,这里才是核心注册环节)
// 添加了一堆的处理器:
// 注册:PropertySourcesPlaceholderConfigurer
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
PropertySourcesPlaceholderConfigurer.class.getName(),
PropertySourcesPlaceholderConfigurer.class,
propertySourcesPlaceholderPropertyValues);
// 注册PropertySourcesProcessor
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
PropertySourcesProcessor.class.getName(),
PropertySourcesProcessor.class);
// 注册ApolloAnnotationProcessor
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
ApolloAnnotationProcessor.class.getName(),
ApolloAnnotationProcessor.class);
// 注册SpringValueProcessor
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
SpringValueProcessor.class.getName(),
SpringValueProcessor.class);
// 注册SpringValueDefinitionProcessor
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
SpringValueDefinitionProcessor.class.getName(),
SpringValueDefinitionProcessor.class);
// 注册ApolloJsonValueProcessor
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry,
ApolloJsonValueProcessor.class.getName(),
ApolloJsonValueProcessor.class);
}
public int getOrder() {
return 2147483647;
}
}

......
// ImportBeanDefinitionRegistrar是 Spring 框架中的一个接口,主要作用是在运行时动态地向 Spring 容器中注册 Bean 定义。
public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 解耦与可扩展性:通过这种方式,可以将服务的实现与使用服务的代码解耦。
* 不同的服务实现可以在不修改使用它们的代码的情况下进行切换,只要它们符合相同的接口或契约。
* 有多个实现了ApolloConfigRegistrarHelper接口的类,而ServiceBootstrap.loadPrimary()方法用于加载其中一个主要的实现。
*/
// 自定义了一个注册器Helper(运行时解耦加载,apollo只有一个默认的Helper实现子类,没搞那么麻烦.)
private ApolloConfigRegistrarHelper helper = (ApolloConfigRegistrarHelper)ServiceBootstrap.loadPrimary(ApolloConfigRegistrarHelper.class);
public ApolloConfigRegistrar() {
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 创建自定义服务的 bean 定义并注册到容器中
this.helper.registerBeanDefinitions(importingClassMetadata, registry);
}
}
至此,完成了一系列的环境配置 Bean,工具类 Bean 的 初始化加载工作............
1860

被折叠的 条评论
为什么被折叠?



