美文网首页
Dubbo构造ServiceBean

Dubbo构造ServiceBean

作者: 你值得拥有更好的12138 | 来源:发表于2019-01-04 22:07 被阅读0次

一、 构造ServiceBean

ServiceBean继承与ServiceConfig,构造完成,并注册后。在触发ServiceBeanonApplicationEvent事 件后,进行dubbo意义上的provider注册zookeeper。一个ServiceBean就对应一个@Service的注解,注解的属性其实和在配置文件中是一致的。

首先dubbo使用ServiceAnnotationBeanPostProcessor实现spring的BeanDefinitionRegistryPostProcessor接口。这个接口是用来注册在配置文件或者注解中配置的javaBean.BeanDefinitionRegistryPostProcessor提供了让我们对BeanDefinition进行自定义注册的方法,如果Spring中的默认配置方式不能满足你的要求,就可以通过实现BeanDefinitionRegistryPostProcessor接口来进行扩展。(详情:http://rason.me/2016/12/16/BeanDefinitionRegistryPostProcessor/)

1.首先看下这个接口的方法:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

这个方法实现后,spring传入BeanDefinitionRegistry(Bean 定义注册),然后并调用方法。只需要在其中写注册的bean的业务。

再看看实现:

private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {

    DubboClassPathBeanDefinitionScanner scanner =
            new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);

    BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);

    scanner.setBeanNameGenerator(beanNameGenerator);
    //过滤器,保留带Service注解的类
    scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));

    for (String packageToScan : packagesToScan) {

        // Registers @Service Bean first
        scanner.scan(packageToScan);

        // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
        Set<BeanDefinitionHolder> beanDefinitionHolders =
                findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

        if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

            for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                registerServiceBean(beanDefinitionHolder, registry, scanner);
            }
}

通过DubboClassPathBeanDefinitionScanner进行扫描,配置注解的service类并注册他们,把scanner传递下去。然后从中过滤出带有@service注解的bean包装成BeanDefinitionHolder传递给registerServiceBean(beanDefinitionHolder, registry, scanner)方法。

2.然后看看registerServiceBean做了什么。

private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry           registry,DubboClassPathBeanDefinitionScanner scanner) {

    Class<?> beanClass = resolveClass(beanDefinitionHolder);

    Service service = findAnnotation(beanClass, Service.class);

    Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);

    String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
    //构造bean定义
    AbstractBeanDefinition serviceBeanDefinition =
            buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);

    // ServiceBean Bean name
    String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);

    if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
        registry.registerBeanDefinition(beanName, serviceBeanDefinition);

        if (logger.isInfoEnabled()) {
            logger.warn("The BeanDefinition[" + serviceBeanDefinition +
                    "] of ServiceBean has been registered with name : " + beanName);
        }

    } 
}

通过上一步BeanDefinitionHolder解析出字节码对象,接口的字节码,bean的名字包装为AbstractBeanDefinitionBeanDefinitionRegistry(spring)进行注册。

3.看看buildServiceBeanDefinition是怎么构造AbstractBeanDefinition的。

//以ServiceBean为根对象
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol", "interface");

propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));

// References "ref" property to annotated-@Service Bean
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// Set interface
builder.addPropertyValue("interface", interfaceClass.getName());

/**
 * Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
 */
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
    addPropertyReference(builder, "provider", providerConfigBeanName);
}

/**
 * Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
 */
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
    addPropertyReference(builder, "monitor", monitorConfigBeanName);
}

/**
 * Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
 */
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
    addPropertyReference(builder, "application", applicationConfigBeanName);
}

/**
 * Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
 */
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
    addPropertyReference(builder, "module", moduleConfigBeanName);
}

这里就是添加@Service注解的属性引用。源码中标记的Add Bean reference很多,未展示完。然后我跳回到上一步的registry.registerBeanDefinition去看看。他就是告诉spring我注册了这样一个javaBean。这就是构造了一个提供者的过程。

rootBeanDefinition(ServiceBean.class);这段代码告诉我们这BeanDefinition是以ServiceBean.class为根的,所以其实就是在构造ServiceBean.

二、总结

可以实现BeanDefinitionRegistryPostProcessor进行自定义扫描注解并注册自己的java bean.其实也就是给自己的代码集成Spring IOC.

相关文章

网友评论

      本文标题:Dubbo构造ServiceBean

      本文链接:https://www.haomeiwen.com/subject/ifutxqtx.html