dubbo原理

1.使用

参考文档:http://dubbo.apache.org/zh-cn/docs/2.7/user/preface/background/

compile 'org.apache.dubbo:dubbo-spring-boot-starter:2.7.7'
dubbo:
  #当前服务id和名称
  application:
    id: order
    name: order
  #注册中心地址及协议,同一集群内的多个地址用逗号分隔
  registry:
    address: nacos://127.0.0.1:8848
    protocol: nacos #注册中心地址协议,支持dubbomulticastzookeeperredisconsul(2.7.1)sofa(2.7.2)etcd(2.7.2)nacos(2.7.2)等协议
  #服务提供者协议
  protocol:
    name: dubbo
    port: 20880
  #服务消费者缺省值配置
  consumer:
    timeout: 60000
    check: true #启动时检查提供者是否存在,true报错,false忽略
  scan:
    base-packages: com.yue.product.service
@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(basePackages = "com.yue")
@EnableDubbo
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }
}

服务提供方:

//新版dubbo注解,暴露服务
@DubboService
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ItemDao itemDao;

    @Override
    public List<Item> getList() {
        return itemDao.selectList(null);
    }
}

服务消费方:

@RestController
@RequestMapping("/order")
public class OrderController {
    
    //引用服务
    @DubboReference
    private ItemService itemService;

    @GetMapping("/getOrder")
    public ResponseResult getOrderList() {
        return ResponseResult.success(itemService.getList());
    }

}

2.启动流程

本文以Dubbo2.7.7为例

启用注解 @EnableDubbo 

@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {...}

@EnableDubboConfig

@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {...}
//ImportBeanDefinitionRegistrar类只能通过其他类@Import的方式来加载,通常是启动类或配置类。
//使用@Import,如果括号中的类是ImportBeanDefinitionRegistrar的实现类,则会调用接口方法,将其中要注册的类注册成bean。
//实现该接口的类拥有注册bean的能力。
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
        boolean multiple = attributes.getBoolean("multiple");
        // 注册启用单一配置绑定
        registerBeans(registry, DubboConfigConfiguration.Single.class);
        // 如果启用多配置,则注册启用多重配置绑定
        if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }
        // 注册普通实例
        registerCommonBeans(registry);
    }
}
static void registerCommonBeans(BeanDefinitionRegistry registry) {

    // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
    registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
            ReferenceAnnotationBeanPostProcessor.class);

    // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093
    registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
            DubboConfigAliasPostProcessor.class);

    // Since 2.7.5 Register DubboLifecycleComponentApplicationListener as an infrastructure Bean
    registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
            DubboLifecycleComponentApplicationListener.class);

    // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean
    registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
            DubboBootstrapApplicationListener.class);

    // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
    registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
            DubboConfigDefaultPropertyValueBeanPostProcessor.class);
}

@DubboComponentScan

@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {...}
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
    //扫描服务提供包并注册ServiceAnnotationBeanPostProcessor
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
     //注册普通实例 registerCommonBeans(registry); }
//注册 private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) { BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class); builder.addConstructorArgValue(packagesToScan); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); } //扫描 private Set<String> getPackagesToScan(AnnotationMetadata metadata) { AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(DubboComponentScan.class.getName())); String[] basePackages = attributes.getStringArray("basePackages"); Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses"); String[] value = attributes.getStringArray("value"); // Appends value array attributes Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value)); packagesToScan.addAll(Arrays.asList(basePackages)); for (Class<?> basePackageClass : basePackageClasses) { packagesToScan.add(ClassUtils.getPackageName(basePackageClass)); } if (packagesToScan.isEmpty()) { return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName())); } return packagesToScan; } }

ServiceAnnotationBeanPostProcessor.class继承ServiceClassPostProcessor.class

ServiceClassPostProcessor.class中来注册ServiceBean!!!

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    //注册应用监听器
    registerBeans(registry, DubboBootstrapApplicationListener.class);
    //处理扫描包
    Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
    if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
        //注册服务bean
        registerServiceBeans(resolvedPackagesToScan, registry);
    } else {
        ...
    }
}

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
    //获取BeanDefinition扫描器,并设置beanName生成器,过滤
    DubboClassPathBeanDefinitionScanner scanner =
            new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
    scanner.setBeanNameGenerator(beanNameGenerator);
    //加入要扫描的注解类型
    serviceAnnotationTypes.forEach(annotationType -> {
        scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
    });
    for (String packageToScan : packagesToScan) {
        // 扫描
        scanner.scan(packageToScan);
        // 查找所有带上面Include注解类型的BeanDefinitionHolders,无论@ComponentScan是否扫描
        Set<BeanDefinitionHolder> beanDefinitionHolders =
                findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                registerServiceBean(beanDefinitionHolder, registry, scanner);
            }
            ...
        }
    }
}

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {
    Class<?> beanClass = resolveClass(beanDefinitionHolder);
    Annotation service = findServiceAnnotation(beanClass);
    AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
    Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
    AbstractBeanDefinition serviceBeanDefinition =
            buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

    // 生成服务名称并注册
    String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
    if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        registry.registerBeanDefinition(beanName, serviceBeanDefinition);
        ...
    }
}

