在第一篇文章中、我们可以看到
@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 中。
剩下的流程放置到下一篇文章中