文章24 | 阅读 12800 | 点赞0
回顾一下前面分析的内容,NacosConfigAutoConfiguration定义了NacosContextRefresher监听器,监听ApplicationReadyEvent事件,当触发事件后会往nacos的configService中注册配置监听,Nacos在收到配置变更时会向applicationContext发布RefreshEvent事件。下面我们分析触发这个事件的后续操作。
首先我们定义一下测试代码:
@RestController
@RequestMapping("/refreshConfig")
@RefreshScope
public class RefreshController {
@Value("${refresh.config}")
private String config;
@GetMapping
public String getConfig(){
return config;
}
}
这里的refresh.config配置由nacos服务端配置:
bootstrap.yml配置:
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yaml
prefix: demo
group: DEMO_GROUP
profiles:
active: dev
在搞清楚整个流程之前,我们需要了解一些关于Spring-cloud的内容。 首先是@RefreshScope注解和RefreshScope类
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
/**
* @see Scope#proxyMode()
* @return proxy mode
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
这个@RefreshScope注解主要声明一个类的对象的作用域和刷新相关,既不是单例也不是原型,而且是会进行动态代理的。@Scope("refresh")
表示他是跟refresh
的作用域相关。
我们看一下spring的包扫描部分ClassPathBeanDefinitionScanner的doScan方法:
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
// 遍历所有的包路径
for (String basePackage : basePackages) {
// 找到包下的Bean定义
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
// 设置默认值, 有个BeanDefinitionDefaults对象定义默认值
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
// Lazy、Primary、DependsOn、Role、Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
// 根据ScopedProxyMode生成代理Holder
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
// 注册
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
关注 definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);这一行,根据scope的元数据生成对应的bean定义包装类holder:
static BeanDefinitionHolder applyScopedProxyMode(
ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
然后是ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);这行:
public static BeanDefinitionHolder createScopedProxy(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
@RefreshScope的proxyMode属性默认是TARGET_CLASS,因此,这里proxyTargetClass是true。
然后是ScopedProxyUtils.createScopedProxy方法:
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
// 原bean的名字
String originalBeanName = definition.getBeanName();
//原bean定义
BeanDefinition targetDefinition = definition.getBeanDefinition();
//代理bean名字,加了scopedTarget.前缀
String targetBeanName = getTargetBeanName(originalBeanName);
// Create a scoped proxy definition for the original bean name,
// "hiding" the target bean in an internal target definition.
// 代理类的bean定义,类型是ScopedProxyFactoryBean
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
//设置装饰的bean定义,把原bean定义放进去
proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
// 设置被代理的bean定义
proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(targetDefinition.getRole());
// targetBeanName属性注入
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
}
else {
// proxyTargetClass属性注入
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
}
// Copy autowire settings from original bean definition.
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary());
if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
}
// The target bean should be ignored in favor of the scoped proxy.
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false);
// Register the target bean as separate bean in the factory.
// 被代理的bean定义也会注册进去,但是beanName换掉了,是scopedTarget.XXX格式。
registry.registerBeanDefinition(targetBeanName, targetDefinition);
// Return the scoped proxy definition as primary bean definition
// (potentially an inner bean).
// 返回代理的bean定义,beanName用原来的,内容换了。外面也会注册。
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
分析一下这段代码:主要是多了一个bean定义,原bean定义的beanName换掉了,换成scopedTarget.xxx格式,而xxx的beanName对应的是代理类。对应的类型是ScopedProxyFactoryBean。
然后我们将目光转向spring-cloud-context的spring.factories文件:
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
我们看到EnableAutoConfiguration配置中有一个RefreshAutoConfiguration,点进去看一下:
@Bean
@ConditionalOnMissingBean(RefreshScope.class)
public static RefreshScope refreshScope() {
return new RefreshScope();
}
定义了一个RefreshScope类的Bean,这个类是和@RefreshScope注解对应的, 实际上就是针对@RefreshScope注解的bean的处理器。我们点进去看一下:
public class RefreshScope extends GenericScope implements ApplicationContextAware,
ApplicationListener<ContextRefreshedEvent>, Ordered {
看一下父类的定义:
public class GenericScope implements Scope, BeanFactoryPostProcessor,
BeanDefinitionRegistryPostProcessor, DisposableBean {
主要实现两个处理器BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
首先是BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,在容器的bean定义注册完成后执行:
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
for (String name : registry.getBeanDefinitionNames()) {
BeanDefinition definition = registry.getBeanDefinition(name);
if (definition instanceof RootBeanDefinition) {
RootBeanDefinition root = (RootBeanDefinition) definition;
if (root.getDecoratedDefinition() != null && root.hasBeanClass()
&& root.getBeanClass() == ScopedProxyFactoryBean.class) {
// 如果是ScopedProxyFactoryBean这个类型的
if (getName().equals(root.getDecoratedDefinition().getBeanDefinition()
.getScope())) { // 此时name是refresh
// 换掉类型
root.setBeanClass(LockedScopedProxyFactoryBean.class);
// 构造方法添加自身作为参数
root.getConstructorArgumentValues().addGenericArgumentValue(this);
// surprising that a scoped proxy bean definition is not already
// marked as synthetic?
// 合成 标记
root.setSynthetic(true);
}
}
}
}
}
可以看到,代理类的类型从ScopedProxyFactoryBean换成了LockedScopedProxyFactoryBean,同时构造方法注入RefreshScope对象进去。
然后是BeanFactoryPostProcessor的postProcessBeanFactory方法:
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
this.beanFactory = beanFactory;
// 注册refresh作用域
beanFactory.registerScope(this.name, this);
setSerializationId(beanFactory);
}
这个是beanFactory的后置处理器,当beanFactory准备完成后执行。主要是注册了一个作用域:refresh
@Override
public void registerScope(String scopeName, Scope scope) {
Assert.notNull(scopeName, "Scope identifier must not be null");
Assert.notNull(scope, "Scope must not be null");
if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
}
// 添加到缓存里
Scope previous = this.scopes.put(scopeName, scope);
if (previous != null && previous != scope) {
if (logger.isDebugEnabled()) {
logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]");
}
}
}
被@RefreshScope注解的类会创建一个代理类的bean定义(实际上是@Scope注解就会创建,@RefreshScope是继承了它)
RefreshScope类用于处理@RefreshScope引入的代理类bean定义。主要做三件事:
把类型从ScopedProxyFactoryBean换成了LockedScopedProxyFactoryBean,同时注入了RefreshScope实例进去
为什么换类型呢?实际上ScopedProxyFactoryBean是由spring定义了,它只是定义了一个扩展作用域的规范,使用ScopedProxyFactoryBean来定义如何得到实例对象。而具体到每个扩展作用域的个性逻辑则由对应的子类实现,即:
@Scope --> @RefreshScope
ScopedProxyFactoryBean --> LockedScopedProxyFactoryBean
到这里我们基本了解了@RefreshScope和RefreshScope的作用,下面主要分析LockedScopedProxyFactoryBean是如何生成代理对象的。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_19414183/article/details/112282981
内容来源于网络,如有侵权,请联系作者删除!