至此,ServiceBean注册完成,并未实例化和初始化。

ReferenceAnnotationBeanPostProcessor.class继承AbstractAnnotationBeanPostProcessor.class

AbstractAnnotationBeanPostProcessor又继承InstantiationAwareBeanPostProcessorAdapter并实现MergedBeanDefinitionPostProcessor接口

AbstractAnnotationBeanPostProcessor中扫描缓存以备后续注入需要

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    if (beanType != null) {
        //获取@DubboReference注解字段并缓存
        InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }
}

InstantiationAwareBeanPostProcessorAdapter在实例化时

public PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

    InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
    try {
        找到@DubboReference来注入
        metadata.inject(bean, beanName, pvs);
    }...省略
    return pvs;
}

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
            (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        //InjectedElement又分为AnnotatedFieldElement,AnnotatedMethodElement
        for (InjectedElement element : elementsToIterate) {
            if (logger.isTraceEnabled()) {
                logger.trace("Processing injected element of bean '" + beanName + "': " + element);
            }
            element.inject(target, beanName, pvs);
        }
    }
}
//以AnnotatedFieldElement为例
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    Class<?> injectedType = resolveInjectedType(bean, field);
    //获取注入bean
    Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
    ReflectionUtils.makeAccessible(field);
    field.set(bean, injectedObject);
}
protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {
    //先从缓存中获取
    String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
    Object injectedObject = injectedObjectsCache.get(cacheKey);
    if (injectedObject == null) {
        //从子类创建
        injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
        // Customized inject-object if necessary
        injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
    }
    return injectedObject;
}
回到ReferenceAnnotationBeanPostProcessor中
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {
    // 创建一个引用bean名称
    String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
    // 注解注入声明的名称
    String referenceBeanName = getReferenceBeanName(attributes, injectedType);
    // 创建一个 @ReferenceBean实例
    ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
    // 判断是否是本地服务bean
    boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
    // 注册到spring容器中
    registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
    // 缓存一份bean实例
    cacheInjectedReferenceBean(referenceBean, injectedElement);
    // 如果存在则返回一个代理对象,否则立即获取
    return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
}

至此,ReferenceBean注册完成。

DubboBootstrapApplicationListener.class启动服务

public DubboBootstrap start() {
    if (started.compareAndSet(false, true)) {
        ready.set(false);
        // 初始化
        initialize();
        if (logger.isInfoEnabled()) {
            logger.info(NAME + " is starting...");
        }
        // 暴露(导出)服务
        exportServices();

        // 不仅提供者注册
        if (!isOnlyRegisterProvider() || hasExportedServices()) {
            // 暴露元数据服务
            exportMetadataService();
            // 如果需要,注册本地服务实例
            registerServiceInstance();
        }
        // 订阅服务
        referServices();
        ...
    }
    return this;
}

initialize();

private void initialize() {
    if (!initialized.compareAndSet(false, true)) {
        return;
    }
    //初始化FrameworkExt类,遍历执行配置管理器,环境等的初始化方法
    ApplicationModel.initFrameworkExts();
    //配置管理器读取并加载配置中心的配置信息,并准备环境,最后存入environment中
    startConfigCenter();
    //使用注册中心作为配置中心,如果有需要
    useRegistryAsConfigCenterIfNecessary();
    //加载远程配置
    loadRemoteConfigs();
    //检查全局配置
    checkGlobalConfigs();
    //初始化元数据服务,加载本地元数据服务提供者类
    initMetadataService();
    //初始化事件监听器
    initEventListener();
}

exportServices();

private void exportServices() {
    //获取所有ServiceBean遍历调用export()
    configManager.getServices().forEach(sc -> {
        ServiceConfig serviceConfig = (ServiceConfig) sc;
        serviceConfig.setBootstrap(this);
        if (exportAsync) {
            ExecutorService executor = executorRepository.getServiceExporterExecutor();
            Future<?> future = executor.submit(() -> {
                //暴露服务
                sc.export();
                exportedServices.add(sc);
            });
            asyncExportingFutures.add(future);
        } else {
            sc.export();
            exportedServices.add(sc);
        }
    });
}

看源码心态崩了,简单来说

1.根据url调用 doLocalExport 导出服务

2.根据 register 的值决定是否注册服务

3.向注册中心进行订阅 override 数据

服务导出详情参考:https://www.cnblogs.com/shenchen123456/p/13826528.html

posted @ 2020-11-14 23:07  柒月丶  阅读(323)  评论(0)    收藏  举报