SpringCloud中动态配置刷新@RefreshScope的源码解析

@RefreshScope
public class App {
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
// 作用域为刷新作用域
@Scope("refresh")
@Documented
public @interface RefreshScope注解 {

    /**
     * 作用域代理的模式,默认为CGLIB
     */
    @AliasFor(annotation = Scope.class)
    ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

// 导入刷新配置的核心处理类
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(ConfigurationPropertiesBindingPostProcessor.class)
public class ConfigurationPropertiesRebinderAutoConfiguration implements ApplicationContextAware, SmartInitializingSingleton {
    // Spring上下文
    private ApplicationContext context;

    // 创建ConfigurationPropertiesBeans的Bean,它保存了所有标注在当前上下文中所有的ConfigurationProperties类
    @Bean
    @ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
    public static ConfigurationPropertiesBeans configurationPropertiesBeans() {
        return new ConfigurationPropertiesBeans();
    }

    // 注入将指定ConfigurationProperties类进行重新绑定
    @Bean
    @ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
    public ConfigurationPropertiesRebinder configurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {
        ConfigurationPropertiesRebinder rebinder = new ConfigurationPropertiesRebinder(beans);
        return rebinder;
    }

    // 所有的Bena都初始化完成
    @Override
    public void afterSingletonsInstantiated() {
        // 如果存在父容器
        if (this.context.getParent() != null) {
            // 获取ConfigurationPropertiesRebinder该Bean
            ConfigurationPropertiesRebinder rebinder = this.context.getBean(ConfigurationPropertiesRebinder.class);
            // 获取父容器中所有的Bean进行重新加载
            for (String name : this.context.getParent().getBeanDefinitionNames()) {
                rebinder.rebind(name);
            }
        }
    }

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnProperty(name = RefreshAutoConfiguration.REFRESH_SCOPE_ENABLED, matchIfMissing = true)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
@EnableConfigurationProperties(RefreshAutoConfiguration.RefreshProperties.class)
public class RefreshAutoConfiguration {

    // 注册刷新作用域
    @Bean
    @ConditionalOnMissingBean(RefreshScope.class)
    public static RefreshScope refreshScope() {
        return new RefreshScope();
    }

    // 配置数据上下文的刷新器,它负责刷新该作用域下的所有bean
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnBootstrapDisabled
    public ConfigDataContextRefresher configDataContextRefresher(ConfigurableApplicationContext context, RefreshScope scope, RefreshProperties properties) {
        return new ConfigDataContextRefresher(context, scope, properties);
    }

    /**
     * {@link com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener(java.lang.String, java.lang.String)}
     * 配置刷新的监听器,该RefreshEvent是由对应的配置中心发布的事件,例如Nacos发生匹配变化的时候,就会触发一个RefreshEvent事件
     */
    @Bean
    public RefreshEventListener refreshEventListener(ContextRefresher contextRefresher) {
        return new RefreshEventListener(contextRefresher);
    }
}

// 配置数据上下文的刷新器,它负责刷新该作用域下的所有bean
public class ConfigDataContextRefresher extends ContextRefresher implements ApplicationListener<ContextRefreshedWithApplicationEvent> {
    // Spring上下文对象
    private ConfigurableApplicationContext context;
    // 刷新作用域的实现
    private RefreshScope scope;
    // SpringBoot的配置为了
    private SpringApplication application;

    @Override
    public void onApplicationEvent(ContextRefreshedWithApplicationEvent event) {
        application = event.getSpringApplication();
    }

