当前位置:   article > 正文

Dubbo学习记录(七) -- Spring整合Dubbo原理中@Service解析流程;_dubboservice注解参数

dubboservice注解参数

Spring

看完了Spring整合Dubbo中, Dubbo配置文件的加载流程;
对@Service, @Reference的加载原理好奇, 挖根刨地,虽然看不懂每处细节,但是我至少想要了解整个流程是怎么走的。

package org.apache.dubbo.demo.provider;
public class Application {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();

        System.in.read();
    }
    @Configuration
    @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    static class ProviderConfiguration {

    }
}
//@EnabeDubbo注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {

	//该属性的值也是DubboComponentScan属性basePackages的值;
    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
	
    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
    boolean multipleConfig() default true;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • @EnableDubboConfig是用来加载配置文件的,并将properties文件里面的配置项转换为绑定的DubboConfig配置类与DubboConfigBingdingBeanPostProcessor后置处理器类,在前置处理过程, 使用Spring的DataBinder技术,给每个DubboConfig配置类绑定值;
  • @DubboComponentScan: 用来扫描@Service 和@Reference注解修饰的类;

@DubboComponentScan

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {

    /**
     * basePackages属性的别名。
     * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
     * declarations e.g.: {@code @DubboComponentScan("org.my.pkg")} instead of
     * {@code @DubboComponentScan(basePackages="org.my.pkg")}.
     *
     * @return the base packages to scan
     */
    String[] value() default {};

    /**
     * 扫描@Service注解类的基本包路径, value属性是这个属性的别名
     * Base packages to scan for annotated @Service classes. {@link #value()} is an
     * alias for (and mutually exclusive with) this attribute.
     * <p>
     * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
     * package names.
     *
     * @return the base packages to scan
     */
    String[] basePackages() default {};=
	//...
    Class<?>[] basePackageClasses() default {};

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • @DubboComponentScan 使用 Import注解 导入类DubboComponentScanRegistrar.class, 通过这个类完成@Service 和@Reference注解的扫描工作;

DubboComponentScanRegistrar

工作:

  1. 获得@DubboComponentToScan注解 定义的基础包路径,扫描基础包路径下的类。
  2. 注册一个ServiceAnnotationBeanPostProcessor处理器类,作用是完成处理被@Service修饰的类;
  3. 注册一个ReferenceAnnotationBeanPostProcessor处理器类, 作用是完成处理被@Reference注解修饰的类;
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("执行DubboComponentScanRegistrar");

        // 拿到DubboComponentScan注解所定义的包路径,扫描该package下的类,识别这些类上
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        // 注册ServiceAnnotationBeanPostProcessor一个Bean
        // 实现了BeanDefinitionRegistryPostProcessor接口,所以在Spring启动时会调用postProcessBeanDefinitionRegistry方法
        // 该方法会进行扫描,扫描@Service注解了的类,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),后续的Spring周期中会生成Bean
        // 在ServiceBean中会监听ContextRefreshedEvent事件,一旦Spring启动完后,就会进行服务导出
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

        // 注册ReferenceAnnotationBeanPostProcessor
        // 实现了AnnotationInjectedBeanPostProcessor接口,继而实现了InstantiationAwareBeanPostProcessorAdapter接口
        // 所以Spring在启动时,在对属性进行注入时会调用AnnotationInjectedBeanPostProcessor接口中的postProcessPropertyValues方法
        // 在这个过程中会按照@Refrence注解的信息去生成一个RefrenceBean对象
        registerReferenceAnnotationBeanPostProcessor(registry);

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

getPackagesToScan(importingClassMetadata)

工作:

  1. 获取DubboComponentScan注解类的所有属性;
  2. 获取DubboComponentScan的basePackages属性值;
  3. 获取DubboComponentScan的basePackageClasses属性值;
  4. 获取DubboComponentScan的value属性值;
  5. 创建一个Set集合存储存储value, basePackages路径;
  6. 获取basePackageClass的包名路径,放入Set集合;
  7. 如果Set集合最后还是为空, 先获取注解所修饰的类的路径包名;
  • 开头@EnableDubbo(scanBasePackages = “org.apache.dubbo.demo.provider”),我们指定了扫描的基本路径
  • 如果没有配置这个路径, 就会使用 @EnabbleDubbo 所修饰的类的路径包名 作为扫描路径 即“org.apache.dubbo.demo.provider”
    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;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

registerServiceAnnotationBeanPostProcessor(packagesToScan, registry)

工作:

  1. 创建一个代表ServiceAnnotationBeanPostProcessor的BeanDefinitionBuilder构造器;
  2. 设置构造器属性 , 参数为扫描的路径集合;
  3. 设置Role属性, 默认为2;
  4. 获取代表ServiceAnnotationBeanPostProcessor的BeanDefinition;
  5. 注入容器;
    /**
     * Registers {@link ServiceAnnotationBeanPostProcessor}
     *
     * @param packagesToScan packages to scan without resolving placeholders
     * @param registry       {@link BeanDefinitionRegistry}
     * @since 2.5.8
     */
    private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
        // 生成一个RootBeanDefinition,对应的beanClass为ServiceAnnotationBeanPostProcessor.class
        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
        // 将包路径作为在构造ServiceAnnotationBeanPostProcessor时调用构造方法时的传入参数
        builder.addConstructorArgValue(packagesToScan);
        builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
ServiceAnnotationBeanPostProcessor
  • 这个类名很奇怪, 第一次还以为是后置处理器, 结果发现这个类是没有实现BeanPostProcessor接口,因此,这个不是一个后置处理器;
  • 该类实现BeanDefinitionRegistryPostProcessor接口, 这个接口是Bean定义注册处理器, 就是用来注册BeanDefinition的;
  • 在Spring启动时, 会调用这个类的postProcessBeanDefinitionRegistry方法,扫描@Service注解所修饰的类,并作为一个Dubbo服务;
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
        ResourceLoaderAware, BeanClassLoaderAware {
     //1. 处理包名, 路径中如果有空格,就去掉;
     //2.  扫描包,进行Bean注册
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
        if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            // 扫描包,进行Bean注册
            registerServiceBeans(resolvedPackagesToScan, registry);
        } else {
            if (logger.isWarnEnabled()) {
                logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
            }
        }

    }
    private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
        Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
        for (String packageToScan : packagesToScan) {
            if (StringUtils.hasText(packageToScan)) {
                String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim());
                resolvedPackagesToScan.add(resolvedPackageToScan);
            }
        }
        return resolvedPackagesToScan;
    }
}   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
registerServiceBeans(resolvedPackagesToScan, registry)

