美文网首页
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