    // 更新环境对象,返回一个新的环境对象
    @Override
    protected void updateEnvironment() {
        // 拷贝一份上下文环境存在的属性对象
        StandardEnvironment environment = copyEnvironment(getContext().getEnvironment());
        ConfigurableBootstrapContext bootstrapContext = getContext().getBeanProvider(ConfigurableBootstrapContext.class).getIfAvailable(DefaultBootstrapContext::new);
        // 加载所有的EnvironmentPostProcessor后置处理器
        List<String> classNames = SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, getClass().getClassLoader());

        Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,
                (parameters) -> {
                    parameters.add(DeferredLogFactory.class, logFactory);
                    parameters.add(Log.class, logFactory::getLog);
                    parameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
                    parameters.add(BootstrapContext.class, bootstrapContext);
                    parameters.add(BootstrapRegistry.class, bootstrapContext);
                });
        // 实例化所有EnvironmentPostProcessor的类
        List<EnvironmentPostProcessor> postProcessors = instantiator.instantiate(classNames);
        for (EnvironmentPostProcessor postProcessor : postProcessors) {
            // 对拷贝的环境对象进行后置处理操作
            postProcessor.postProcessEnvironment(environment, application);
        }
        // 如果包含refreshArgs属性,将该属性移除
        if (environment.getPropertySources().contains(REFRESH_ARGS_PROPERTY_SOURCE)) {
            environment.getPropertySources().remove(REFRESH_ARGS_PROPERTY_SOURCE);
        }
        // 获取环境对象中的所有属性
        MutablePropertySources target = getContext().getEnvironment().getPropertySources();
        String targetName = null;
        // 保持属性的顺序
        for (PropertySource<?> source : environment.getPropertySources()) {
            String name = source.getName();
            if (target.contains(name)) {
                targetName = name;
            }
            if (!this.standardSources.contains(name)) {
                if (target.contains(name)) {
                    target.replace(name, source);
                } else {
                    if (targetName != null) {
                        target.addAfter(targetName, source);
                        targetName = name;
                    } else {
                        target.addFirst(source);
                        targetName = name;
                    }
                }
            }
        }
    }

    // 刷新配置以及对应的配置为了
    public synchronized Set<String> refresh() {
        // 刷新环境对象
        Set<String> keys = this.refreshEnvironment();
        // 刷新标注了@RefreshScope的类
        this.scope.refreshAll();
        return keys;
    }

    // 刷新环境对象,返回发生变化的属性
    public synchronized Set<String> refreshEnvironment() {
        Map<String, Object> before = extract(this.context.getEnvironment().getPropertySources());
        // 更新环境对象,返回一个新的环境对象
        this.updateEnvironment();
        // 获取发生变化的属性名
        Set<String> keys = this.changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();
        /**发布一个事件,该事件会由{@link ConfigurationPropertiesRebinder#onApplicationEvent(EnvironmentChangeEvent)}处理,从而刷新标注了**/
        this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
        // 返回发生变化的属性
        return keys;
    }

    // 将原始的属性与当前的属性做对比,提取出发生变化的属性
    private Map<String, Object> changes(Map<String, Object> before, Map<String, Object> after) {
        Map<String, Object> result = new HashMap<>();
        for (String key : before.keySet()) {
            if (!after.containsKey(key)) {
                result.put(key, null);
            } else if (!equal(before.get(key), after.get(key))) {
                result.put(key, after.get(key));
            }
        }
        for (String key : after.keySet()) {
            if (!before.containsKey(key)) {
                result.put(key, after.get(key));
            }
        }
        return result;
    }
}

@ManagedResource
public class RefreshScope extends GenericScope implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, Ordered {
    // 刷新当前作用域的所有Bean
    public void refreshAll() {
        /**
         * 创建该作用域Bean的流程{@link RefreshScope#get(String, ObjectFactory)}
         */
        // 销毁所有refresh作用域的@Bean,下次需要发现该作用域没有缓存该Bean,则又会触发Bean的创建
        super.destroy();
        // 发布作用域刷新事件,这个事件我们自己可以监听的做一些事情
        this.context.publishEvent(new RefreshScopeRefreshedEvent());
    }

    /**
     * <pre>
     *     获取Bean对象,如果Bean对象不存在,则创建Bean
     *    // 根据不同的作用域来创建对象
     *    if (mbd.isSingleton()) {
     *        // 从单例池中获取,不存在则创建
     *        sharedInstance = getSingleton(beanName, () -> {
     * 	    	return createBean(beanName, mbd, args);
     *        });
     * 	    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
     *    }
     *    else if (mbd.isPrototype()) {
     *       // 直接创建
     *       prototypeInstance = createBean(beanName, mbd, args);
     *       beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
     *    }
     *    // 其他作用域
     *    else {
     *        // 获取自定义作用域的Scope对象
     *        String scopeName = mbd.getScope();
     * 		  Scope scope = this.scopes.get(scopeName);
     * 		  // 调用Scope的get方法,从该作用域中获取Bean对象,如果不存在则创建对象
     *          {@link BeanLifecycleWrapper#get(String, ObjectFactory)}
     * 		  Object scopedInstance = scope.get(beanName, () -> {
     * 		  		return createBean(beanName, mbd, args);
     *          });
     * 		  beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
     *    }
     * </pre>
     */
    // 自定义作用域的get方法,从指定位置返回该作用域的Bean对象,这个Bean对象由自己管理
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        // 缓存当前Bean
        BeanLifecycleWrapper value = this.cache.put(name, new BeanLifecycleWrapper(name, objectFactory));
        // 加读写锁
        this.locks.putIfAbsent(name, new ReentrantReadWriteLock());
        try {
            return value.getBean();
        } catch (RuntimeException e) {
            this.errors.put(name, e);
            throw e;
        }
    }
}

