spring cloud config client refresh过程

整体流程(触发EnvironmentChangeEvent事件)

spring cloud config client refresh过程_第1张图片

响应EnvironmentChangeEvent事件(进行rebind)

spring cloud config client refresh过程_第2张图片

RefreshEndpoint

@ConfigurationProperties(prefix = "endpoints.refresh", ignoreUnknownFields = false)
@ManagedResource
public class RefreshEndpoint extends AbstractEndpoint> {

    private ContextRefresher contextRefresher;

    public RefreshEndpoint(ContextRefresher contextRefresher) {
        super("refresh");
        this.contextRefresher = contextRefresher;
    }

    @ManagedOperation
    public String[] refresh() {
        Set keys = contextRefresher.refresh();
        return keys.toArray(new String[keys.size()]);
    }

    @Override
    public Collection invoke() {
        return Arrays.asList(refresh());
    }

}

ContextRefresher.refresh

public synchronized Set refresh() {
        Map before = extract(
                this.context.getEnvironment().getPropertySources());
        addConfigFilesToEnvironment();
        Set keys = changes(before,
                extract(this.context.getEnvironment().getPropertySources())).keySet();
        this.context.publishEvent(new EnvironmentChangeEvent(keys));
        this.scope.refreshAll();
        return keys;
    }

ConfigurationPropertiesRebinder.onApplicationEvent(EnvironmentChangeEvent)

@Component
@ManagedResource
public class ConfigurationPropertiesRebinder
        implements ApplicationContextAware, ApplicationListener {

    private ConfigurationPropertiesBeans beans;

    private ConfigurationPropertiesBindingPostProcessor binder;

    private ApplicationContext applicationContext;

    private Map errors = new ConcurrentHashMap<>();

    public ConfigurationPropertiesRebinder(
            ConfigurationPropertiesBindingPostProcessor binder,
            ConfigurationPropertiesBeans beans) {
        this.binder = binder;
        this.beans = beans;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * A map of bean name to errors when instantiating the bean.
     *
     * @return the errors accumulated since the latest destroy
     */
    public Map getErrors() {
        return this.errors;
    }

    @ManagedOperation
    public void rebind() {
        this.errors.clear();
        for (String name : this.beans.getBeanNames()) {
            rebind(name);
        }
    }

    @ManagedOperation
    public boolean rebind(String name) {
        if (!this.beans.getBeanNames().contains(name)) {
            return false;
        }
        if (this.applicationContext != null) {
            try {
                Object bean = this.applicationContext.getBean(name);
                this.binder.postProcessBeforeInitialization(bean, name);
                this.applicationContext.getAutowireCapableBeanFactory()
                        .initializeBean(bean, name);
                return true;
            }
            catch (RuntimeException e) {
                this.errors.put(name, e);
                throw e;
            }
        }
        return false;
    }

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

    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        rebind();
    }

}

ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization

public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        ConfigurationProperties annotation = AnnotationUtils
                .findAnnotation(bean.getClass(), ConfigurationProperties.class);
        if (annotation != null) {
            postProcessBeforeInitialization(bean, beanName, annotation);
        }
        annotation = this.beans.findFactoryAnnotation(beanName,
                ConfigurationProperties.class);
        if (annotation != null) {
            postProcessBeforeInitialization(bean, beanName, annotation);
        }
        return bean;
    }

AbstractAutowireCapableBeanFactory.initializeBean

/**
     * Initialize the given bean instance, applying factory callbacks
     * as well as init methods and bean post processors.
     * 

Called from {@link #createBean} for traditionally defined beans, * and from {@link #initializeBean} for existing bean instances. * @param beanName the bean name in the factory (for debugging purposes) * @param bean the new bean instance we may need to initialize * @param mbd the bean definition that the bean was created with * (can also be {@code null}, if given an existing bean instance) * @return the initialized bean instance (potentially wrapped) * @see BeanNameAware * @see BeanClassLoaderAware * @see BeanFactoryAware * @see #applyBeanPostProcessorsBeforeInitialization * @see #invokeInitMethods * @see #applyBeanPostProcessorsAfterInitialization */ protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }

doc

  • Detecting refreshing of RefreshScope beans

你可能感兴趣的:(springcloud)