Dubbo之ServiceBean

什么是ServiceBean

dubbo的服务,生成的spring的bean定义类型都是ServiceBean。也就是dubbo的注解@Service和配置文件里的dubbo:service/生成的bean定义类型都是ServiceBean。
举个例子:
接口

package com.mytest.dubbo;

public interface DemoService {
}

实现类

package com.mytest.dubbo;
import com.alibaba.dubbo.config.annotation.Service;

@Service
public class DemoServiceImpl implements DemoService {
}

main方法

public static void main(String[] args) throws IOException {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoDubboConfig.class);
    context.start();
    ServiceBean bean = (ServiceBean)context.getBean("ServiceBean:com.mytest.dubbo.DemoService");
    System.out.println(bean);
}

context.getBean(“ServiceBean:com.mytest.dubbo.DemoService”)获取到的就是dubbo服务的bean。

Dubbo服务的bean定义在哪配置?

Dubbo服务的bean定义在哪配置,也就是ServiceBean在哪里设置的?

以下代码展示都是基于2.6.12的版本

首先在配置类上增加注解@EnableDubbo,开启dubbo,接着就可以看下@EnableDubbo是怎么工作的,最终把ServiceBean注册到spring中的。

@Configuration
@EnableDubbo(scanBasePackages = "com.mytest.dubbo" )
public class DemoDubboConfig {
}

@EnableDubbo上有@DubboComponentScan,再看@DubboComponentScan上导入了DubboComponentScanRegistrar.class,该类实现了ImportBeanDefinitionRegistrar接口,springIOC在执行过程中会调用ImportBeanDefinitionRegistrar接口的registerBeanDefinitions方法,用于注册bean定义。

@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
}

@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
}

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
}

接着来看下registerBeanDefinitions方法,该方法往springIOC注册了ServiceAnnotationBeanPostProcessor bean定义,该类实现了BeanDefinitionRegistryPostProcessor接口,在springIOC执行过程中又会执行postProcessBeanDefinitionRegistry方法。

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

    Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

    registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

    registerReferenceAnnotationBeanPostProcessor(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);

}

public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
        ResourceLoaderAware, BeanClassLoaderAware {
}

postProcessBeanDefinitionRegistry方法,调用了registerServiceBeans(resolvedPackagesToScan, registry),该方法会扫描加了注解@Service 的类,然后根据buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName)方法把相关信息和ServiceBean封装到一个bean定义中。

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);

    if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
        registerServiceBeans(resolvedPackagesToScan, registry);
    } else {
        if (logger.isWarnEnabled()) {
            logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
        }
    }

}

buildServiceBeanDefinition方法

private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
                                                          String annotatedServiceBeanName) {

    BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

    MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
    
    // 省略
}

以上过程,我们看到dubbo服务使用ServiceBean作为Spring的bean定义,接下来我们再看看ServiceBean如何进行导出的?

Dubbo服务如何进行导出?

SpringIOC在完成所有Bean定义和单例的初始化之后,会调用finishRefresh()方法,该方法会执行所有实现了ContextRefreshedEvent事件的监听器。
ServiceBean也是一个监听器,实现了ApplicationListener接口,具体方法实现:

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    if (isDelay() && !isExported() && !isUnexported()) {
        if (logger.isInfoEnabled()) {
            logger.info("The service ready on spring started. service: " + getInterface());
        }
        export();
    }
}

export() 方法就是具体的导出逻辑。export()往下跟,会调用protocol.export(wrapperInvoker)方法。
会调用3次该方法。
第一次会执行injvm协议,也就是导出到本地进程,该方法在com.alibaba.dubbo.config.ServiceConfig#exportLocal

private void exportLocal(URL url) {
    if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
        URL local = URL.valueOf(url.toFullString())
                .setProtocol(Constants.LOCAL_PROTOCOL)
                .setHost(LOCALHOST)
                .setPort(0);
        StaticContext.getContext(Constants.SERVICE_IMPL_CLASS).put(url.getServiceKey(), getServiceClass(ref));
        Exporter<?> exporter = protocol.export(
                proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
        exporters.add(exporter);
        logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
    }
}

第二次会执行dubbo协议,该方法是在com.alibaba.dubbo.registry.integration.RegistryProtocol#doLocalExport,也就是在注册时候会先执行dubbo协议,再执行registry协议

private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) {
    String key = getCacheKey(originInvoker);
    ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
    if (exporter == null) {
        synchronized (bounds) {
            exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
            if (exporter == null) {
                final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
                exporter = new ExporterChangeableWrapper<T>((Exporter<T>) protocol.export(invokerDelegete), originInvoker);
                bounds.put(key, exporter);
            }
        }
    }
    return exporter;
}

第三次会执行registry协议,执行该协议时会先dubbo协议,具体可以看下RegistryProtocol类。
在执行到具体的协议之前,都会以责任链的形式执行以下封装类

QosProtocolWrapper -> ProtocolFilterWrapper -> ProtocolListenerWrapper

具体这几个协议底层是怎么执行的,下次再分享。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值