// Bean的Scope生命周期包装类
public class BeanLifecycleWrapper {

    // BeanName
    private final String name;
    // 创建Bean的工厂
    private final ObjectFactory<?> objectFactory;
    // Bean对象
    private volatile Object bean;
    // 销毁Bean执行的任务
    /**
     * 在创建的Bean的时候,如果Bean是DisposableBean类型,会自动注册一个任务,就是将该Bean执行所有的DestructionAwareBeanPostProcessor,处理一些销毁逻辑
     * {@link AbstractBeanFactory#registerDisposableBeanIfNecessary(String, Object, RootBeanDefinition)}
     */
    private Runnable callback;

    BeanLifecycleWrapper(String name, ObjectFactory<?> objectFactory) {
        this.name = name;
        this.objectFactory = objectFactory;
    }

    public String getName() {
        return this.name;
    }

    public void setDestroyCallback(Runnable callback) {
        this.callback = callback;
    }

    // 获取Bean对象
    public Object getBean() {
        // 是否存在Bean对象
        if (this.bean == null) {
            synchronized (this.name) {
                // 使用对象工厂创建Bean对象
                if (this.bean == null) {
                    // 保存Bean对象
                    this.bean = this.objectFactory.getObject();
                }
            }
        }
        return this.bean;
    }

    // 销毁Bean对象
    public void destroy() {
        // 如果没有设置销毁时需要执行的任务,则不处理任何东西
        if (this.callback == null) {
            return;
        }
        synchronized (this.name) {
            // 执行指定的销毁任务
            Runnable callback = this.callback;
            if (callback != null) {
                callback.run();
            }
            // 清空当前Bean对象
            this.callback = null;
            this.bean = null;
        }
    }
}

public class GenericScope implements Scope, BeanFactoryPostProcessor, BeanDefinitionRegistryPostProcessor, DisposableBean {
    // 所有继承该类的作用域保存对应Bean的缓存对象
    private BeanLifecycleWrapperCache cache = new BeanLifecycleWrapperCache(new StandardScopeCache());

    // 销毁对象
    @Override
    public void destroy() {
        // 清空所有该作用域的缓存Bean
        Collection<BeanLifecycleWrapper> wrappers = this.cache.clear();
        // 遍历所有该作用域的Bean的包装对象
        for (BeanLifecycleWrapper wrapper : wrappers) {
            // 调用每一个Bean包装器的销毁方法
            wrapper.destroy();
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        // 注册当前作用域为refresh
        beanFactory.registerScope(this.name, this);
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 获取所有的Bean
        for (String name : registry.getBeanDefinitionNames()) {
            BeanDefinition definition = registry.getBeanDefinition(name);
            if (definition instanceof RootBeanDefinition root) {
                // 如果是作用域代理的Bean
                if (root.getDecoratedDefinition() != null && root.hasBeanClass() && root.getBeanClass() == ScopedProxyFactoryBean.class) {
                    // 并且当前Bean的作用域正好是refresh
                    if (getName().equals(root.getDecoratedDefinition().getBeanDefinition().getScope())) {
                        // 修改当前Bean的BeanClass,增强一下,从ScopedProxyFactoryBean变成LockedScopedProxyFactoryBean
                        // 它是继承ScopedProxyFactoryBean,就是在执行的过程中添加了读写锁
                        root.setBeanClass(LockedScopedProxyFactoryBean.class);
                        // 添加构造参数
                        root.getConstructorArgumentValues().addGenericArgumentValue(this);
                        root.setSynthetic(true);
                    }
                }
            }
        }
    }
}


/**
 * {@link com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener(java.lang.String, java.lang.String)}
 * 配置刷新的监听器,该RefreshEvent是由对应的配置中心发布的事件,例如Nacos发生匹配变化的时候,就会触发一个RefreshEvent事件
 */
public class RefreshEventListener implements SmartApplicationListener {
    // 配置数据上下文的刷新器
    private ConfigDataContextRefresher refresh;
    // 配置是否就绪
    private AtomicBoolean ready = new AtomicBoolean(false);

