@ConditionalOnProperty(
prefix = "dubbo",
name = {"enabled"},
matchIfMissing = true
)
@Configuration
@AutoConfigureAfter({DubboRelaxedBindingAutoConfiguration.class})
@EnableConfigurationProperties({DubboConfigurationProperties.class})
@EnableDubboConfig
public class DubboAutoConfiguration implements ApplicationContextAware, BeanDefinitionRegistryPostProcessor {
public DubboAutoConfiguration() {
}
@ConditionalOnProperty(
prefix = "dubbo.scan.",
name = {"base-packages"}
)
@ConditionalOnBean(
name = {"dubbo-service-class-base-packages"}
)
@Bean
public ServiceClassPostProcessor serviceClassPostProcessor(@Qualifier("dubbo-service-class-base-packages") Set packagesToScan) {
return new ServiceClassPostProcessor(packagesToScan);
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof ConfigurableApplicationContext) {
ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;
DubboLifecycleComponentApplicationListener dubboLifecycleComponentApplicationListener = new DubboLifecycleComponentApplicationListener();
dubboLifecycleComponentApplicationListener.setApplicationContext(applicationContext);
context.addApplicationListener(dubboLifecycleComponentApplicationListener);
DubboBootstrapApplicationListener dubboBootstrapApplicationListener = new DubboBootstrapApplicationListener();
dubboBootstrapApplicationListener.setApplicationContext(applicationContext);
context.addApplicationListener(dubboBootstrapApplicationListener);
}
}
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.removeBeanDefinition(registry, "dubboLifecycleComponentApplicationListener");
this.removeBeanDefinition(registry, "dubboBootstrapApplicationListener");
}
private void removeBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
if (registry.containsBeanDefinition(beanName)) {
registry.removeBeanDefinition(beanName);
}
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
这是dubbo-spring-boot-starter.jar中主要的启动配置类,该类直接通过@Bean注册ServiceClassPostProcessor到Spring容器中,并通过**@EnableDubboConfig引入DubboConfigConfigurationRegistrar**,注册ReferenceAnnotationBeanPostProcessor、DubboConfigAliasPostProcessor、DubboLifecycleComponentApplicationListener、DubboBootstrapApplicationListener和DubboConfigDefaultPropertyValueBeanPostProcessor到Spring容器中。
- DubboConfigDefaultPropertyValueBeanPostProcessor:用来填充AbstarctConfig.id和AbstarctConfig.name的默认值
- DubboConfigAliasPostProcessor:用来注册beanName和AbstarctConfig.id的别名
- DubboLifecycleComponentApplicationListener:用来从Spring容器中获取所有实现了org.apache.dubbo.common.context.LifeCycle接口的Bean,并执行他们的start()方法;
- ServiceClassPostProcessor:扫描所有@DubboService注解的类,构建成ServiceBean注册到Srping容器中;
- ReferenceAnnotationBeanPostProcessor:扫描Bean中所有@DubboReference注解的属性,通过ReferenceBean构建远程服务的实例,注入到相应的依赖中;
- DubboBootstrapApplicationListener:监听ContextRefreshedEvent和ContextClosedEvent事件,相应的执行DubboBootstrap的start()和stop()方法;
下面会详细介绍ServiceClassPostProcessor、ReferenceAnnotationBeanPostProcessor和DubboBootstrapApplicationListener的作用。
二、ServiceClassPostProcessor该类的主要作用是将@DubboService和@org.apache.dubbo.config.annotation.Service注释的类注册到Spring容器中。
1、UML类图:
EnvironmentAware,ResourceLoaderAware,BeanClassLoaderAware全部继承自Aware接口,用于set对应的bean到对象中。
BeanDefinitionRegistryPostProcessor:可以通过此接口传入的BeanDefinitionRegistry注册Bean到Spring容器中,或判断Spring容器是否存在某个Bean,或从Spring容器中删除某个bean;
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
关于BeanDefinitionRegistryPostProcessor详细的介绍可以参考:https://blog.csdn.net/ztchun/article/details/90814135
2、 支持的注解:DubboService、org.apache.dubbo.config.annotation.Service,com.alibaba.dubbo.config.annotation.Serviceprivate final static List3、方法:postProcessBeanDefinitionRegistry> serviceAnnotationTypes = asList( // @since 2.7.7 Add the @DubboService , the issue : https://github.com/apache/dubbo/issues/6007 DubboService.class, // @since 2.7.0 the substitute @com.alibaba.dubbo.config.annotation.Service Service.class, // @since 2.7.3 Add the compatibility for legacy Dubbo's @Service , the issue : https://github.com/apache/dubbo/issues/4330 com.alibaba.dubbo.config.annotation.Service.class );
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// @since 2.7.5
//这里重复注册了一次DubboBootstrapApplicationListener
registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);
Set resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
此方法实现自接口BeanDefinitionRegistryPostProcessor:
该方法首先注册DubboBootstrapApplicationListener到Spring容器,DubboBootstrapApplicationListener用来监听ContextRefreshedEvent,Spring Context刷新完成后,调用DubboBootstrap.start()方法,启动Dubbo服务;
然后解析要扫描的报列表,从${dubbo.scan.base-packages}配置项读取扫描列表,如果扫描列表不为空,则调用registerServiceBeans方法;
private void registerServiceBeans(SetpackagesToScan, 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 beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator); if (!CollectionUtils.isEmpty(beanDefinitionHolders)) { for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) { 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 + "]"); } } } }
使用DubboClassPathBeanDefinitionScanner扫描所有的DubboService类,然后遍历扫描结果,调用registerServiceBean方法,注册bean到Spring容器中。
5、方法:registerServiceBeanprivate void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
//从BeanDefinitionHolder解析出beanClass;
Class> beanClass = resolveClass(beanDefinitionHolder);
//按顺序从beanClass获取@DubboService、@org.apache.dubbo.config.annotation.Service或@com.alibaba.dubbo.config.annotation.Service注解
Annotation service = findServiceAnnotation(beanClass);
//从注解从读取属性值,用于后续构建Dubbo Service Bean时的参数;
AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
//获取DubboService的接口类,如果注解中指定了接口类,则使用注解中指定的类(解析顺序interfaceClass->interfaceName),否则使用服务类实现的接口中的第一个。如果找不到接口类,则抛出异常;
Class> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
//构建ServiceBean
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
//使用ServiceBeanNameBuilder生成beanName
String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
//检查是否可以注册到容器中
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
//注册ServiceBean到容器中
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?");
}
}
}
6、方法:buildServiceBeanDefinition
private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,
AnnotationAttributes serviceAnnotationAttributes,
Class> interfaceClass,
String annotatedServiceBeanName) {
//创建 ServiceBean BeanDefinitionBuilder
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");
//从Annotation读取属性并设置到MutablePropertyValues中,比如group,version
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 methodConfigs = convertMethodConfigs(serviceAnnotationAttributes.get("methods"));
if (!methodConfigs.isEmpty()) {
builder.addPropertyValue("methods", methodConfigs);
}
String providerConfigBeanName = serviceAnnotationAttributes.getString("provider");
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
String monitorConfigBeanName = serviceAnnotationAttributes.getString("monitor");
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
String applicationConfigBeanName = serviceAnnotationAttributes.getString("application");
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
String moduleConfigBeanName = serviceAnnotationAttributes.getString("module");
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry");
List registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
}
String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol");
List protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!protocolRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
return builder.getBeanDefinition();
}
三、 ServiceBean
Dubbo服务的定义类,用于封装Dubbo服务的参数,如group、version、interfaceClass,服务类对象实例等,我们可以通过自定义ServiceBean来自定义需要发布的Dubbo服务,如:
@Bean public ServiceBeandubboDefinitionServiceBean(DubboMappingService dubboDefinitionService){ ServiceBean serviceBean = new ServiceBean<>(); serviceBean.setVersion(CommonServiceVersion.DUBBO_DEFINITION_SERVICE);//版本 serviceBean.setGroup(this.applicationName);//将Dubbo服务的group设置为application Name serviceBean.setRef(dubboDefinitionService);//实现类对象实例 serviceBean.setInterface(DubboMappingService.class);//接口类 return serviceBean; }
需要重点关注的方法:export()和addIntoConfigManager(),后面会详细介绍
1、UML类图

- ServiceConfig:用于Dubbo服务暴漏
- **InitializingBean **, 主要是用到了他的afterPropertiesSet方法,在对象实例化完毕后,调用该方法,做一些值的初始化
- **DisposableBean **, 主要用到他的destroy() 方法, 在spring容器showdown的时候调用。
- ApplicationContextAware, 为了得到applicationContext
- ApplicationEventPublisherAware, 用于发布ServiceBeanExportedEvent,DubboMetadataAutoConfiguration中会监听此事件,发布RestMetadata;
- **BeanNameAware **, 用于设置Bean的名称
@PostConstruct
public void addIntoConfigManager() {
ApplicationModel.getConfigManager().addConfig(this);
}
@PostConstruct:java原生注解,用于在执行构造函数后,init()前执行的方法,在Spring框架中@PostConstruct执行顺序:
Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
addIntoConfigManager():用于将ServiceBean注册到Dubbo的ConfigManager中,用于后续在DubboBootstrap.start()方法中暴露到注册中心。
public synchronized void export() {
if (!shouldExport()) {
return;
}
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
bootstrap.initialize();
}
checkAndUpdateSubConfigs();
//init serviceMetadata
serviceMetadata.setVersion(getVersion());
serviceMetadata.setGroup(getGroup());
serviceMetadata.setDefaultGroup(getGroup());
serviceMetadata.setServiceType(getInterfaceClass());
serviceMetadata.setServiceInterfaceName(getInterface());
serviceMetadata.setTarget(getRef());
if (shouldDelay()) {
DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
} else {
doExport();
}
exported();
}
用户暴露服务到注册中心,该方法在DubboBootstrap.exportServices()中被调用。
三、 ReferenceAnnotationBeanPostProcessor自动注入@DubboReference和@org.apache.dubbo.config.annotation.Reference注解注释的属性
1、UML类图:
PriorityOrdered: 继承自Ordered接口,Spring OrderComparator会有限使用此接口的值进行对比排序;
BeanFactoryAware:设置BeanFactory
BeanClassLoaderAware:设置ClassLoader
EnvironmentAware:设置Environment
ApplicationContextAware:设置ApplicationContext
DisposableBean:主要用到他的destroy() 方法, 在spring容器showdown的时候调用。
MergedBeanDefinitionPostProcessor:依赖注入检查。
InstantiationAwareBeanPostProcessorAdapter:实现了postProcessPropertyValues接口,用于注入依赖;
实现自接口MergedBeanDefinitionPostProcessor,在AbstractAutowireCapableBeanFactory中调用:
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
接口实现代码:
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
if (beanType != null) {
InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
3、postProcessPropertyValues
接口实现代码:
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
try {
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;
}
4、findInjectionMetadata
扫描所有@DubboReference和@org.apache.dubbo.config.annotation.Reference注释的Field,生成
private InjectionMetadata findInjectionMetadata(String beanName, Class> clazz, PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
try {
//扫描calzz中所有@DubboReference和@org.apache.dubbo.config.annotation.Reference注释的属性,并构建AnnotatedFieldElement
metadata = buildAnnotatedMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
} catch (NoClassDefFoundError err) {
throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
"] for annotation metadata: could not find class that it depends on", err);
}
}
}
}
return metadata;
}
5、AnnotatedFieldElement.inject:继承自InjectionMetadata.InjectedElement
在InstantiationAwareBeanPostProcessor.postProcessPropertyValues方法中被调用,调用Field.set方法,注入依赖
@Override
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Class> injectedType = resolveInjectedType(bean, field);
//获取要注入的对象,先从缓存中取,如果取不到,调用doGetInjectedBean方法构建;
Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(field);
field.set(bean, injectedObject);
}
6、doGetInjectedBean
@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
String referenceBeanName = getReferenceBeanName(attributes, injectedType);
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);
registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
cacheInjectedReferenceBean(referenceBean, injectedElement);
return referenceBean.get();
}
构建ReferenceBean,继承自ReferenceConfig,我们常用ReferenceConfig进行Dubbo服务的泛化调用;
四、 ReferenceBean 1、UML类图
ReferenceBean也继承自AbstractConfig,同样会通过addIntoConfigManager()方法将自身注册导ConfigManager中,以便在DubboBootstrap调用referenceConfig.get()方法;
实现了ApplicationListener接口,监听ContextRefreshedEvent和ContextClosedEvent事件;
1、构建方法:public DubboBootstrapApplicationListener() {
this.dubboBootstrap = DubboBootstrap.getInstance();
}
2、onContextRefreshedEvent
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
dubboBootstrap.start();
}
3、onContextClosedEvent
private void onContextClosedEvent(ContextClosedEvent event) {
dubboBootstrap.stop();
}
六、DubboBootstrap:Dubbo的核心类,单例模式
1、initialize:初始化dubbo的环境配置,
public void initialize() {
if (!initialized.compareAndSet(false, true)) {
确保只执行一次
return;
}
ApplicationModel.initFrameworkExts();
startConfigCenter();
loadRemoteConfigs();
checkGlobalConfigs();
// @since 2.7.8
startMetadataCenter();
initMetadataService();
initMetadataServiceExports();
initEventListener();
if (logger.isInfoEnabled()) {
logger.info(NAME + " has been initialized!");
}
}
2、start:dubbo服务启动,主要从ConfigManager中获取ServiceConfig和ReferenceConfig,暴漏自身服务,并解析远程服务;
public DubboBootstrap start() {
if (started.compareAndSet(false, true)) {
ready.set(false);
initialize();
if (logger.isInfoEnabled()) {
logger.info(NAME + " is starting...");
}
// 1. export Dubbo Services
exportServices();
// Not only provider register
if (!isOnlyRegisterProvider() || hasExportedServices()) {
// 2. export MetadataService
exportMetadataService();
//3. Register the local ServiceInstance if required
registerServiceInstance();
}
// reference dubbo remote service
referServices();
if (asyncExportingFutures.size() > 0) {
new Thread(() -> {
try {
this.awaitFinish();
} catch (Exception e) {
logger.warn(NAME + " exportAsync occurred an exception.");
}
ready.set(true);
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
}).start();
} else {
ready.set(true);
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
}
if (logger.isInfoEnabled()) {
logger.info(NAME + " has started.");
}
}
return this;
}
3、stop: Dubbo停止服务,调用destroy()方法,销毁相关实例。
public void destroy() {
if (destroyLock.tryLock()) {
try {
DubboShutdownHook.destroyAll();
if (started.compareAndSet(true, false)
&& destroyed.compareAndSet(false, true)) {
unregisterServiceInstance();
unexportMetadataService();
unexportServices();
unreferServices();
destroyRegistries();
DubboShutdownHook.destroyProtocols();
destroyServiceDiscoveries();
clear();
shutdown();
release();
}
} finally {
destroyLock.unlock();
}
}
}