工作:

  1. 创建一个DubboClassPathBeanDefinitionScanner实例, dubbo的路径扫描器;
  2. 创建一个Bean名称生成器;
  3. 扫描器设置要扫描的注解, 指定为Service.class,和com.alibaba.dubbo.config.annotation.Service.class, 后者为了兼容处理;
  4. 遍历扫描包路径集合;
    4.1 scanner.scan(packageToScan) 扫描Dubbo自定义的@Service注解, 并将扫描到的Dubbo服务转换为BeanDefinition实例注入容器;
    4.2 findServiceBeanDefinitionHolders查找路径下所有被@Service注解所修饰的类的BeanDefinition;
    4.3 遍历BeanDefinition
    4.4 生成一个ServiceBean实例,并注入容器;
	
    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));
        scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class));

        for (String packageToScan : packagesToScan) {

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

            // 查找被@Service注解的类的BeanDefinition(无论这个类有没有被@ComponentScan注解标注了)
            // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
            Set<BeanDefinitionHolder> beanDefinitionHolders =
                    findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);

            if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {

                // 扫描到BeanDefinition开始处理它
                for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
                    registerServiceBean(beanDefinitionHolder, registry, scanner);
                }
              	//...日志

            } else {
            //....日志
            }

        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
ClassPathBeanDefinitionScanner#doScan

这个内容是Spring的扫描注解的内容, 我大概知道其作用,内部源码和我想象的不一样;
工作:

  1. 创建返回结果beanDefinitions的Set集合
  2. 遍历包路径
  3. findCandidateComponents扫描候选的组件,返回一个BeanDefinition集合;
  4. 遍历返回的BeanDefinition集合;
  5. 将BeanDefinition转换为BeanDefinitionHolder实例, 然后registerBeanDefinition方法注入容器;
	protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
		for (String basePackage : basePackages) {
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator)

