Spring与Dubbo整合源码分析-P1
前言
根据之前的SpringBoot
整合Dubbo
的demo
可知,当编写完测试接口及其实现后,最后一步是要在启动类上加上@EnableDubbo
,这样就可以启动Dubbo
相关服务了,那么是如何实现的呢?
问题
SpringBoot
启动类上加上@EnableDubbo
,这样就可以启动Dubbo
相关服务了,原理是什么?
EnableDubbo注解解析
点开EnableDubbo
注解,如下所示:
可以看到其定义中还有三个Dubbo
相关的注解,分别为EnableDubboConfig
、DubboComponentScan
和三个注解。我们知道,Java
中的注解定义中如果有其他注解,那么这个注解其实就是一个复合注解,复合注解同时具备这个注解定义中的所有注解的功能(具体可以参考Java注解)。由于这部分涉及的接口太多,所以拆成两个部分来说。本章先说EnableDubboConfig
注解的作用。
EnableDubboConfig
可以看到EnableDubboConfig
的定义中使用了@Import
注解引入了DubboConfigConfigurationRegistrar
类。DubboConfigConfigurationRegistrar
实现了ImportBeanDefinitionRegistrar
接口,这样就可以向Spring
启动时,通过registerBeanDefinitions
方法向Spring
容器中注册beanDefinition
,如下所示:
DubboConfigConfigurationRegistrar
DubboConfigConfigurationRegistrar
类中主要方法和注释如下:
public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar, ApplicationContextAware {
private ConfigurableApplicationContext applicationContext;
/**
* 根据导入@Configuration类的给定注释元数据,根据需要向beanDefinitionMap中添加beanDefinition
* @param importingClassMetadata 导入类的注解元数据
* @param registry beanDefinition注册器
* @return void
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取EnableDubboConfig注解里的键值对,这里主要获取的是multiple的值,默认为true
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
// 获取multiple属性值
boolean multiple = attributes.getBoolean("multiple");
// ============重点===========================
// 向Spring容器中注册DubboConfigConfiguration.Single
registerBeans(registry, DubboConfigConfiguration.Single.class);
// 向Spring容器中注册DubboConfigConfiguration.Multiple
if (multiple) { // Since 2.6.6 https://github.com/apache/dubbo/issues/3193
registerBeans(registry, DubboConfigConfiguration.Multiple.class);
}
// Since 2.7.6
// 注册公共组件,5个
// ReferenceAnnotationBeanPostProcessor,
// DubboConfigAliasPostProcessor,
// DubboLifecycleComponentApplicationListener,
// DubboBootstrapApplicationListener,
// DubboConfigDefaultPropertyValueBeanPostProcessor
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;
}
}
com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils#registerBeans
方法
/**
* 向Spring中的beanDefinitionMap注册beanDefinition
*
* @param registry {@link BeanDefinitionRegistry}
* @param annotatedClasses {@link Annotation annotation} class
*/
public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {
if (ObjectUtils.isEmpty(annotatedClasses)) {
return;
}
Set<Class<?>> classesToRegister = new LinkedHashSet<Class<?>>(asList(annotatedClasses));
Iterator<Class<?>> iterator = classesToRegister.iterator();
while (iterator.hasNext()) {
Class<?> annotatedClass = iterator.next();
// 移除已经注册过的bean,防止重复注册
if (isPresentBean(registry, annotatedClass)) {
iterator.remove();
}
}
// 构建AnnotatedBeanDefinitionReader
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
if (logger.isDebugEnabled()) {
logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
}
// 注册beanDefinition
reader.register(classesToRegister.toArray(EMPTY_CLASS_ARRAY));
}
org.apache.dubbo.config.spring.util.DubboBeanUtils#registerCommonBeans
方法,注册公共组件
/**
* Register the common beans
*
* @param registry {@link BeanDefinitionRegistry}
* @see ReferenceAnnotationBeanPostProcessor
* @see DubboConfigDefaultPropertyValueBeanPostProcessor
* @see DubboConfigAliasPostProcessor
* @see DubboLifecycleComponentApplicationListener
* @see DubboBootstrapApplicationListener
*/
public static void registerCommonBeans(BeanDefinitionRegistry registry) {
// Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
// 从 2.5.7版本开始注册@Reference注解的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.9 Register DubboApplicationListenerRegister as an infrastructure Bean
// https://github.com/apache/dubbo/issues/6559
// 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);
// 从 2.7.9版本开始添加DubboApplicationListenerRegister,作为基础组件 https:github.comapachedubboissues6559
// 从 2.7.5版本开始添加DubboLifecycleComponentApplicationListener,作为基础组件 registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME, DubboLifecycleComponentApplicationListener.class);
// 从 2.7.4版本开始添加DubboBootstrapApplicationListener,作为基础组件 registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);
registerInfrastructureBean(registry, DubboApplicationListenerRegistrar.BEAN_NAME,
DubboApplicationListenerRegistrar.class);
// Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
// 从 2.7.6版本开始添加DubboConfigDefaultPropertyValueBeanPostProcessor,作为基础组件
registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
DubboConfigDefaultPropertyValueBeanPostProcessor.class);
// Since 2.7.15 Register DubboConfigEarlyRegistrationPostProcessor as an infrastructure Bean
// 从 2.7.6版本开始添加DubboConfigEarlyRegistrationPostProcessor,作为基础组件
registerInfrastructureBean(registry, DubboConfigEarlyRegistrationPostProcessor.BEAN_NAME,
DubboConfigEarlyRegistrationPostProcessor.class);
}
com.alibaba.spring.util.BeanRegistrar#registerInfrastructureBean
方法,注册基础组件
/**
* 向Spring容器中注册beanDefinition
* @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
* @param beanType the type of bean
* @param beanName the name of bean
* @return if it's a first time to register, return <code>true</code>, or <code>false</code>
*/
public static boolean registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName,
Class<?> beanType) {
boolean registered = false;
// 如果beanDefinitionMap没有该bean
// 那么就将该bean注册到beanDefinitionMap中
if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
// 构建RootBeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
// 设置角色
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册到beanDefinitionMp中
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
registered = true;
if (log.isInfoEnabled()) {
log.info("The Infrastructure bean definition [" + beanDefinition
+ "with name [" + beanName + "] has been registered.");
}
}
return registered;
}
小结一下,DubboConfigConfigurationRegistrar
这个类主要是向Spring
容器注册DubboConfig
相关类的beanDefinition
。
DubboConfigConfiguration
DubboConfigConfiguration.Single
和DubboConfigConfiguration.Multiple
结构如下所示:
public class DubboConfigConfiguration {
/**
* 单个dubbo服务配置绑定
*/
@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 {
}
/**
* 多个dubbo服务配置绑定
*/
@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
注解,点开EnableConfigurationBeanBindings
注解,发现它又使用了@Import
注解引入了ConfigurationBeanBindingsRegister
类。
ConfigurationBeanBindingsRegister
public class ConfigurationBeanBindingsRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private ConfigurableEnvironment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取 EnableConfigurationBeanBindings 中的键值对
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableConfigurationBeanBindings.class.getName()));
// 获取 EnableConfigurationBeanBinding 数组
AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");
// 构建 ConfigurationBeanBindingRegistrar
ConfigurationBeanBindingRegistrar registrar = new ConfigurationBeanBindingRegistrar();
// 设置环境变量
registrar.setEnvironment(environment);
// 遍历 EnableConfigurationBeanBinding 数组
for (AnnotationAttributes element : annotationAttributes) {
// 调用ConfigurationBeanBindingRegistrar中的registerConfigurationBeanDefinitions方法
// 将beanDefinition注册到Spring的beanDefinitionMap中
registrar.registerConfigurationBeanDefinitions(element, registry);
}
}
@Override
public void setEnvironment(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
this.environment = (ConfigurableEnvironment) environment;
}
}
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();
private final Log log = LogFactory.getLog(getClass());
private ConfigurableEnvironment environment;
/*
* 注册beanDefinition
* @param metadata
* @param registry
* @return void
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 获取 EnableConfigurationBeanBinding 注解上的键值对
Map<String, Object> attributes = metadata.getAnnotationAttributes(ENABLE_CONFIGURATION_BINDING_CLASS_NAME);
// 注册配置bean的beanDefinition
registerConfigurationBeanDefinitions(attributes, registry);
}
/*
* 注册配置bean的beanDefinition
* @param attributes
* @param registry
* @return void
*/
public void registerConfigurationBeanDefinitions(Map<String, Object> attributes, BeanDefinitionRegistry registry) {
String prefix = getRequiredAttribute(attributes, "prefix");
prefix = environment.resolvePlaceholders(prefix);
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);
}
/*
* 配置bean的beanDefinition注册
*
* @param prefix
* @param configClass
* @param multiple 是否支持多Dubbo配置Bean绑定
* @param ignoreUnknownFields
* @param ignoreInvalidFields
* @param registry
* @return void
*/
private void registerConfigurationBeans(String prefix, Class<?> configClass, boolean multiple,
boolean ignoreUnknownFields, boolean ignoreInvalidFields,
BeanDefinitionRegistry registry) {
// 从application.properties中根据前缀拿对应的配置项
Map<String, Object> configurationProperties = PropertySourcesUtils.getSubProperties(environment.getPropertySources(), environment, prefix);
if (CollectionUtils.isEmpty(configurationProperties)) {
if (log.isDebugEnabled()) {
log.debug("There is no property for binding to configuration class [" + configClass.getName()
+ "] within prefix [" + prefix + "]");
}
return;
}
// multiple 表示是否支持多Dubbo 配置 Bean 绑定
// 比如
/*
dubbo.protocols.p1.id=p1
dubbo.protocols.p1.name=dubbo
dubbo.protocols.p1.port=20881
dubbo.protocols.p1.host=127.0.0.1
dubbo.protocols.p2.id=p2
dubbo.protocols.p2.name=dubbo
dubbo.protocols.p2.port=20881
dubbo.protocols.p2.host=127.0.0.1
*/
// 生成多个Dubbo配置Bean,而这多个bean直接按protocols后的p1,p2命名
Set<String> beanNames = multiple ? resolveMultipleBeanNames(configurationProperties) :
singleton(resolveSingleBeanName(configurationProperties, configClass, registry));
// 遍历循环
for (String beanName : beanNames) {
// 注册配置bean的beanDefinition
registerConfigurationBean(beanName, configClass, multiple, ignoreUnknownFields, ignoreInvalidFields,
configurationProperties, registry);
}
// 注册 ConfigurationBindingBeanPostProcessor 后置处理器
// 这样可以在bean实例化之前进行属性赋值
registerConfigurationBindingBeanPostProcessor(registry);
}
private void registerConfigurationBean(String beanName, Class<?> configClass, boolean multiple,
boolean ignoreUnknownFields, boolean ignoreInvalidFields,
Map<String, Object> configurationProperties,
BeanDefinitionRegistry registry) {
// 构建BeanDefinitionBuilder
BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
// 获取 beanDefinition
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 设置源头
// 后面会bean后置处理器会通过它区分bean是否是这里引过去的
setSource(beanDefinition);
// 获取每项配置的键值对
Map<String, Object> subProperties = resolveSubProperties(multiple, beanName, configurationProperties);
// 设置beanDefinition的属性
initBeanMetadataAttributes(beanDefinition, subProperties, ignoreUnknownFields, ignoreInvalidFields);
// 注册beanDefinition
registry.registerBeanDefinition(beanName, beanDefinition);
if (log.isInfoEnabled()) {
log.info("The configuration bean definition [name : " + beanName + ", content : " + beanDefinition
+ "] has been registered.");
}
}
}
ConfigurationBeanBindingPostProcessor
ConfigurationBeanBindingPostProcessor
是一个后置处理器,实现了BeanPostProcessor
接口,这样就可以在bean
实例化的前后对bean
进行一些特殊处理。
@SuppressWarnings("unchecked")
public class ConfigurationBeanBindingPostProcessor implements BeanPostProcessor, BeanFactoryAware, PriorityOrdered {
/**
* The bean name of {@link ConfigurationBeanBindingPostProcessor}
*/
public static final String BEAN_NAME = "configurationBeanBindingPostProcessor";
static final String CONFIGURATION_PROPERTIES_ATTRIBUTE_NAME = "configurationProperties";
static final String IGNORE_UNKNOWN_FIELDS_ATTRIBUTE_NAME = "ignoreUnknownFields";
static final String IGNORE_INVALID_FIELDS_ATTRIBUTE_NAME = "ignoreInvalidFields";
/*
* 前置处理
* @param bean
* @param beanName
* @return java.lang.Object
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 获取 beanDefinition
BeanDefinition beanDefinition = getNullableBeanDefinition(beanName);
// 判断bean是不是@EnableConfigurationBeanBinding注册的bean
if (isConfigurationBean(bean, beanDefinition)) {
// 属性值绑定到bean上
bindConfigurationBean(bean, beanDefinition);
customize(beanName, bean);
}
return bean;
}
/*
* 判断bean是否是通过EnableConfigurationBeanBinding路径注册的
* @param bean
* @param beanDefinition
* @return boolean
*/
private boolean isConfigurationBean(Object bean, BeanDefinition beanDefinition) {
return beanDefinition != null &&
ENABLE_CONFIGURATION_BINDING_CLASS.equals(beanDefinition.getSource())
&& nullSafeEquals(getBeanClassName(bean), beanDefinition.getBeanClassName());
}
/*
* 设置配置bean的属性值
* @param configurationBean
* @param beanDefinition
* @return void
*/
private void bindConfigurationBean(Object configurationBean, BeanDefinition beanDefinition) {
// 获取 key 为 configurationProperties 的属性值
Map<String, Object> configurationProperties =
getConfigurationProperties(beanDefinition);
// 是否忽略 UnknownFields
boolean ignoreUnknownFields = getIgnoreUnknownFields(beanDefinition);
//是否忽略 InvalidFields
boolean ignoreInvalidFields = getIgnoreInvalidFields(beanDefinition);
getConfigurationBeanBinder().bind(configurationProperties, ignoreUnknownFields, ignoreInvalidFields, configurationBean);
if (log.isInfoEnabled()) {
log.info("The configuration bean [" + configurationBean + "] have been binding by the " +
"configuration properties [" + configurationProperties + "]");
}
}
private ConfigurationBeanBinder configurationBeanBinder = null;
public ConfigurationBeanBinder getConfigurationBeanBinder() {
if (configurationBeanBinder == null) {
// 从Sprin容器中获取 ConfigurationBeanBinder
// 如果出现异常,则直接 new 一个 DefaultConfigurationBeanBinder
initConfigurationBeanBinder();
}
return configurationBeanBinder;
}
private void customize(String beanName, Object configurationBean) {
// 遍历
for (ConfigurationBeanCustomizer customizer : getConfigurationBeanCustomizers()) {
// 自定义设置配置bean的属性
customizer.customize(beanName, configurationBean);
}
}
}
debug过程
DubboConfigConfigurationRegistrar#registerBeanDefinitions
好了,上面贴了这么多的方法及源码,估计现在看客们已经云里雾里了,下面就带大家debug一次,再梳理一下流程。
首先将断点设置在DubboConfigConfigurationRegistrar#registerBeanDefinitions
方法的第一行,然后启动SpringBoot
项目,进入断点,如下所示:
然后我们step into
到registerBeans
的执行
此时控制台输出日志:
DefaultListableBeanFactory will register annotated classes : [class org.apache.dubbo.config.spring.context.annotation.DubboConfigConfiguration$Single]
下面的就不跟踪了,属于Spring
容器相关的源码了。
DubboConfigConfigurationRegistrar#registerCommonBeans
回到DubboConfigConfigurationRegistrar#registerBeanDefinitions
方法,继续de bug,然后step into
里面registerCommonBeans
方法里面,紧接着进入BeanRegistrar#registerInfrastructureBean
方法中,如下所示:
此时打印日志如下:
The Infrastructure bean definition [Root bean: class [org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=nullwith name [referenceAnnotationBeanPostProcessor] has been registered.
DubboConfigConfigurationRegistrar#registerBeanDefinitions
的debug
流程大致就是这样。
ConfigurationBeanBindingsRegister#registerBeanDefinitions
在DubboConfigConfigurationRegistrar#registerBeanDefinitions
方法中,会将DubboConfigConfiguration.Single
、DubboConfigConfiguration.Multiple
的beadDefinition
注册到Spring
容器中。而这两个类上都有EnableConfigurationBeanBindings
注解,如此所示:
最终也会将DubboCofig
配置相关的类的beadDefinition
注册到Spring
容器的beanDefinitionMap
中,从而进入到ConfigurationBeanBindingsRegister#registerBeanDefinitions
的方法。在此处打个断点,进行debug
,如下所示:
接着step into
registrar.registerConfigurationBeanDefinitions(element, registry)
行,进入到ConfigurationBeanBindingRegistrar#registerConfigurationBeanDefinitions
方法
接着step into
registerConfigurationBeans
这个方法,直到registerConfigurationBindingBeanPostProcessor
方法停止
此时日志输出:
The configuration bean definition [name : org.apache.dubbo.config.ApplicationConfig#0, content : Root bean: class [org.apache.dubbo.config.ApplicationConfig]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] has been registered.
The Infrastructure bean definition [Root bean: class [com.alibaba.spring.beans.factory.annotation.ConfigurationBeanBindingPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=nullwith name [configurationBeanBindingPostProcessor] has been registered.
There is no property for binding to configuration class [org.apache.dubbo.config.ModuleConfig] within prefix [dubbo.module]
step into
registerConfigurationBindingBeanPostProcessor
方法
这是个向Spring
容器的beanDefinitionMap
中注册ConfigurationBeanBindingPostProcessor
后置处理器的beanDefinition
。
回答问题
文章一开始的问题是,SpringBoot
启动类上加上@EnableDubbo
,这样就可以启动Dubbo
相关服务了,为什么?
结合本文的内容可以这么说,EnableDubbo
注解是一个组合注解,继承了EnableDubboConfig
和DubboComponentScan
这两个注解。EnableDubboConfig
注解的作用是将DubboConfig
的相关配置bean
的beanDefinition
注入到Spring
容器的beanDefinitionMap
,将这些bean
交由Spring
进行管理,以便在合适的时机获取特定的bean
实例。
至于DubboComponentScan
注解的作用我会在下一章进行讲解。