    public RefreshEventListener(ContextRefresher refresh) {
        this.refresh = refresh;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ApplicationReadyEvent.class.isAssignableFrom(eventType) || RefreshEvent.class.isAssignableFrom(eventType);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationReadyEvent) {
            // 标记已就绪
            this.ready.compareAndSet(false, true);
        }
        if (event instanceof RefreshEvent) {
            // 已就绪才会处理
            if (this.ready.get()) {
                // 使用配置数据的上下文对象进行刷新
                Set<String> keys = this.refresh.refresh();
            }
        }
    }
}

@Component
public class ConfigurationPropertiesBeans implements BeanPostProcessor, ApplicationContextAware {
    // 标注了ConfigurationProperties的Bean对象
    private Map<String, ConfigurationPropertiesBean> beans = new HashMap<>();
    // Spring上下文
    private ApplicationContext applicationContext;
    // Bean工厂
    private ConfigurableListableBeanFactory beanFactory;
    // 刷新作用域
    private String refreshScope;
    // 刷新作用域是否初始化了
    private boolean refreshScopeInitialized;
    // 父容器中的ConfigurationPropertiesBeans
    private ConfigurationPropertiesBeans parent;

    // 初始化当前上下文中父容器的配置类ConfigurationProperties的Bean对象
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        if (applicationContext.getAutowireCapableBeanFactory() instanceof ConfigurableListableBeanFactory) {
            this.beanFactory = (ConfigurableListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        }
        AutowireCapableBeanFactory bf = applicationContext.getParent().getAutowireCapableBeanFactory();
        // 如果存在父容器
        if (applicationContext.getParent() != null && bf instanceof ConfigurableListableBeanFactory listable) {
            // 从父容器中获取获取ConfigurationPropertiesBeans
            String[] names = listable.getBeanNamesForType(ConfigurationPropertiesBeans.class);
            // 如果只存在一个
            if (names.length == 1) {
                // 将该父容器中的ConfigurationPropertiesBeans保存
                this.parent = (ConfigurationPropertiesBeans) listable.getBean(names[0]);
                // 将父容器中的ConfigurationProperties的Bean对象保存
                this.beans.putAll(this.parent.beans);
            }
        }
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 判断容器中的bean是不是refresh作用域
        // 如果是,不处理
        if (this.isRefreshScoped(beanName)) {
            return bean;
        }
        // 如果不是refresh作用域,获取执行beanName的Bean对象,标注了ConfigurationProperties才会返回对象
        // 如果不存在ConfigurationProperties注解,返回null
        ConfigurationPropertiesBean propertiesBean = ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName);
        // 如果是属性配置Bean
        if (propertiesBean != null) {
            // 保存当前配置Bean信息
            this.beans.put(beanName, propertiesBean);
        }
        return bean;
    }

    // 判断容器中的bean是不是refresh作用域
    private boolean isRefreshScoped(String beanName) {
        // 如果刷新作用域为空(默认)并且没有被初始化过
        if (this.refreshScope == null && !this.refreshScopeInitialized) {
            // 开始初始化,标记初始化
            this.refreshScopeInitialized = true;
            // 遍历当前容器中的保存的所有作用域(例如,单例,原型,会话等等
            for (String scope : this.beanFactory.getRegisteredScopeNames()) {
                // 从容器中获取RefreshScope的Bean对象,如果当前作用域是RefreshScope,则保存该作用域
                if (this.beanFactory.getRegisteredScope(scope) instanceof org.springframework.cloud.context.scope.refresh.RefreshScope) {
                    this.refreshScope = scope;
                    break;
                }
            }
        }
        // 如果beanName为空或者没找到RefreshScope的Bean,表示不是RefreshScope
        if (beanName == null || this.refreshScope == null) {
            return false;
        }
        // 如果当前Bean工厂包含指定的Bean,并且该Bean的作用域正是refresh(该Bean标注了@RefreshScope),返回true
        return this.beanFactory.containsBeanDefinition(beanName) && this.refreshScope.equals(this.beanFactory.getBeanDefinition(beanName).getScope());
    }

    // 获取所有标注了ConfigurationProperties的Bean对象的BeanName
    public Set<String> getBeanNames() {
        return new HashSet<>(this.beans.keySet());
    }

}

