需要前置知识,了解spring源码,springboot自动加载机制等
DubboBootstrap启动
详细信息可看 学习Dubbo源码需要了解的基础内容源码详解
DubboBootstrap 启动所需要的信息
- 添加应用程序配置
- 添加注册中心配置
- 添加协议配置
- 添加服务配置
- 启动
SpringBoot启动Dubbo
@EnableDubbo
注解 中引用了 @DubboComponentScan
和 @EnableDubboConfig
注解
@DubboComponentScan
注解中引用了 @Import(DubboComponentScanRegistrar.class) 所以以DubboComponentScanRegistrar类为起点
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
DubboComponentScanRegistrar
实现自 ImportBeanDefinitionRegistrar
重写了 registerBeanDefinitions
方法,在SpringBoot源码中会回调 registerBeanDefinitions
方法,可见SpringBoot源码
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// initialize dubbo beans
// 核心 初始化环境 包括注册监听器
DubboSpringInitializer.initialize(registry);
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
// 注册ServiceBean 和dubbo启动信息
registerServiceAnnotationPostProcessor(packagesToScan, registry);
}
DubboSpringInitializer.initialize(registry) =》 调用 initContext(context, registry, beanFactory) 初始化上下文
initContext(context, registry, beanFactory) =》调用 DubboBeanUtils.registerCommonBeans(registry);注册公共使用Bean对象
DubboBeanUtils.registerCommonBeans(registry);
static void registerCommonBeans(BeanDefinitionRegistry registry) {
registerInfrastructureBean(registry, ServicePackagesHolder.BEAN_NAME, ServicePackagesHolder.class);
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);
}
注册服务配置信息SercviceBean
registerServiceAnnotationPostProcessor(packagesToScan, registry);
注册了 ServiceAnnotationPostProcessor
private void registerServiceAnnotationPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
// 注册 ServiceAnnotationPostProcessor
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
ServiceAnnotationPostProcessor
实现了BeanDefinitionRegistryPostProcessor,所以会调用postProcessBeanDefinitionRegistry方法
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
// 扫描Bean
scanServiceBeans(resolvedPackagesToScan, registry);
}
scanServiceBeans(resolvedPackagesToScan, registry);
这个方法就包含了注册dubbo配置的bean的逻辑了,需要扫描自定义的注解来注册到spring的ioc容器中的套路大致都是相同的,和Mybatis一样,使用spring的扩展机制来扫描自定义的注解,然后注册为BeanDefinition,即可在Spring中注册为bean
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);
// 添加有 @DubboService @Service 的过滤条件
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;
}
// Registers @Service Bean first
// 包扫描,扫描当前包路径下所有类(因为没开 @Indexed注解 )
scanner.scan(packageToScan);
// 查找@Service的所有beandefinitionholder,无论@ComponentScan是否扫描
// 包装成 BeanDefinitionHolder 返回
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) {
// 核心 核心 对 每一个包装的 beanDefinitionHolder 处理
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 @Service was found under package ["
+ packageToScan + "], ignore re-scanned classes: " + scanExcludeFilter.getExcludedCount());
}
}
servicePackagesHolder.addScannedPackage(packageToScan);
}
}
@DubboService注解的扫描使用原理
这里保证文档可读性,简单介绍,详情见 Dubbo注解 详细介绍
DubboClassPathBeanDefinitionScanner 扫描包类 实现自 ClassPathBeanDefinitionScanner
在 scanServiceBeans 方法中 通过以下代码添加了 DubboService Service 注解的过滤条件,从而才scan 扫描报的时候根据过滤条件寻找类,Scan扫描包去看Spring扫描包原理
private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
// @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007
DubboService.class,
// @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service
Service.class,
// @since 2.7.3 Add the compatibility for legacy Dubbo's @Service , the issue : https://github.com/apache/dubbo/issues/4330
com.alibaba.dubbo.config.annotation.Service.class
);
// 添加有 @DubboService @Service 的过滤条件
for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
}
……
scanner.scan(packageToScan);
processScannedBeanDefinition
private void processScannedBeanDefinition(BeanDefinitionHolder beanDefinitionHolder) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
// 获取 @DubboService
Annotation service = findServiceAnnotation(beanClass);
// 获取配置在注解@DubboService上的所有属性
Map<String, Object> serviceAnnotationAttributes = AnnotationUtils.getAttributes(service, true);
// 根据注解信息和类信息解析出接口信息
String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);
// 拿到 @DubboSerivce修饰的类名
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// ServiceBean Bean name
String beanName = generateServiceBeanName(serviceAnnotationAttributes, serviceInterface);
// 构造了关于Servicebean的 BeanDefinition
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(serviceAnnotationAttributes, serviceInterface, annotatedServiceBeanName);
// 把 关于Servicebean的 BeanDefinition 添加到spring中
registerServiceBeanDefinition(beanName, serviceBeanDefinition, serviceInterface);
}
buildServiceBeanDefinition
构建了一个BeanDefinition,设置他的BeanClass = ServiceBean, 每个接口都会生成一个BeanDefinition
到这里位置,就已经把所以扫描到@DubboService(包括兼容历史所需要的 @Service )注解的类,全部注册为了BeanDefinition,开始进行spring bean的初始化,开始初始化设置的ServiceBean
private AbstractBeanDefinition buildServiceBeanDefinition(Map<String, Object> serviceAnnotationAttributes,
String serviceInterface,
String refServiceBeanName) {
// 创建 ServiceBean 的Builder
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 设置ServiceBean需要的相关参数,例如 protocol,ref 等
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
"methods", "interfaceName", "parameters");
…… …… ……
return builder.getBeanDefinition();
}
ServiceBean初始化
初始化会调用 InitializingBean的 afterPropertiesSet 方法,详解见Dubbo前置知识
DubboDeployApplicationListener
在ServiceBean初始化后 DubboDeployApplicationListener 监听器监听了 ContextRefreshedEvent 时间,在spring初始化完成后 该监听器会被执行
onApplicationEvent监听事件
@Override
public void onApplicationEvent(ApplicationContextEvent event) {
if (nullSafeEquals(applicationContext, event.getSource())) {
if (event instanceof ContextRefreshedEvent) {
onContextRefreshedEvent((ContextRefreshedEvent) event);
} else if (event instanceof ContextClosedEvent) {
onContextClosedEvent((ContextClosedEvent) event);
}
}
}
onContextRefreshedEvent
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
ModuleDeployer deployer = moduleModel.getDeployer();
Assert.notNull(deployer, "Module deployer is null");
// start module
// 核心 部署器启动
Future 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);
}
}
}
DefaultModuleDeployer#start
部署器启动
@Override
public Future start() throws IllegalStateException {
// initialize,maybe deadlock applicationDeployer lock & moduleDeployer lock
// 初始化部署
applicationDeployer.initialize();
return startSync();
}
DefaultApplicationDeployer#initialize
初始化,包括配置中心,应用程序配置,元数据配置等
对应DubboBootstrap 代码启动的加载
@Override
public void initialize() {
if (initialized) {
return;
}
// Ensure that the initialization is completed when concurrent calls
synchronized (startLock) {
if (initialized) {
return;
}
// register shutdown hook
registerShutdownHook();
startConfigCenter();
loadApplicationConfigs();
initModuleDeployers();
// @since 2.7.8
startMetadataCenter();
initialized = true;
if (logger.isInfoEnabled()) {
logger.info(getIdentifier() + " has been initialized!");
}
}
}
DefaultModuleDeployer#startSync()
private synchronized Future startSync() throws IllegalStateException {
if (isStopping() || isStopped() || isFailed()) {
throw new IllegalStateException(getIdentifier() + " is stopping or stopped, can not start again");
}
try {
if (isStarting() || isStarted()) {
return startFuture;
}
// 却换模块启动状态 STARTING
onModuleStarting();
//如果为初始化则初始化
initialize();
// export services
//服务暴漏
exportServices();
// prepare application instance
// exclude internal module to avoid wait itself
if (moduleModel != moduleModel.getApplicationModel().getInternalModule()) {
applicationDeployer.prepareInternalModule();
}
// refer services
//引用服务
referServices();
// if no async export/refer services, just set started
//非异步启动直接转换状态为STARTED
if (asyncExportingFutures.isEmpty() && asyncReferringFutures.isEmpty()) {
onModuleStarted();
} else {
//如果是异步启动,等待服务发布和服务引用的回调
frameworkExecutorRepository.getSharedExecutor().submit(() -> {
try {
// wait for export finish
waitExportFinish();
// wait for refer finish
waitReferFinish();
} catch (Throwable e) {
logger.warn(CONFIG_FAILED_WAIT_EXPORT_REFER, "", "", "wait for export/refer services occurred an exception", e);
} finally {
onModuleStarted();
}
});
}
} catch (Throwable e) {
onModuleFailed(getIdentifier() + " start failed: " + e, e);
throw e;
}
return startFuture;
}
服务暴漏和服务拉去见 源码详解