RefreshScope源码深度分析

来源

在spring-cloud-context包下(2.1.3 release)

为什么要与Spring深度结合?

我们开发的项目基本都是基于spring,一个配置可能在多个地方使用,所以为了更好的更新依赖的Bean的配置,与spring结合修改起来方便

如何与Spring深度结合?

一. 初始化
1. 首先RefreshAutoConfiguration中的RefreshScopeBeanDefinitionEnhancer会实现BeanDefinitionRegistryPostProcessor;可以在BeanDefinitionRegistry期间对被refreshscope修饰的类变成代理类(ScopedProxyFactoryBean);如果判断为refreshScope,会执行GenericScope下的postProcessBeanDefinitionRegistry,会将代理类变更为(LockedScopedProxyFactoryBean),此类专用作安全的刷新实际bean(读写锁)
2. RefreshScope监听Spring中的ContextRefreshedEvent事件,如果代理BeanDefinitionRegistry设置为非懒加载,就会提前初始化bean

二. 实际获取bean(默认懒加载)
1. 再调用代理对象,想获取其实际bean的方法时,会执行LockedScopedProxyFactoryBean的invoke方法执行实际代理的方法;而实际代理又有一个DelegatingIntroductionInterceptor拦截器来执行实际对象bean的初始化(如果初始化过直接拿到对象),实际调用的是GenericScope中的get方法;初始化完成后返回调用的方法。

如何做到配置更新(改变@Value、@ConfigurationProperties修饰的对象的变量)?

  1. 发布RefreshEvent事件
  2. RefreshEventListener监听RefreshEvent事件;后续发布EnvironmentChangeEvent(修改@ConfigurationProperties的属性)、销毁代理对象里边的实际bean对象和RefreshScopeRefreshedEvent事件并且,销毁genericScope缓存的实际bean对象

如何做到更新过程中其他线程读取安全,不会出现NPL?

在发布刷新事件后,会销毁代理实际对象;在下一次读取时,会有个读写锁,在写入的时候,阻塞读,等待写入成功后,放开阻塞;所以读写锁保证了更新过程中的线程安全问题

如何做到懒加载?

在spring初始化期间,只会创建一个代理对象;在真正使用的时候,获取bean的属性,会有拦截(1. 先执行GenericScope中的LockedScopedProxyFactoryBean中的invoke方法 2. 再执行DelegatingIntroductionInterceptor中的invoke方法,如果bean没有初始化会先初始化再调用get方法获取属性)

为什么要做成代理?

  1. 懒加载
  2. 线程安全

公司自建组件disconf为什么不用发布RefreshEvent事件?

因为我们大部分系统未引入spring cloud 的context包,所以没有用

为什么@ConfigurationProperties和普通bean的更新方式不一样?

@ConfigurationProperties采用的是监听EnvironmentChangeEvent事件来重新绑定rebind属性
而@Value采用的是销毁代理中的原始bean

因为ConfigurationProperties只注重属性的获取与赋值
而普通的bean有很多额外的操作,像DataSource,改变了url需要先销毁原先的,再重建

为什么@ConfigurationProperties的rebind不使用替换,而是先销毁再初始化

  1. 为了保证整个操作的原子性,如果是替换,部分成功部分失败,将会造成不可预知的后果
  2. 可以针对final修饰的属性进行重建
  3. 完美支持@PostStruct、@PreDestory
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值