在第一篇文章中、我们可以看到
@DubboService(version = "1.0.0") public class DefaultDemoService implements DemoService { /** * The default value of ${dubbo.application.name} is ${spring.application.name} */ @Value("${dubbo.application.name}") private String serviceName; public String sayHello(String name) { return String.format("[%s] : Hello, %s", serviceName, name); } } 复制代码
@EnableDubbo @SpringBootApplication public class DubboProviderDemo { public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(DubboProviderDemo.class, args); System.out.println(); } } 复制代码
只要使用 DubboReferenc 注解就可以将该接口暴露到服务注册中心上面
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig @DubboComponentScan public @interface EnableDubbo { .............. ....... 复制代码
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(DubboComponentScanRegistrar.class) public @interface DubboComponentScan { 复制代码
我们看一下 DubboComponentScanRegistrar
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); registerServiceAnnotationBeanPostProcessor(packagesToScan, registry); // @since 2.7.6 Register the common beans registerCommonBeans(registry); } 复制代码
registerServiceAnnotationBeanPostProcessor 注册一个 BeanPostProcessor
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); } 复制代码
registerCommonBeans 注册一些其他需要用的 Bean。其中 ReferenceAnnotationBeanPostProcessor 就是服务消费方的关键 bean
static void registerCommonBeans(BeanDefinitionRegistry registry) { // Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); // Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093 registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class); // Since 2.7.5 Register DubboLifecycleComponentApplicationListener as an infrastructure Bean registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME, DubboLifecycleComponentApplicationListener.class); // Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class); // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME, DubboConfigDefaultPropertyValueBeanPostProcessor.class); } 复制代码
那么对于服务提供者、ServiceAnnotationBeanPostProcessor 就是服务注册的入口了。
xml 配置文件请看 DubboNamespaceHandler
这个类看起来啥屁事都没做
public class ServiceAnnotationBeanPostProcessor extends ServiceClassPostProcessor { public ServiceAnnotationBeanPostProcessor(String... packagesToScan) { this(Arrays.asList(packagesToScan)); } public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) { this(new LinkedHashSet<>(packagesToScan)); } public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) { super(packagesToScan); } } 复制代码
直接去它的父类 ServiceClassPostProcessor
public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware, ResourceLoaderAware, BeanClassLoaderAware { 复制代码
发现其继承了不少接口、其中 BeanDefinitionRegistryPostProcessor 为 Spring 注册完 Spring BeanDefinition 之后的回调接口
直接看它实现的方法
@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // @since 2.7.5 registerBeans(registry, DubboBootstrapApplicationListener.class); Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { registerServiceBeans(resolvedPackagesToScan, registry); } } } 复制代码
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) { DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader); BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry); scanner.setBeanNameGenerator(beanNameGenerator); // refactor @since 2.7.7 serviceAnnotationTypes.forEach(annotationType -> { scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType)); }); 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); } } .......... } 复制代码
registerBeans(registry, DubboBootstrapApplicationListener.class);
这里会注册一个 Spring 事件监听、对于后续注册服务到注册中心起着触发的作用
上面代码的大意就是扫描路径下、在类上有下面三个注解的类
private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList( DubboService.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class ); 复制代码
registerServiceBean 关键点在这里
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner) { Class<?> beanClass = resolveClass(beanDefinitionHolder); Annotation service = findServiceAnnotation(beanClass); AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false); Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass); String annotatedServiceBeanName = beanDefinitionHolder.getBeanName(); AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName); // ServiceBean Bean name String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass); if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean // 注册到 Spring registry.registerBeanDefinition(beanName, serviceBeanDefinition); } } 复制代码
private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation, AnnotationAttributes serviceAnnotationAttributes, Class<?> interfaceClass, String annotatedServiceBeanName) { 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"); propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames)); // References "ref" property to annotated-@Service Bean addPropertyReference(builder, "ref", annotatedServiceBeanName); // Set interface builder.addPropertyValue("interface", interfaceClass.getName()); // Convert parameters into map builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters"))); // Add methods parameters List<MethodConfig> methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods")); if (!methodConfigs.isEmpty()) { builder.addPropertyValue("methods", methodConfigs); } ........... } 复制代码
ServiceBean 这个 bean 就是 Dubbo 服务提供者的关键。
我们为每个声明了 Dubbo 注解的 bean 再额外注册了一个 ServiceBean 、并且会将这个 bean 赋值到 ServiceBean 的 ref 变量中
addPropertyReference(builder, "ref", annotatedServiceBeanName); 复制代码
BeanDefinitionValueResolver
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } 复制代码
@Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; Class<?> beanType = ref.getBeanType(); ........ else { String resolvedName; ........ else { resolvedName = String.valueOf(doEvaluate(ref.getBeanName())); bean = this.beanFactory.getBean(resolvedName); } this.beanFactory.registerDependentBean(resolvedName, this.beanName); } if (bean instanceof NullBean) { bean = null; } return bean; } catch (BeansException ex) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex); } } 复制代码
在填充该 ServiceBean 的时候会将对应的那个声明了注解的 bean 设置到 ServiceBean 中。
剩下的流程放置到下一篇文章中