工作:

  1. 使用扫描器对包路径下的服务进行扫描,扫描到的Dubbo服务类都会转换为一个Bean Definition类 (是否重复了这个过程,上面就已经执行了一次,有点疑问)
  2. 创建一个Set集合存储结果
  3. 遍历 扫描的BeanDefinition类
  4. 转换为BeanDefinitionHolder类, 加入Set集合结果;
  5. 返回;
    private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders(
            ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
            BeanNameGenerator beanNameGenerator) {

        Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan);

        Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<>(beanDefinitions.size());

        for (BeanDefinition beanDefinition : beanDefinitions) {

            String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
            BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
            beanDefinitionHolders.add(beanDefinitionHolder);

        }

        return beanDefinitionHolders;

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
registerServiceBean(beanDefinitionHolder, registry, scanner)

工作:

  1. 获取BeanDefinitionHolder代表的Dubbo服务实现类;
  2. 获取@Service注解对象实例; (@Service(protocol , version …) 注解里面可以指定多个属性)
  3. 获取@Service注解对象实例的所有的属性值;
  4. 获取实现类实现的接口;
  5. 获取服务实现类的Bean名称;DemoServiceImpl类的bean名称为demoServiceImpl…
  6. 创建一个代表serviceBean的BeanDefinition实例;
  7. 获取一个ServiceBean的Bean名称, (以类名+组名+版本号为名称)
  8. 判断容器中是否已经存在,不存在就注入容器;

    private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
                                     DubboClassPathBeanDefinitionScanner scanner) {
        // 处理扫描到的每一个BeanDefinition
        // 1. 得到@Service注解上所配置的参数
        // 2. 根据每一个BeanDefinition会再额外的生成一个ServiceBean
        // 3. 对于每一个被@Service注解的类(服务的实现类),会生成两个Bean,一个服务实现类对应的Bean(普通Bean,和@Component一样),一个ServiceBean(Dubbo中要用到的Bean,因为在ServiceBean中包括了很的Config)

        // 具体的服务实现类
        Class<?> beanClass = resolveClass(beanDefinitionHolder);
        // @Service可以对服务进行各种配置
        Annotation service = findServiceAnnotation(beanClass);

        /**
         * The {@link AnnotationAttributes} of @Service annotation
         */
        AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);

        // 服务实现类对应的接口
        Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
        // 服务实现类对应的bean的名字,比如:demoServiceImpl
        String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();

        // 生成一个ServiceBean
        AbstractBeanDefinition serviceBeanDefinition =
                buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);

        // ServiceBean Bean name   ServiceBean表示服务,我们要使用一个服务应该拿ServiceBean
        String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);

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

            // 把ServiceBean注册进去,对应的beanName为ServiceBean:org.apache.dubbo.demo.DemoService
            registry.registerBeanDefinition(beanName, serviceBeanDefinition);
      		//...日志

        } else {
          //...日志
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
findServiceAnnotation(beanClass)

工作 :获取服务实现类Class上的@Service注解信息;

    private Annotation findServiceAnnotation(Class<?> beanClass) {
        Annotation service = findMergedAnnotation(beanClass, Service.class);
        if (service == null) {
            service = findMergedAnnotation(beanClass, com.alibaba.dubbo.config.annotation.Service.class);
        }
        return service;
    }
    public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
        if (!(element instanceof Class)) {
        	//关键: 获取Class的注解@Service
            A annotation = element.getAnnotation(annotationType);
            if (annotation != null) {
            	//返回
                return AnnotationUtils.synthesizeAnnotation(annotation, element);
            }
        }

        AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationType, false, false);
        return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName)

