spring cloud @refreshscope 注解源码流程
2023-02-14 22:42:42 0 举报
登录查看完整内容
springcloud 动态配置更新结合@refreshscope源码流程图
作者其他创作
大纲/内容
这个没啥好说的,就是一个 bean的销毁流程,看下源码就好了
动态刷新配置,销毁 refresh bean
缓存 scope beanscopeName -> RefreshScope
handle((RefreshEvent) event)
执行lambda 表达式
for (BeanLifecycleWrapper wrapper : wrappers) { // 遍历,执行销毁bean 的流程}
执行 get 方法,第一次 refresh scope bean 需要去 createBean并缓存起来,后面就直接去缓存起来的 refresh bean
RefreshEventListener
@Component
ConfigurationClassPostProcessor
RefreshScope
this.context.publishEvent(new RefreshScopeRefreshedEvent())
@ComponentScan
执行目标对象的方法,不会继续取走advice 链路了
target bean,原始的bean,被隐藏了
ClassPathBeanDefinitionScanner#doScan
缓存 scopeName - scopeBean(refresh - RefreshScope)
@Bean
getBean(targetBeanName)
ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
beandefinition.setScope(scopeMetadata.getScopeName())
设置callback
这里主要就是看 refreshables 是否配置了需要进行 refresh 的beanName,符合条件的去 createScopedProxy,但是这个refreshables 我不知道该怎么赋值进去
callback.run()
ScopedProxyFactoryBean
refresh bean 提前加载
new RefreshEventListener(contextRefresher)
MethodInterceptor
registerBeanDefinitionForImportedConfigurationClass(configClass)
2. 发布 refresh bean 刷新完成的事件
这里首先 BeanDefinition 都会设置 scope
构建 ProxyFactory 这个Spring 代理工厂对象
LockedScopedProxyFactoryBean
LegacyContextRefresher
DynamicAdvisedInterceptor
@RefreshScope 对应的是 RefreshScope 对象 extend GenericScope
SimpleBeanTargetSource
this.scopedTargetSource.getTargetClass()
走到 GenericScope 这个 RefreshScope 的父类中
事件监听可以监听ApplicationReadyEventRefreshEvent,该流程下主要看下RefreshEvent事件的监听
逆向查找发现是在doCreateBean 的时候注册销毁hook这个方法中赋值的
onApplicationEvent(ApplicationEvent event)
执行销毁bean 的线程
objectFactory 是个 lambda 表达式 - createBean这个put 方法效果就是,scopedTarget.beanName已存在则拿缓存的,没有就添加进缓存
getTargetSource
回到 scope.get方法
postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
super.setBeanFactory(beanFactory)
依赖注入,去执行 FactoryBean 的 getObject() 方法注意:这里 ScopedProxyFactoryBean 已经改为子类LockedScopedProxyFactoryBean
extend
this.beanFactory.getType(this.targetBeanName)
修改beandefinition 的 beanclass
FactoryBean
@ConditionalOnBootstrapDisabled所有条件都不匹配NoneNestedConditionsboolean match = !memberOutcomes.getMatches().isEmpty();
this.proxy = pf.getProxy(cbf.getBeanClassLoader())
缓存refresh bean
2. 刷新 refresh bean
RefreshScopeBeanDefinitionEnhancer
loadBeanDefinitionsForBeanMethod(beanMethod)
true
refresh
删除缓存的所有refresh bean并返回这些删除的数据
implements
执行销毁bean 线程
LockedScopedProxyFactoryBean.getObject()-> proxy
getObject()
ScopedProxyFactoryBean 在赋值 targetBeanName 的时候,将 targetBeanName 同时赋值给 scopedTargetSource 这个对象
invokeBeanFactoryPostProcessors
tenantProperties -> FactoryBean 创建的对象 ->ScopedProxyFactoryBean.getObjectType() -> TenantProperties ScopedProxyFactoryBean.getObject() -> 代理对象
执行链路获取方法返回值
将 BeanFactory 传递给 TargetSource
维护了该对象属性
doCreateBean
BeanDefinitionRegistryPostProcessor
非单例bean 走这个方法注册销毁
targetSource.getTarget()
this.scope.refreshAll()
处理 scope 为 refresh的beandefinition,原有 beanName 分配给一个新注册的 FactoryBean,target bean 的 target beanName 变成 targetScoped.beanName
loadbeandefinitions
getCallbacks(rootClass)
getbean
this.cache.clear()
注册 beandefinition
这里可以做一个扩展点,用于刷新完成后的自定义操作
this.context.getBean(name)
RefreshAutoConfiguration
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
scope 为refresh不走 单例和原型bean走自定义scope的流程
refreshEnvironment()
@Autowiredprivate TenantProperties tenantProperties;
implements ApplicationListenerapplicationContext refresh 完成发布事件监听,将refresh scope 的 bean 提前加载缓存起来
...pf.setTargetSource(this.scopedTargetSource)...
setBeanFactory(BeanFactory beanFactory)
getProxy(ClassLoader classLoader)
@RefreshScope 注解的Bean,实际能产生3个对象
更新 environment 环境变量
getObjectType()
postProcessBeanFactory
监听 RefreshEvent 事件
1. 刷新环境变量
直接在 create bean 的时候就去拿到 FactoryBean 的getObject 对象
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
ConfigDataContextRefresher
@ConditionalOnBootstrapEnabled匹配任意条件AnyNestedConditionboolean match = !memberOutcomes.getMatches().isEmpty();
if (root.getDecoratedDefinition() != null && root.hasBeanClass() && root.getBeanClass() == ScopedProxyFactoryBean.class) { if (getName().equals(root.getDecoratedDefinition().getBeanDefinition().getScope())) { // ScopedProxyFactoryBean 改为其子类 LockedScopedProxyFactoryBean root.setBeanClass(LockedScopedProxyFactoryBean.class); // RefreshScope 作为构造参数传递进 LockedScopedProxyFactoryBean 这个 bean root.getConstructorArgumentValues().addGenericArgumentValue(this); // surprising that a scoped proxy bean definition is not already // marked as `? root.setSynthetic(true); }}
eagerlyInitialize()
@ConfigurationProperties(prefix = \"tenant\")@RefreshScope@Componentpublic class TenantProperties { private String column;}
1. create bean的时候会进来
该 FactoryBean 作为Advice 添加给代理对象,并设置在第一个,这个第一个很重要,后面 invoke 的时候就不会走下面的 advicechain了
value.setDestroyCallback(callback)
Autowired TenantProperties 属性依赖注入找 bean 的时候FactoryBean 根据该方法来进行类型匹配
改 FactoryBean 的beanclass 为原来的子类 LockedScopedProxyFactoryBean
value.getBean()
清空所有 refresh bean 的缓存
postProcessBeanDefinitionRegistry
@Autowired TargetClass beanName -> FactoryBean所以每次执行这个 beanName 对应 bean 的方法都会进入代理逻辑-> 代理逻辑中去getBean
onApplicationEvent(ContextRefreshedEvent event)start(ContextRefreshedEvent event)
FactoryBean.getObject()
super.destroy()
1. 销毁原先缓存起来的 所有 refresh bean
wrapper.destroy()
2. 执行代理对象的时候会进来
这里是核心逻辑,右边是详细的流程
this.advised.getTargetSource()
核心:在这里会将原始的 bean 的beaname 添加 scopedTarget. 前缀原来的 beanName 给到新建的 ScopedProxyFactoryBean下面一步就写下核心代码
implements BeanDefinitionRegistryPostProcessor
this.refresh.refresh()
invoke(MethodInvocation invocation)
ConfigurationClassPostProcessor这个是入口,会在加载 beandefinition 的时候判断其 scope 从而会去构建一个 ScopeProxyFactoryBean
// 取原始的 beandefinitionBeanDefinition targetDefinition = definition.getBeanDefinition();// beanName -> scopedTarget.beanNameString targetBeanName = getTargetBeanName(originalBeanName);// 构建一个 FactoryBean -> getObject 创建代理对象,getObjectType -> originBeanClassRootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);...// ScopedProxyFactoryBean 对象属性赋值:被代理对象的 beanName 为 scopedTarget.beanName proxyDefinition.getPropertyValues().add(\"targetBeanName\
this.scopedTargetSource.setBeanFactory(beanFactory)
GenericScope
最后拿到 target bean (也就是TenantProperties) 的代理对象使用的是 cglib 代理
scopedTarget.tenantProperties -> scope 为 refresh,非单例bean,target bean -> TenantProperties
注册销毁 bean
依赖注入,根据类型找 bean,找到的就是 getObject() 创建的对象
&tenantProperties ->单例 bean (FactoryBean) -> ScopedProxyFactoryBean
cglibAopProxy
getBeanFactory().getBean(getTargetBeanName())
收藏
0 条评论
回复 删除
下一页