美文网首页程序员
Dubbo系列1-初始化(一)

Dubbo系列1-初始化(一)

作者: 梦孤 | 来源:发表于2018-08-24 18:13 被阅读0次

    在2.5.4版本中,我们通常使用以下方式启动dubbo应用

    public static void main(String[] args) {
        com.alibaba.dubbo.container.Main.main(args);
    }
    

    深入这个方法,其实核心的代码是这一段

    public void start() {
        String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
        if (configPath == null || configPath.length() == 0) {
            configPath = DEFAULT_SPRING_CONFIG;
        }
        context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false);
        context.addApplicationListener(new DubboApplicationListener());
        context.registerShutdownHook();
        context.refresh();
        context.start();
    }
    

    可以看到,其实还启动了spring的ClassPathXmlApplicationContext,并添加了一个DubboApplicationListener。更细的内容先放放,再看看在2.5.8版本后的基于annotation的启动方式:

    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();
        System.in.read();
    }
    

    这里除了换成创建AnnotationConfigApplicationContext意外,特别的就是这个ProviderConfiguration

    @Configuration
    @EnableDubbo(scanBasePackages = "com.alibaba.dubbo.samples.impl")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    public class ProviderConfiguration {
    }
    

    是不是和sprinBoot的风格很像,相比之前的xml配置方式,是不是清爽了很多?
    下面顺便也把provider中的service以及consumer中的reference一并贴一下,方便大家阅读:

    @Component("annotatedConsumer")
    public class GreetingServiceConsumer {
    
        @Reference
        private GreetingService greetingService;
    
        public String doSayHello(String name) {
            return greetingService.sayHello(name);
        }
    }
    
    @Service
    public class AnnotatedGreetingService implements GreetingService {
        public String sayHello(String name) {
            System.out.println("greeting service received: " + name);
            return "hello, " + name;
        }
    }
    

    除了@Service和@Reference两个Dubbo的标注,就没有其他框架层面的代码了,大大减少我们配置的工作量。
    回到我们的主题,知道了程序启动的入口,也知道其实都是通过spring容器来加载dubbo的Service的,那么Service是怎么加载并初始化的呢,这里分成两个阶段来介绍,一个是Service定义的加载;另一个是Service对象的实例化;

    Service定义的加载

    先来看看这个类

    /**
     * {@link Service} Annotation
     * {@link BeanDefinitionRegistryPostProcessor Bean Definition Registry Post Processor}
     *
     * @since 2.5.8
     */
    public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
            ResourceLoaderAware, BeanClassLoaderAware {
    ...
        @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!");
                }
            }
    
        }
        /**
         * 注册被 {@link Service}标注的类的Bean(此Bean是Service类的定义)
         *
         * @param packagesToScan The base packages to scan
         * @param registry       {@link BeanDefinitionRegistry}
         */
        private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
    
            DubboClassPathBeanDefinitionScanner scanner =
                    new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
    
            BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
    
            scanner.setBeanNameGenerator(beanNameGenerator);
    
            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) {
                        // 解析生成Service的定义Bean,并注册到spring容器中
                        registerServiceBean(beanDefinitionHolder, registry, scanner);
                    }
                } 
    
            }
    
        }
    ...
    }
    
    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();
            // 解析Service类的注解,创建RootBeanDefinition对象,对象的beanClass属性值为ServiceBean
            AbstractBeanDefinition serviceBeanDefinition =
                    buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
    
            // ServiceBean Bean name
            String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
    
            if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
                // 注册ServcieBean到spring容器中
                registry.registerBeanDefinition(beanName, serviceBeanDefinition);
    ...
    }
    

    未完待续...

    相关文章

      网友评论

        本文标题:Dubbo系列1-初始化(一)

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