作用: 创建代表ServiceBean的BeanDefinition对象;
工作:

  1. 生成一个ServiceBean对应的BeanDefinition
  2. 获取ServiceBean的普通属性MutablePropertyValues (像String,Long…)
  3. 从@Service注解的配置值 赋值给ServiceBean的属性;
  4. 设置ref属性, ref属性 引用 Dubbo服务实现类实例;
    4.1 Spring的内容: Spring根据传入的Bean名称,从容器中拿到Bean,拿不到就进行创建, 然后返回, 然后ServiceBean的ref属性引用Bean实例;
  5. ServiceBean的属性"provider", “monitor”, “application”, “module”, “registry”, “protocol”,“interface”, “interfaceName”, "parameters"赋值,
    这些属性都不是普通属性, 而是类对象, 例如application对应得DubboApplicationConfig, protocol对应得ProtocolConfig依次类推,Spring中使用addPropertyValue进行赋值;
  6. 最终返回代表ServiceBean得BeanDefinition对象

    private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,
                                                              AnnotationAttributes serviceAnnotationAttributes,
                                                              Class<?> interfaceClass,
                                                              String annotatedServiceBeanName) {
        // 生成一个ServiceBean对应的BeanDefinition
        BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();

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

        // 把serviceAnnotation中的参数值赋值给ServiceBean的属性
        propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));

        // References "ref" property to annotated-@Service Bean
        // ref属性赋值为另外一个bean, 对应的就是被@Service注解的服务实现类对应的bean
        addPropertyReference(builder, "ref", annotatedServiceBeanName);
        // Set interface
        builder.addPropertyValue("interface", interfaceClass.getName());
        // Convert parameters into map
        builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters")));

        // 配置了methods属性,则给ServiceBean对应的methods属性赋值
        // Add methods parameters
        List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
        if (!methodConfigs.isEmpty()) {
            builder.addPropertyValue("methods", methodConfigs);
        }

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

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

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

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


        /**
         * Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference
         * 获取注解上配置的注册中心的beanName
         */
        String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry");

        List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);

        if (!registryRuntimeBeanReferences.isEmpty()) {
            builder.addPropertyValue("registries", registryRuntimeBeanReferences);
        }

        /**
         * Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference
         */
        String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol");

        List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);

        if (!protocolRuntimeBeanReferences.isEmpty()) {
            builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
        }

        return builder.getBeanDefinition();

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

ServiceBean

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
        ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware,
        ApplicationEventPublisherAware {
	//...省略部分代码

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 当前服务没有被导出并且没有卸载,才导出服务
        if (!isExported() && !isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + getInterface());
            }
            // 服务导出(服务注册)
            export();
        }
    }
}
public class ServiceConfig<T> extends AbstractServiceConfig {

    private static final long serialVersionUID = 3033787999037024738L;
    private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
    private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>();
    private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
    private final List<URL> urls = new ArrayList<URL>();
    private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();

    private String interfaceName;
    private Class<?> interfaceClass;
    private T ref;
    private String path;
    private List<MethodConfig> methods;
    private ProviderConfig provider;
    private String providerIds;
}
public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {

    private static final long serialVersionUID = 1L;

    protected String version;

    protected String group;

    protected Boolean deprecated = false;

    protected Integer delay;

    protected Boolean export;

    protected Integer weight;

    protected String document;

    protected Boolean dynamic = true;

    protected String token;

    protected String accesslog;

    protected List<ProtocolConfig> protocols;

    protected String protocolIds;

    private Integer executes;

    private Boolean register;

    private Integer warmup;

    private String serialization;
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 重要配置属性:
    ServiceBean表示一个Dubbo服务,它有一些参数,比如:
  1. ref,表示服务的具体实现类
  2. interface,表示服务的接口
  3. parameters,表示服务的参数(@Service注解中所配置的信息)
  4. application,表示服务所属的应用
  5. protocols,表示服务所使用的协议
  6. registries,表示服务所要注册的注册中心
  • ServiceBean本身实现了ApplicationListener监听器接口, 当Spring应用启动完后,Bean全部加载完毕, Dubbo的所有服务都会进行导出,例如注册到注册中心等操作;

结果

  1. Dubbo整合Spring过程中, 扫描@Service注解和所修饰的类时, 会生成代表服务实现类的BeanDefinition,并注入容器;
  2. 对于Dubbo来说此时得到的Bean是一个服务, 因此Dubbo需要解析@Service注解所包含的信息, 解析@Service注解后,会另外生成一个代表ServiceBean的BeanDefinition, 并注入容器;
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/165780
推荐阅读
相关标签
  

闽ICP备14008679号