【dubbo源码分析流程-2】
摘要:@EnableDubbo注解是Dubbo框架自动装配的入口,包含@EnableDubboConfig和@DubboComponentScan两个核心功能。前者开启配置自动装配,后者负责扫描@Service和@DubboService注解的类。通过DubboClassPathBeanDefinitionScanner执行包扫描,将符合条件的Bean注册到容器中,实现Dubbo服务的自动发现与装
dubbo自动装配入口
@EnableDubbo注解是源码分析的入口
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
@EnableDubbo源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig //开启自动装配
@DubboComponentScan //扫描核心
public @interface EnableDubbo {
/**
* Base packages to scan for annotated @Service classes.
* <p>
* Use {@link #scanBasePackageClasses()} for a type-safe alternative to String-based
* package names.
*
* @return the base packages to scan
* @see DubboComponentScan#basePackages()
*/
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages()} for specifying the packages to
* scan for annotated @Service classes. The package of each class specified will be
* scanned.
*
* @return classes from the base packages to scan
* @see DubboComponentScan#basePackageClasses
*/
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
/**
* It indicates whether {@link AbstractConfig} binding to multiple Spring Beans.
*
* @return the default value is <code>true</code>
* @see EnableDubboConfig#multiple()
*/
@AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
boolean multipleConfig() default true;
}
扫描DubboService的类
//在DubboComponentScanRegistrar实例化的时候,我们执行下面的方法,实例化ServerAnnotationPostProcessor
private void registerServiceAnnotationPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
ServerAnnotationPostProcessor.class注册所有的@Service以及@DubboService
ServerAnnotationPostProcessor注册实例化时,会走下面的postProcessDefinitionRegister()方法。
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
scanServiceBeans(resolvedPackagesToScan, registry);
}
走scanServiceBeans扫描@Service或者@DubboService修饰的类
private void scanServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
//标识位
scanned = true;
//校验扫描路径
if (CollectionUtils.isEmpty(packagesToScan)) {
if (logger.isWarnEnabled()) {
logger.warn(
CONFIG_NO_BEANS_SCANNED,
"",
"",
"packagesToScan is empty , ServiceBean registry will be ignored!");
}
return;
}
//核心执行扫描的类
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
//设置扫描拍的属性
scanner.setBeanNameGenerator(beanNameGenerator);
for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
}
ScanExcludeFilter scanExcludeFilter = new ScanExcludeFilter();
scanner.addExcludeFilter(scanExcludeFilter);
for (String packageToScan : packagesToScan) {
// avoid duplicated scans
if (servicePackagesHolder.isPackageScanned(packageToScan)) {
if (logger.isInfoEnabled()) {
logger.info("Ignore package who has already bean scanned: " + packageToScan);
}
continue;
}
// 核心扫描事件
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not. 查询全部的bean实例
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
if (logger.isInfoEnabled()) {
List<String> serviceClasses = new ArrayList<>(beanDefinitionHolders.size());
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
serviceClasses.add(
beanDefinitionHolder.getBeanDefinition().getBeanClassName());
}
logger.info("Found " + beanDefinitionHolders.size()
+ " classes annotated by Dubbo @Service under package [" + packageToScan + "]: "
+ serviceClasses);
}
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
//注册被@Service或者 @DubboService修饰的类,核心
processScannedBeanDefinition(beanDefinitionHolder);
servicePackagesHolder.addScannedClass(
beanDefinitionHolder.getBeanDefinition().getBeanClassName());
}
} else {
if (logger.isWarnEnabled()) {
logger.warn(
CONFIG_NO_ANNOTATIONS_FOUND,
"No annotations were found on the class",
"",
"No class annotated by Dubbo @DubboService or @Service was found under package ["
+ packageToScan + "], ignore re-scanned classes: "
+ scanExcludeFilter.getExcludedCount());
}
}
servicePackagesHolder.addScannedPackage(packageToScan);
}
}
processScannedBeanDefinition注册扫描到的被@DubboService或@Service修饰的类
private void processScannedBeanDefinition(BeanDefinitionHolder beanDefinitionHolder) {
//解析类
Class<?> beanClass = resolveClass(beanDefinitionHolder);
//获取当前类的注解
Annotation service = findServiceAnnotation(beanClass);
// T获取注解的属性
Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);
//解析服务的接口
String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);
//获取当前类的benaName
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// ServiceBean Bean name
String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);
// // ① 创建一个新的 BeanDefinition —— ServiceBean
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);
//注册新的 BeanDefinition
registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);
}
获取Referen修饰的属性

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 初始化dubbo 的bean实例
DubboSpringInitializer.initialize(registry);
}
}
DubboSpringInitializer#initContext()方法
private static void initContext(
DubboSpringInitContext context,
BeanDefinitionRegistry registry,
ConfigurableListableBeanFactory beanFactory) {
context.setRegistry(registry);
context.setBeanFactory(beanFactory);
// customize context, you can change the bind module model via DubboSpringInitCustomizer SPI
customize(context);
// 初始化模型模块
ModuleModel moduleModel = context.getModuleModel();
if (moduleModel == null) {
ApplicationModel applicationModel;
if (findContextForApplication(ApplicationModel.defaultModel()) == null) {
// first spring context use default application instance
applicationModel = ApplicationModel.defaultModel();
logger.info("Use default application: " + applicationModel.getDesc());
} else {
// 创建一个新的实例模块
applicationModel = FrameworkModel.defaultModel().newApplication();
logger.info("Create new application: " + applicationModel.getDesc());
}
// init ModuleModel
moduleModel = applicationModel.getDefaultModule();
context.setModuleModel(moduleModel);
logger.info("Use default module model of target application: " + moduleModel.getDesc());
} else {
logger.info("Use module model from customizer: " + moduleModel.getDesc());
}
logger.info(
"Bind " + moduleModel.getDesc() + " to spring container: " + ObjectUtils.identityToString(registry));
// set module attributes
Map<String, Object> moduleAttributes = context.getModuleAttributes();
if (moduleAttributes.size() > 0) {
moduleModel.getAttributes().putAll(moduleAttributes);
}
// 绑定dubbo的实力到spring容器中
registerContextBeans(beanFactory, context);
// mark context as bound
context.markAsBound();
moduleModel.setLifeCycleManagedExternally(true);
// 注册公共的实例信息
DubboBeanUtils.registerCommonBeans(registry);
}
//注册公共的实例信息
static void registerCommonBeans(BeanDefinitionRegistry registry) {
registerInfrastructureBean(registry, ServicePackagesHolder.BEAN_NAME, ServicePackagesHolder.class);
//注册referenceBeanManager实例
registerInfrastructureBean(registry, ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
// Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
registerInfrastructureBean(
registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
// TODO Whether DubboConfigAliasPostProcessor can be removed ?
// Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093
registerInfrastructureBean(
registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class);
// register ApplicationListeners
registerInfrastructureBean(
registry, DubboDeployApplicationListener.class.getName(), DubboDeployApplicationListener.class);
registerInfrastructureBean(
registry, DubboConfigApplicationListener.class.getName(), DubboConfigApplicationListener.class);
// Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
registerInfrastructureBean(
registry,
DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
DubboConfigDefaultPropertyValueBeanPostProcessor.class);
// Dubbo config initializer
registerInfrastructureBean(registry, DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class);
// register infra bean if not exists later
registerInfrastructureBean(
registry, DubboInfraBeanRegisterPostProcessor.BEAN_NAME, DubboInfraBeanRegisterPostProcessor.class);
}
注册 ReferenceAnnotationBeanPostProcessor类,实例化后执行postProcessBeanFactory()方法
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//获取spring容器中的所有的bean实例
String[] beanNames = beanFactory.getBeanDefinitionNames();
//遍历bean实例,找出这些实例中被@DubboReference或者@Reference注解修饰
for (String beanName : beanNames) {
Class<?> beanType;
if (beanFactory.isFactoryBean(beanName)) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
if (isReferenceBean(beanDefinition)) {
continue;
}
if (isAnnotatedReferenceBean(beanDefinition)) {
// process @DubboReference at java-config @bean method
processReferenceAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition);
continue;
}
String beanClassName = beanDefinition.getBeanClassName();
beanType = ClassUtils.resolveClass(beanClassName, getClassLoader());
} else {
beanType = beanFactory.getType(beanName);
}
if (beanType != null) {
AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
try {
prepareInjection(metadata);
} catch (BeansException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
}
}
}
if (beanFactory instanceof AbstractBeanFactory) {
List<BeanPostProcessor> beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors();
for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
if (beanPostProcessor == this) {
// This bean has been registered as BeanPostProcessor at
// org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory()
// so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause
// BeanPostProcessorChecker detection error
beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
break;
}
}
}
try {
// this is an early event, it will be notified at
// org.springframework.context.support.AbstractApplicationContext.registerListeners()
applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext));
} catch (Exception e) {
// if spring version is less than 4.2, it does not support early application event
logger.warn(
CONFIG_DUBBO_BEAN_INITIALIZER,
"",
"",
"publish early application event failed, please upgrade spring version to 4.2.x or later: " + e);
}
}
请求调用流程
消费者如何订阅到生产者
消费者初始化订阅的对象
创建ReferenceBean对象后会执行AfterPropertesSet()方法
public void afterPropertiesSet() throws Exception {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// pre init xml reference bean or @DubboReference annotation
Assert.notEmptyString(getId(), "The id of ReferenceBean cannot be empty");
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(getId());
this.interfaceClass = (Class<?>) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_CLASS);
this.interfaceName = (String) beanDefinition.getAttribute(ReferenceAttributes.INTERFACE_NAME);
Assert.notNull(this.interfaceClass, "The interface class of ReferenceBean is not initialized");
if (beanDefinition.hasAttribute(Constants.REFERENCE_PROPS)) {
// @DubboReference annotation at java-config class @Bean method
// @DubboReference annotation at reference field or setter method
referenceProps = (Map<String, Object>) beanDefinition.getAttribute(Constants.REFERENCE_PROPS);
} else {
if (beanDefinition instanceof AnnotatedBeanDefinition) {
// Return ReferenceBean in java-config class @Bean method
if (referenceProps == null) {
referenceProps = new LinkedHashMap<>();
}
ReferenceBeanSupport.convertReferenceProps(referenceProps, interfaceClass);
if (this.interfaceName == null) {
this.interfaceName = (String) referenceProps.get(ReferenceAttributes.INTERFACE);
}
} else {
// xml reference bean
propertyValues = beanDefinition.getPropertyValues();
}
}
if (referenceProps != null) {
this.proxy = (String) referenceProps.get(ReferenceAttributes.PROXY);
}
Assert.notNull(this.interfaceName, "The interface name of ReferenceBean is not initialized");
//创建referenceBeanManager对象
this.referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
//执行addreference方法
referenceBeanManager.addReference(this);
}
核心方法addreference()
public void addReference(ReferenceBean referenceBean) throws Exception {
String referenceBeanName = referenceBean.getId();
Assert.notEmptyString(referenceBeanName, "The id of ReferenceBean cannot be empty");
if (!initialized) {
// TODO add issue url to describe early initialization
logger.warn(
CONFIG_DUBBO_BEAN_INITIALIZER,
"",
"",
"Early initialize reference bean before DubboConfigBeanInitializer,"
+ " the BeanPostProcessor has not been loaded at this time, which may cause abnormalities in some components (such as seata): "
+ referenceBeanName
+ " = " + ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext));
}
//生成referencename的名称
String referenceKey = getReferenceKeyByBeanName(referenceBeanName);
if (StringUtils.isEmpty(referenceKey)) {
referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext);
}
//判断缓存中是否已经含有的此对象
ReferenceBean oldReferenceBean = referenceBeanMap.get(referenceBeanName);
if (oldReferenceBean != null) {
if (referenceBean != oldReferenceBean) {
String oldReferenceKey =
ReferenceBeanSupport.generateReferenceKey(oldReferenceBean, applicationContext);
throw new IllegalStateException("Found duplicated ReferenceBean with id: " + referenceBeanName
+ ", old: " + oldReferenceKey + ", new: " + referenceKey);
}
return;
}
//放到map缓存中
referenceBeanMap.put(referenceBeanName, referenceBean);
// save cache, map reference key to referenceBeanName
this.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
// if add reference after prepareReferenceBeans(), should init it immediately.
if (initialized) {
//初始化referenceBean创建referenceConfig
initReferenceBean(referenceBean);
}
}
initReferenceBean方法
public synchronized void initReferenceBean(ReferenceBean referenceBean) throws Exception {
//判断当前的referenceBean是否已经含有配置信息
if (referenceBean.getReferenceConfig() != null) {
return;
}
// TOTO check same unique service name but difference reference key (means difference attributes).
// 生成reference的名称
String referenceKey = getReferenceKeyByBeanName(referenceBean.getId());
//如果为null,则重新生成
if (StringUtils.isEmpty(referenceKey)) {
referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext);
}
//从map中获取referenceConfig
ReferenceConfig referenceConfig = referenceConfigMap.get(referenceKey);
//缓存中获取到的为null
if (referenceConfig == null) {
// 创建真正的referencebean信息
Map<String, Object> referenceAttributes = ReferenceBeanSupport.getReferenceAttributes(referenceBean);
referenceConfig = ReferenceCreator.create(referenceAttributes, applicationContext)
.defaultInterfaceClass(referenceBean.getObjectType())
.build();
// 设置id
if (referenceBean.getId() != null && !referenceBean.getId().contains("#")) {
referenceConfig.setId(referenceBean.getId());
}
// 放到缓存中
referenceConfigMap.put(referenceKey, referenceConfig);
// register ReferenceConfig
moduleModel.getConfigManager().addReference(referenceConfig);
moduleModel.getDeployer().setPending();
}
// 将referenceConfig和referenceBean关联
referenceBean.setKeyAndReferenceConfig(referenceKey, referenceConfig);
}
DubboDeployApplicationListener.onContextRefreshedEvent()对象
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
//获取模块模型的ModuleDeployer
ModuleDeployer deployer = moduleModel.getDeployer();
Assert.notNull(deployer, "Module deployer is null");
Object singletonMutex = LockUtils.getSingletonMutex(applicationContext);
// start module
Future future = null;
synchronized (singletonMutex) {
//开启startModel
future = deployer.start();
}
// if the module does not start in background, await finish
if (!deployer.isBackground()) {
try {
future.get();
} catch (InterruptedException e) {
logger.warn(
CONFIG_FAILED_START_MODEL,
"",
"",
"Interrupted while waiting for dubbo module start: " + e.getMessage());
} catch (Exception e) {
logger.warn(
CONFIG_FAILED_START_MODEL,
"",
"",
"An error occurred while waiting for dubbo module start: " + e.getMessage(),
e);
}
}
}
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐


所有评论(0)