@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<String> 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容器中。
下面会详细介绍ServiceClassPostProcessor、ReferenceAnnotationBeanPostProcessor和DubboBootstrapApplicationListener的作用。
该类的主要作用是将@DubboService和@org.apache.dubbo.config.annotation.Service注释的类注册到Spring容器中。

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
private final static List<Class<? extends Annotation>> 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<String> 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(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);
}
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容器中。
private 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);
/**
* The {@link AnnotationAttributes} of @Service annotation
*/
//从注解从读取属性值,用于后续构建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<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
*/
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();
}
Dubbo服务的定义类,用于封装Dubbo服务的参数,如group、version、interfaceClass,服务类对象实例等,我们可以通过自定义ServiceBean来自定义需要发布的Dubbo服务,如:
@Bean
public ServiceBean<DubboMappingService> dubboDefinitionServiceBean(DubboMappingService dubboDefinitionService){
ServiceBean<DubboMappingService> 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类图

@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()中被调用。
自动注入@DubboReference和@org.apache.dubbo.config.annotation.Reference注解注释的属性

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);
}
}
接口实现代码:
@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;
}
扫描所有@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;
}
在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);
}
@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
/**
* The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
*/
String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
/**
* The name of bean that is declared by {@link Reference @Reference} annotation injection
*/
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也继承自AbstractConfig,同样会通过addIntoConfigManager()方法将自身注册导ConfigManager中,以便在DubboBootstrap调用referenceConfig.get()方法;
实现了ApplicationListener接口,监听ContextRefreshedEvent和ContextClosedEvent事件;
public DubboBootstrapApplicationListener() {
this.dubboBootstrap = DubboBootstrap.getInstance();
}
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
dubboBootstrap.start();
}
private void onContextClosedEvent(ContextClosedEvent event) {
dubboBootstrap.stop();
}
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!");
}
}
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;
}
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();
}
}
}