// 配置属性Bean的重新绑定器
@Component
@ManagedResource
public class ConfigurationPropertiesRebinder implements ApplicationContextAware, ApplicationListener<EnvironmentChangeEvent> {
    // 需要重新绑定的配置类
    private ConfigurationPropertiesBeans beans;
    // Spring上下文对象
    private ApplicationContext applicationContext;
    // 重新绑定过程中的异常
    private Map<String, Exception> errors = new ConcurrentHashMap<>();

    // 需要将哪些配置Bean进行重新绑定
    public ConfigurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {
        this.beans = beans;
    }

    // 重新绑定所有配置类
    @ManagedOperation
    public void rebind() {
        // 清空所有的异常信息
        this.errors.clear();
        // 遍历当前需要重新绑定的配置类Bean名称
        for (String name : this.beans.getBeanNames()) {
            // 重新绑定
            this.rebind(name);
        }
    }

    // 重新绑定指定配置类
    @ManagedOperation
    public boolean rebind(String name) {
        // 如果当前名称不在需要重新绑定的名单中,不处理
        if (!this.beans.getBeanNames().contains(name)) {
            return false;
        }
        ApplicationContext appContext = this.applicationContext;
        // 遍历所有层级的Spring上下文
        while (appContext != null) {
            // 如果包含该配置Bean,进行重新绑定
            if (appContext.containsLocalBean(name)) {
                return rebind(name, appContext);
            }
            // 如果当前容器不包含当前配置Bean,则查找父容器
            else {
                appContext = appContext.getParent();
            }
        }
        return false;
    }

    // 根据指定类型绑定
    public boolean rebind(Class type) {
        // 获取指定类型的配置Bean
        String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.applicationContext, type);
        if (beanNamesForType.length > 0) {
            // 获取到该Bean最原始的BeanName,因为该Bean可能设置了作用域代理
            String name = beanNamesForType[0];
            // 如果是作用域代理的Bean
            if (ScopedProxyUtils.isScopedTarget(name)) {
                // 获取最原始的bean名称,因为作用域代理的beanName经过加工
                name = ScopedProxyUtils.getOriginalBeanName(name);
            }
            // 开始绑定
            return rebind(name, this.applicationContext);
        }
        return false;
    }

    // 真正的开始查询绑定
    private boolean rebind(String name, ApplicationContext appContext) {
        try {
            // 获取需要绑定的Bean
            Object bean = appContext.getBean(name);
            // 获取到原始对象
            if (AopUtils.isAopProxy(bean)) {
                bean = ProxyUtils.getTargetObject(bean);
            }
            if (bean != null) {
                // 如果设置了不支持刷新,不处理
                if (getNeverRefreshable().contains(bean.getClass().getName())) {
                    return false;
                }
                // 销毁该Bean
                appContext.getAutowireCapableBeanFactory().destroyBean(bean);
                // 重新初始化该Bean
                appContext.getAutowireCapableBeanFactory().initializeBean(bean, name);
                return true;
            }
        } catch (RuntimeException e) {
            // 保存绑定的异常信息
            this.errors.put(name, e);
            throw e;
        } catch (Exception e) {
            this.errors.put(name, e);
            throw new IllegalStateException("Cannot rebind to " + name, e);
        }
        return false;
    }

    // 不支持刷新
    @ManagedAttribute
    public Set<String> getNeverRefreshable() {
        String neverRefresh = this.applicationContext.getEnvironment().getProperty("spring.cloud.refresh.never-refreshable", "com.zaxxer.hikari.HikariDataSource");
        return StringUtils.commaDelimitedListToSet(neverRefresh);
    }

    @ManagedAttribute
    public Set<String> getBeanNames() {
        return new HashSet<>(this.beans.getBeanNames());
    }

    // 如何监听到环境对象发生了改变,需要重新绑定
    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        // 在配置属性发生改变的时候,会发布这个事件
        /**
         * {@link ConfigDataContextRefresher#refreshEnvironment}
         */
        if (this.applicationContext.equals(event.getSource()) || event.getKeys().equals(event.getSource())) {
            this.rebind();
        }
    }

}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值