本文解析的Dubbo源码的版本为2.7.9
1 与spring整合源码
1.1 注册Dubbo配置类
上图为Dubbo与Spring整合注册配置类的主要流程,下面我们一步步来分析。
Dubbo与Spring整合首先我们会在启动类上配置 @EnableDubbo注解,
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
@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;
}
该注解类上面有@EnableDubboConfig和@DubboComponentScan两个注解,@EnableDubboConfig注解的作用就是将Dubbo的一些配置类注册到Spring种,而@DubboComponentScan则是注册扫描@Service注解和@Reference注解的bean工厂后置处理器。
下面进入@EnableDubboConfig注解类
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {
boolean multiple() default true;
}
该注解类上使用了注解@Import,导入了DubboConfigConfigurationRegistrar类,该类实现了ImportBeanDefinitionRegistrar,所以会在启动的时候执行其registerBeanDefinitions。
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar, ApplicationContextAware {
private ConfigurableApplicationContext applicationContext;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
boolean multiple = attributes.getBoolean("multiple");
/**
* 注册DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple,
* 该类中配置了需要注册的配置类
* 及配置类的属性对应的值在配置文件种的前缀
*/
// Single Config Bindings
registerBeans(registry, DubboConfigConfiguration.Single.class);
if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
registerBeans(registry, DubboConfigConfiguration.Multiple.class);
}
// Since 2.7.6
registerCommonBeans(registry);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (!(applicationContext instanceof ConfigurableApplicationContext)) {
throw new IllegalArgumentException("The argument of ApplicationContext must be ConfigurableApplicationContext");
}
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
}
在registerBeanDefinitions方法中注册了DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple两个类。
注意在EnableDubboConfig注解中有一个属性multiple,默认是true,为true的时候才会注册DubboConfigConfiguration.Multiple类,这个类会解析复数形式的配置,即同一类型的配置类可能会注册多个。
dubbo.applications.p1.name=dubbo-server1
dubbo.applications.p2.name=dubbo-server2
如上配置会注册两个ApplicationConfig类到Spring容器中,beanName分别为p1和p2。
下面查看DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple源码
@EnableConfigurationBeanBindings({
@EnableConfigurationBeanBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.module", type = ModuleConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.metrics", type = MetricsConfig.class),
@EnableConfigurationBeanBinding(prefix = "dubbo.ssl", type = SslConfig.class)
})
public static class Single {
}
/**
* Multiple Dubbo {@link AbstractConfig Config} Bean Binding
*/
@EnableConfigurationBeanBindings({
@EnableConfigurationBeanBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true),
@EnableConfigurationBeanBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true)
})
public static class Multiple {
}
这两个类中都是空的,类上面都配置了@EnableConfigurationBeanBindings注解,注解里配置了Dubbo配置类的类型,以及该配置类对应的配置前缀。下面我们进入该注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigurationBeanBindingsRegister.class)
public @interface EnableConfigurationBeanBindings {
/**
* @return the array of {@link EnableConfigurationBeanBinding EnableConfigurationBeanBindings}
*/
EnableConfigurationBeanBinding[] value();
}
可以看到EnableConfigurationBeanBindings注解上又使用了@Import注解,导入了ConfigurationBeanBindingsRegister,我们看其registerBeanDefinitions方法
public class ConfigurationBeanBindingsRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private ConfigurableEnvironment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
/**
* 获取DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple类上的
* EnableConfigurationBeanBindings注解配置的属性
*/
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableConfigurationBeanBindings.class.getName()));
AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");
ConfigurationBeanBindingRegistrar registrar = new ConfigurationBeanBindingRegistrar();
registrar.setEnvironment(environment);
for (AnnotationAttributes element : annotationAttributes) {
/**
* 根据@EnableConfigurationBeanBindings注解配置的属性注册配置类
* 配置类中的属性的值来源于Spring的environment即我们在配置文件中配置的值
*/
registrar.registerConfigurationBeanDefinitions(element, registry);
}
}
@Override
public void setEnvironment(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
this.environment = (ConfigurableEnvironment) environment;
}
}
该方法中首先获取了DubboConfigConfiguration.Single和DubboConfigConfiguration.Multiple类上@EnableConfigurationBeanBindings注解配置的属性,根据配置的属性通过ConfigurationBeanBindingRegistrar 类来注册属性上配置的配置类,调用的是其registerConfigurationBeanDefinitions方法,ConfigurationBeanBindingRegistrar类主要方法如下
public class ConfigurationBeanBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
final static Class ENABLE_CONFIGURATION_BINDING_CLASS = EnableConfigurationBeanBinding.class;
private final static String ENABLE_CONFIGURATION_BINDING_CLASS_NAME = ENABLE_CONFIGURATION_BINDING_CLASS.getName();
public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {
/**
* 获取@EnableConfigurationBeanBindings注解中属性配置的前缀,比如dubbo.appliation
*/
String prefix = getRequiredAttribute(attributes, "prefix");
prefix = environment.resolvePlaceholders(prefix);
/**
* 获取@EnableConfigurationBeanBindings注解中配置的Dubbo配置类类型
* 比如ApplicationConfig.class
*/
Class<?> configClass = getRequiredAttribute(attributes, "type");
boolean multiple = getAttribute(attributes, "multiple", valueOf(DEFAULT_MULTIPLE));
boolean ignoreUnknownFields = getAttribute(attributes, "ignoreUnknownFields", valueOf(DEFAULT_IGNORE_UNKNOWN_FIELDS));
boolean ignoreInvalidFields = getAttribute(attributes, "ignoreInvalidFields", valueOf(DEFAULT_IGNORE_INVALID_FIELDS));
registerConfigurationBeans(prefix, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields, registry);
}
private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple,
boolean ignoreUnknownFields, boolean ignoreInvalidFields,
BeanDefinitionRegistry registry) {
/**
* 根据配置的前缀,获取配置文件中配置的属性值以key-value的形式存入map中
* 如配置的dubbo.application.name=dubbo-server,对应map中为name->dubbo-server
* 如果配置的为复数dubbo.applications.p1.name=dubbo-server1,对应map中p1.name->dubbo-server1
*/
Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(environment.getPropertySources(), environment, prefix);
/**
* 如果根据前缀在配置文件中获取到的map为空则直接返回,不注册前缀对应的配置类。
*/
if (CollectionUtils.isEmpty(configurationProperties)) {
if (log.isDebugEnabled()) {
log.debug("There is no property for binding to configuration class [" + configClass.getName()
+ "] within prefix [" + prefix + "]");
}
return;
}
/**
* 获取beanName,如果是配置单数的情况,则自动生成beanname
* 如果配置双数的情况,如dubbo.applications.p1.name,则p1则为beanName
*/
Set<String> beanNames = multiple ? resolveMultipleBeanNames(configurationProperties) :
singleton(resolveSingleBeanName(configurationProperties, configClass, registry));
/**
* 根据beanName注册配置类,配置复数形式,则同一配置类会注册多个bean
*/
for (String beanName : beanNames) {
registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields,
configurationProperties, registry);
}
/**
* 注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性
*/
registerConfigurationBindingBeanPostProcessor(registry);
}
private void registerConfigurationBean(String beanName, Class<?> configClass, boolean multiple,
boolean ignoreUnknownFields, boolean ignoreInvalidFields,
Map<String, Object> configurationProperties,
BeanDefinitionRegistry registry) {
/**
* 根据配置类类型创建一个BeanDefinition.
*/
BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
/**
* 给BeanDefinition设置source属性,这个值很重要,因为bean的后置处理其会处理所有的bean,
* ConfigurationBeanBindingPostProcessor这个bean的后置处理器,
* 就是通过这个属性来判断该类是dubbo的一个配置类,从而注入属性,过滤其它的bean。
*/
setSource(beanDefinition);
/**
* 获取配置类的属性配置
* 如果是单数形式,则直接返回configurationProperties
* 如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
*/
Map<String, Object> subProperties = resolveSubProperties(multiple, beanName, configurationProperties);
/**
* 给BeanDefinition设置属性,如subProperties
* 后置处理器ConfigurationBeanBindingPostProcessor会取从BeanDefinition中取得属性subProperties,给配置类实例赋值。
*/
initBeanMetadataAttributes(beanDefinition, subProperties, ignoreUnknownFields, ignoreInvalidFields);
registry.registerBeanDefinition(beanName, beanDefinition);
if (log.isInfoEnabled()) {
log.info("The configuration bean definition [name : " + beanName + ", content : " + beanDefinition
+ "] has been registered.");
}
}
/**
* 获取配置类的属性配置
* 如果是单数形式,则直接返回configurationProperties
* 如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
*/
private Map<String, Object> resolveSubProperties(boolean multiple, String beanName,
Map<String, Object> configurationProperties) {
if (!multiple) {
return configurationProperties;
}
MutablePropertySources propertySources = new MutablePropertySources();
propertySources.addLast(new MapPropertySource("_", configurationProperties));
return getSubProperties(propertySources, environment, normalizePrefix(beanName));
}
private void setSource(AbstractBeanDefinition beanDefinition) {
beanDefinition.setSource(ENABLE_CONFIGURATION_BINDING_CLASS);
}
/**
* 注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性
*/
private void registerConfigurationBindingBeanPostProcessor(BeanDefinitionRegistry registry) {
registerInfrastructureBean(registry, ConfigurationBeanBindingPostProcessor.BEAN_NAME,
ConfigurationBeanBindingPostProcessor.class);
}
}
首先看registerConfigurationBeanDefinitions方法,该方法就是获取@EnableConfigurationBeanBindings注解中属性配置,比如配置类类型等,然后调用registerConfigurationBeans方法。
registerConfigurationBeans:
1.根据配置的前缀,获取配置文件中配置的属性值以key-value的形式存入map中。如配置的dubbo.application.name=dubbo-server,对应map中为name->dubbo-server;如果配置的为复数dubbo.applications.p1.name=dubbo-server1,对应map中p1.name->dubbo-server1。
2.如果根据前缀在配置文件中获取到的map为空则直接返回,不注册前缀对应的配置类。
3.获取beanName,如果是配置单数的情况,则自动生成beanName,如果配置双数的情况,如dubbo.applications.p1.name,则p1则为beanName
4.根据beanName注册配置类,配置复数形式,则同一配置类会注册多个bean,即调用registerConfigurationBean方法。
5.注册一个bean的后置处理器ConfigurationBeanBindingPostProcessor,在初始化之前给配置类注入属性
registerConfigurationBean:
1.根据配置类类型创建一个BeanDefinition。
2.给BeanDefinition设置source属性,这个值很重要,因为bean的后置处理其会处理所有的bean,ConfigurationBeanBindingPostProcessor这个bean的后置处理器,就是通过这个属性来判断该类是dubbo的一个配置类,从而注入属性,过滤其它的bean。
3.获取配置类的属性配置如果是单数形式,则直接返回configurationProperties;如果是复数形式,configurationProperties中的key为p1.name,p2.name,需要根据beanName,将key转为name
4.给BeanDefinition设置属性,如subProperties,后置处理器ConfigurationBeanBindingPostProcessor会从BeanDefinition中取得属性subProperties,给配置类实例赋值。
5.注册BeanDefinition。
1.2 注册ServiceBean和ReferenceBean
上图是注册ServiceBean和ReferenceBean的主要流程,下面详细分析源码
ServiceBean和ReferenceBean的注册是通过EnableDubbo注解类上@DubboComponentScan注解来完成的,而@DubboComponentScan注解上又有@Import(DubboComponentScanRegistrar.class)注解,下面查看DubboComponentScanRegistrar类,spring启动会调用其registerBeanDefinitions方法
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
/**
* 获取@EnableDubbo注解上配置的扫描包的路径
* 如果未配置,则使用注解所修饰的配置类所在包路径。
*/
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
/**
* 注册bean工厂的后置处理器ServiceAnnotationBeanPostProcessor
* 该bean工厂的后置处理器的作用是扫描@Service注解所在类,注册到spring中
* 并注册一个对应的ServiceBean到spring中
*/
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
// @since 2.7.6 Register the common beans
registerCommonBeans(registry);
}
/**
* 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) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
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;
}
}
该类完成了3件事情:
1.获取扫描包的路径,如果@EnableDubbo注解上配置了扫描包的路径,则使用配置路径;如果未配置,则使用注解所修饰的配置类所在包路径。
2.注册了一个bean工厂的后置处理器ServiceAnnotationBeanPostProcessor,扫描@Service注解
3.注册了一个bean的后置处理器ReferenceAnnotationBeanPostProcessor,扫描@Reference。
1.2.1 ServiceAnnotationBeanPostProcessor 扫描@Service
ServiceAnnotationBeanPostProcessor类里什么也没做,主要逻辑是在其父类ServiceClassPostProcessor里完成的,该类是一个bean工厂的后置处理其,会执行其postProcessBeanDefinitionRegistry方法。
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
/**
* 注册DubboBootstrapApplicationListener这是一个ApplicationListener
* spring容器启动完成后会执行其onApplicationContextEvent方法
* 调用所有注册了的ServiceBean的exported方法,完成服务导出
*/
// @since 2.7.5
registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);
/**
* 获取传入的扫描包路径
*/
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
/**
* 注册@Service修饰的类到spring中,并注册对应的ServiceBean到spring中
*/
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
该方法中:
- 注册了一个ApplicationListener的实现DubboBootstrapApplicationListener,这个listener很重要,spring容器启动完成后会执行其onApplicationContextEvent方法,调用所有注册了的ServiceBean的exported方法,完成服务导出。
- 调用registerServiceBeans方法注册@Service修饰的类到spring中,并注册对应的ServiceBean到spring中。
下面我们进入registerServiceBeans方法
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
/**
* 创建一个扫描包的扫描器
*/
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
/**
* 获取一个beanName的生成器
*/
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
/**
* 添加扫描注解的filter
*/
// refactor @since 2.7.7
serviceAnnotationTypes.forEach(annotationType -> {
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
});
for (String packageToScan : packagesToScan) {
/**
* 将@Service注解的类注册的spring中
*/
// 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) {
/**
* 注册相应的ServiceBean到spring中
*/
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + "]");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
+ packageToScan + "]");
}
}
}
}
该方法中:
1.创建一个扫描包的扫描器DubboClassPathBeanDefinitionScanner,该类继承了ClassPathBeanDefinitionScanner,将useDefaultFilters设置为false,默认的过滤器是扫描@Component注解的,并设置了beanName生成器BeanNameGenerator,给扫描器添加了扫描@Service注解的AnnotationTypeFilter过滤器。
2.调用DubboClassPathBeanDefinitionScanner的scan方法将@Service所在类注册到Spring容器,改方法为Spring逻辑这里不做深究。
3.获取到DubboClassPathBeanDefinitionScanner注册的所有BeanDefinition,调用registerServiceBean注册ServiceBean。
registerServiceBean方法如下:
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Annotation service = findServiceAnnotation(beanClass);
/**
* 获取@Service注解的所有属性
*/
AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
/**
* 获取服务的接口
*/
Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
/**
* 服务实现类的beanName
*/
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
/**
* 创建ServiceBean的BeanDefinition
*/
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);
/**
* 根据InterfaceClass、group、version生成ServiceBean的beanName
*/
// ServiceBean Bean name
String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.info("The BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean has been registered with name : " + beanName);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean[ bean name : " + beanName +
"] was be found , Did @DubboComponentScan scan to same package in many times?");
}
}
}
该方法中:
- 首先获取@Service注解的所有属性
- 创建ServiceBean的BeanDefinition
- 根据InterfaceClass、group、version生成ServiceBean的beanName,并注册ServiceBean到Spring容器中。
注意:在ServiceBean的顶层父类中有AbstractConfig中,有一个
addIntoConfigManager方法上添加了注解@PostConstruct,所以该方法会在Bean的初始化时调用
@PostConstruct
public void addIntoConfigManager() {
ApplicationModel.getConfigManager().addConfig(this);
}
该方法通过dubbo得SPI获得一个单例的ConfigManager,将ServiceBean的实例添加到configsCache中。
1.2.1.1 DubboBootstrapApplicationListener 服务导出
Spring容器启动后会调用其onApplicationContextEvent方法,该方法中调用了onContextRefreshedEvent方法
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
dubboBootstrap.start();
}
服务导出就是在DubboBootstrap 类的start方法中完成的,start方法调用了exportServices方法
private void exportServices() {
/**
* 遍历configsCache中所有的ServiceBean实例
* 执行其exported方法
*/
configManager.getServices().forEach(sc -> {
// TODO, compatible with ServiceConfig.export()
ServiceConfig serviceConfig = (ServiceConfig) sc;
serviceConfig.setBootstrap(this);
if (exportAsync) {
ExecutorService executor = executorRepository.getServiceExporterExecutor();
Future<?> future = executor.submit(() -> {
sc.export();
exportedServices.add(sc);
});
asyncExportingFutures.add(future);
} else {
sc.export();
exportedServices.add(sc);
}
});
}
该方法中通过ConfigManager的getServices获取到所有的ServiceBean实例,最终就是从configsCache中拿到的实例,而通过上面的分析我们知道,在ServiceBean的初始化时会将实例放入单例的ConfigManager的configsCache中。
1.2.2 ReferenceAnnotationBeanPostProcessor 扫描@Reference
ReferenceAnnotationBeanPostProcessor 继承了AbstractAnnotationBeanPostProcessor类,该类属于InstantiationAwareBeanPostProcessor,在spring的bean属性注入populate方法中会调用其postProcessPropertyValues方法
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
/**
* 扫描bean中被@Reference修饰的属性和方法,得到AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata对象
* 每个被@Reference修饰得属性和方法都会被封装为AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement或AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement对象
*/
InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
try {
/**
* 调用AnnotatedFieldElement或AnnotatedMethodElement的inject方法,完成ReferenceBean的生成和代理对象的注入。
*/
metadata.inject(bean, beanName, pvs);
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
+ " dependencies is failed", ex);
}
return pvs;
}
该放发中:
- 扫描bean中被@Reference修饰的属性和方法,得到AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata对象,每个被@Reference修饰得属性和方法都会被封装为AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement或AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement对象。
- 调用AnnotatedFieldElement或AnnotatedMethodElement的inject方法,完成ReferenceBean的生成和代理对象的注入。
AnnotatedFieldElement方法的inject方法如下:
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Class<?> injectedType = resolveInjectedType(bean, field);
/**
* 获取到依赖注入的代理对象
*/
Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(field);
/**
* 反射给注入属性值
*/
field.set(bean, injectedObject);
}
AnnotatedMethodElement方法的inject方法如下:
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Class<?> injectedType = pd.getPropertyType();
/**
* 获取到依赖注入的代理对象
*/
Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(method);
/**
* 反射调用方法
*/
method.invoke(bean, injectedObject);
}
由上面看出获取到注入的代理对象,都是通过getInjectedObject方法获取的。
protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
/**
* 从缓存中injectedObjectsCache中获取代理对象
* 如果被引入过,就会存到injectedObjectsCache缓存中
*/
Object injectedObject = injectedObjectsCache.get(cacheKey);
if (injectedObject == null) {
injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
// Customized inject-object if necessary
injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
}
return injectedObject;
}
该方法中首先会从缓存injectedObjectsCache中,拿代理对象,如果为null再调用doGetInjectedBean方法获取代理对象,最后存到缓存中。
下面进入doGetInjectedBean,该方法属于ReferenceAnnotationBeanPostProcessor,生成ReferenceBean和注册,就是在该方法中完成的。
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
/**
* 通过接口类型和注解的group、version得到对应得ServiceBean在spring中得beanName
*/
String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
/**
* 根据接口类型和@Reference注解中的属性,生成一个ReferenceBean在spring中的beanName
*/
String referenceBeanName = getReferenceBeanName(attributes, injectedType);
/**
* 根据referenceBeanName从referenceBeanCache中拿ReferenceBean
* 如果不存在则创建,并放入referenceBeanCache中
*/
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
/**
* 判断服务是否是本地服务
*/
boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
/**
* 如果是本地服务,判断是否导出,若未导出,则执行ServiceBean的exported方法导出服务
*/
prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);
/**
* 如果是本地服务,则给本地服务的实现类注册一个别名,别名为referencedBeanName
* 这样就和引用关联上
* 如果是远程服务,则将ReferenceBean注册到Spring容器中
*/
registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
/**
* 缓存注入的ReferenceBean
*/
cacheInjectedReferenceBean(referenceBean, injectedElement);
return referenceBean.get();
}
该方法的每一步在代码中都有注释,此处不作解释,注意最后调用的referenceBean.get(),实际是调用的ReferenceConfig的get方法获取到的代理对象。