Spring與Dubbo整合原理與源碼分析 【1】註解@EnableDubbo @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig // @ ...
Spring與Dubbo整合原理與源碼分析
【1】註解@EnableDubbo
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @EnableDubboConfig // @EnableDubboConfig註解用來將properties文件中的配置項轉化為對應的Bean @DubboComponentScan // @DubboComponentScan註解用來掃描服務提供者和引用者(@Service與@Reference) 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; }
【2】註解@EnableDubboConfig
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Import(DubboConfigConfigurationRegistrar.class) public @interface EnableDubboConfig { boolean multiple() default true; }
1)DubboConfigConfigurationRegistrar類的作用
//因為實現了ImportBeanDefinitionRegistrar介面,spring容器就會實例化該類,並且調用其registerBeanDefinitions方法; public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //執行DubboConfigConfigurationRegistrar; AnnotationAttributes attributes = AnnotationAttributes.fromMap( importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName())); boolean multiple = attributes.getBoolean("multiple"); //預設值是true // 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); } } }
2)registerBeans做了什麼
public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) { if (ObjectUtils.isEmpty(annotatedClasses)) { return; } ... AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry); ... // 利用Spring中的AnnotatedBeanDefinitionReader來解析annotatedClasses // 會解析該類上的註解,然後進行處理 reader.register(annotatedClasses); }
3)DubboConfigConfiguration類展示
public class DubboConfigConfiguration { /** * Single Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class), @EnableDubboConfigBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.metrics", type = MetricsConfig.class) }) public static class Single {} /** * Multiple Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.metricses", type = MetricsConfig.class, multiple = true) }) public static class Multiple {} }
4)那麼必然又會解析到@EnableDubboConfigBindings註解
//又是利用了實現了ImportBeanDefinitionRegistrar介面,在實例化該類會調用其registerBeanDefinitions方法; public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { private ConfigurableEnvironment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //執行DubboConfigBindingsRegistrar AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBindings.class.getName())); // 拿到多個@EnableDubboConfigBinding註解 AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value"); DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar(); //將環境變數註入 registrar.setEnvironment(environment); for (AnnotationAttributes element : annotationAttributes) { // 逐個解析@EnableDubboConfigBinding註解,比如@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class) registrar.registerBeanDefinitions(element, registry); } } @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } }
5)registrar.registerBeanDefinitions方法的調用情況
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { private final Log log = LogFactory.getLog(getClass()); private ConfigurableEnvironment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //執行DubboConfigBindingRegistrar AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName())); registerBeanDefinitions(attributes, registry); } protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { // prefix = "dubbo.application" String prefix = environment.resolvePlaceholders(attributes.getString("prefix")); // type = ApplicationConfig.class Class<? extends AbstractConfig> configClass = attributes.getClass("type"); boolean multiple = attributes.getBoolean("multiple"); //針對配置分別進行註冊成Bean對象,方法1 registerDubboConfigBeans(prefix, configClass, multiple, registry); } //方法1,因為Single和Multiple都是走同一套邏輯,採用參數boolean multiple區分 private void registerDubboConfigBeans(String prefix, Class<? extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry) { // 從properties文件中根據首碼拿對應的配置項,比如根據dubbo.application首碼, // 就可以拿到如下配置: // dubbo.application.name=dubbo-demo-provider-application // dubbo.application.logger=log4j Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix); // 如果沒有相關的配置項,則不需要註冊BeanDefinition if (CollectionUtils.isEmpty(properties)) { if (log.isDebugEnabled()) { log.debug(...); } return; } // 根據配置項生成beanNames,為什麼會有多個? // 普通情況一個dubbo.application首碼對應一個ApplicationConfig類型的Bean // 特殊情況下(配置兩種協議),比如dubbo.protocols對應了: // dubbo.protocols.p1.name=dubbo // dubbo.protocols.p1.port=20880 // dubbo.protocols.p1.host=0.0.0.0 // dubbo.protocols.p2.name=http // dubbo.protocols.p2.port=8082 // dubbo.protocols.p2.host=0.0.0.0 // 那麼就需要對應兩個ProtocolConfig類型的Bean,那麼就需要兩個beanName:p1和p2 // 這裡就是multiple為true或false的區別,名字的區別,根據multiple用來判斷是否從配置項中獲取beanName // 如果multiple為false,則看有沒有配置id屬性,如果沒有配置則自動生成一個beanName. Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : Collections.singleton(resolveSingleBeanName(properties, configClass, registry)); for (String beanName : beanNames) { // 為每個beanName,註冊一個空的BeanDefinition,方法2 registerDubboConfigBean(beanName, configClass, registry); // 為每個bean註冊一個DubboConfigBindingBeanPostProcessor的Bean後置處理器,方法3 //這裡存在的問題就是對應每一種配置都會產生對應的BeanPostProcessor,最多好像也就是10種左右 //但其實一個就可以做的任務,拓展成多個貌似不太合理,結合處理邏輯都是同一套就很尷尬 registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry); } // 註冊一個NamePropertyDefaultValueDubboConfigBeanCustomizer的bean registerDubboConfigBeanCustomizers(registry); } //方法2,為對應的配置生成一個beanDefinition,並註入到容器 private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,BeanDefinitionRegistry registry) { BeanDefinitionBuilder builder = rootBeanDefinition(configClass); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); registry.registerBeanDefinition(beanName, beanDefinition); // ApplicatinoConfig對象 if (log.isInfoEnabled()) { log.info("...); //日誌記錄 } } //方法3 private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple,BeanDefinitionRegistry registry) { // 註冊一個DubboConfigBindingBeanPostProcessor的Bean // 每個XxConfig的Bean對應一個DubboConfigBindingBeanPostProcessor的Bean // 比如,一個ApplicationConfig對應一個DubboConfigBindingBeanPostProcessor, // 一個ProtocolConfig也會對應一個DubboConfigBindingBeanPostProcessor // 在構造DubboConfigBindingBeanPostProcessor的時候會指定構造方法的值,這樣就可以區別開來了 Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class; BeanDefinitionBuilder builder = rootBeanDefinition(processorClass); // 真實的首碼,比如dubbo.registries.r2 String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix; // 添加兩個構造方法參數值,所以會調用DubboConfigBindingBeanPostProcessor的兩個參數的構造方法 builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registerWithGeneratedName(beanDefinition, registry); if (log.isInfoEnabled()) { log.info(...); } } private void registerDubboConfigBeanCustomizers(BeanDefinitionRegistry registry) { registerInfrastructureBean(registry, BEAN_NAME, NamePropertyDefaultValueDubboConfigBeanCustomizer.class); } @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) { Set<String> beanNames = new LinkedHashSet<String>(); // 比如dubbo.protocols.p1.name=dubbo的propertyName為p1.name for (String propertyName : properties.keySet()) { // propertyName為p1.name int index = propertyName.indexOf("."); if (index > 0) { // 截取beanName名字為p1 String beanName = propertyName.substring(0, index); beanNames.add(beanName); } } return beanNames; } private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,BeanDefinitionRegistry registry) { // 配置了dubbo.application.id=appl,那麼appl就是beanName String beanName = (String) properties.get("id"); // 如果beanName為null,則會進入if分支,由spring自動生成一個beanName,比如org.apache.dubbo.config.ApplicationConfig#0 if (!StringUtils.hasText(beanName)) { BeanDefinitionBuilder builder = rootBeanDefinition(configClass); beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry); } return beanName; } }
6)單個DubboConfigBindingBeanPostProcessor的展示(刪減掉部分不怎麼用到的)
public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware, InitializingBean, BeanDefinitionRegistryPostProcessor { private final String prefix; private final String beanName; private DubboConfigBinder dubboConfigBinder; .... private List<DubboConfigBeanCustomizer> configBeanCustomizers = Collections.emptyList(); .... @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // 每個XxConfig對應一個BeanPostProcessor,所以每個DubboConfigBindingBeanPostProcessor只處理對應的beanName if (this.beanName.equals(beanName) && bean instanceof AbstractConfig) { AbstractConfig dubboConfig = (AbstractConfig) bean; // 從properties文件中獲取值,並設置到dubboConfig對象中 bind(prefix, dubboConfig); // 設置dubboConfig對象的name屬性,設置為beanName customize(beanName, dubboConfig); } return bean; } private void bind(String prefix, AbstractConfig dubboConfig) { dubboConfigBinder.bind(prefix, dubboConfig); if (log.isInfoEnabled()) { log.info(...); } } private void customize(String beanName, AbstractConfig dubboConfig) { for (DubboConfigBeanCustomizer customizer : configBeanCustomizers) { customizer.customize(beanName, dubboConfig); } } ... @Override public void afterPropertiesSet() throws Exception { initDubboConfigBinder(); // 創建DefaultDubboConfigBinder initConfigBeanCustomizers(); } private void initDubboConfigBinder() { if (dubboConfigBinder == null) { try { // 先從Spring容器中獲取DubboConfigBinder,預設獲取不到 dubboConfigBinder = applicationContext.getBean(DubboConfigBinder.class); } catch (BeansException ignored) { if (log.isDebugEnabled()) { log.debug("DubboConfigBinder Bean can't be found in ApplicationContext."); } // Use Default implementation // 生成一個預設的 dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment()); } } dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields); dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields); } private void initConfigBeanCustomizers() { // 得到之前創建了的NamePropertyDefaultValueDubboConfigBeanCustomizer Collection<DubboConfigBeanCustomizer> configBeanCustomizers = beansOfTypeIncludingAncestors(applicationContext, DubboConfigBeanCustomizer.class).values(); this.configBeanCustomizers = new ArrayList<>(configBeanCustomizers); AnnotationAwareOrderComparator.sort(this.configBeanCustomizers); } ... }
【3】註解@DubboComponentScan
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(DubboComponentScanRegistrar.class) public @interface DubboComponentScan { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; }
1)導入的DubboComponentScanRegistrar類做了什麼
/又是利用了實現了ImportBeanDefinitionRegistrar介面,在實例化該類會調用其registerBeanDefinitions方法; public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //執行DubboComponentScanRegistrar // 拿到DubboComponentScan註解所定義的包路徑,掃描該package下的類,識別這些類上 Set<String> packagesToScan = getPackagesToScan(importingClassMetadata); // 註冊ServiceAnnotationBeanPostProcessor一個Bean // 實現了BeanDefinitionRegistryPostProcessor介面,所以在Spring啟動時會調用postProcessBeanDefinitionRegistry方法 // 該方法會進行掃描,掃描@Service註解了的類,然後生成BeanDefinition(會生成兩個,一個普通的bean,一個ServiceBean),後續的Spring周期中會生成Bean // 在ServiceBean中會監聽ContextRefreshedEvent事件,一旦Spring啟動完後,就會進行服務導出 registerServiceAnnotationBeanPostProcessor(packagesToScan, registry); // 註冊ReferenceAnnotationBeanPostProcessor // 實現了AnnotationInjectedBeanPostProcessor介面,繼而實現了InstantiationAwareBeanPostProcessorAdapter介面 // 所以Spring在啟動時,在對屬性進行註入時會調用AnnotationInjectedBeanPostProcessor介面中的postProcessPropertyValues方法 // 在這個過程中會按照@Refrence註解的信息去生成一個RefrenceBean對象 registerReferenceAnnotationBeanPostProcessor(registry); } //核心方法1,註冊一個對@Service註解處理的 BeanDefinitionRegistryPostProcessor private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) { // 生成一個RootBeanDefinition,對應的beanClass為ServiceAnnotationBeanPostProcessor.class BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class); // 將包路徑作為在構造ServiceAnnotationBeanPostProcessor時調用構造方法時的傳入參數 builder.addConstructorArgValue(packagesToScan); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry); } //核心方法2,註冊一個對屬性賦值處理的AnnotationInjectedBeanPostProcessor且帶有ApplicationListener事件監聽功能 private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) { // Register @Reference Annotation Bean Processor // 註冊一個ReferenceAnnotationBeanPostProcessor做為bean,ReferenceAnnotationBeanPostProcessor是一個BeanPostProcessor BeanRegistrar.registerInfrastructureBean(registry,ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); } 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; } }
【4】掃描@Service註解,並且進行處理
彙總說明:實際上便是通過處理器掃描@Service註解的類,生成兩個Bean【類對應的普通Bean,與Dubbo中要用到的ServiceBean】
其中ServiceBean,是先根據註解上的信息填充對應的屬性,後採用環境變數中獲取配置的屬性,來完成屬性填充。
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,ResourceLoaderAware, BeanClassLoaderAware { ... //核心方法1 @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { // 掃描包,進行Bean註冊,核心方法2調用 registerServiceBeans(resolvedPackagesToScan, registry); } else { if (logger.isWarnEnabled()) { logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!"); } } } //核心方法2 private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) { DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader); BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry); scanner.setBeanNameGenerator(beanNameGenerator); // 掃描被Service註解標註的類 scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class)); scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class)); for (String packageToScan : packagesToScan) { // Registers @Service Bean first // 掃描Dubbo自定義的@Service註解 scanner.scan(packageToScan); // 查找被@Service註解的類的BeanDefinition(無論這個類有沒有被@ComponentScan註解標註了) Set<BeanDefinitionHolder> beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator); if (!CollectionUtils.isEmpty(beanDefinitionHolders)) { // 掃描到BeanDefinition開始處理它,核心方法3的調用 for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) { registerServiceBean(beanDefinitionHolder, registry, scanner); } if (logger.isInfoEnabled()) { logger.info(b...); } } else { if (logger.isWarnEnabled()) { logger.warn(...); } } } } //核心方法3 private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner) { // 處理掃描到的每一個BeanDefinition // 1. 得到@Service註解上所配置的參數 // 2. 根據每一個BeanDefinition會再額外的生成一個ServiceBean // 3. 對於每一個被@Service註解的類(服務的實現類),會生成兩個Bean,一個服務實現類對應的Bean(普通Bean,和@Component一樣),一個ServiceBean(Dubbo中要用到的Bean,因為在ServiceBean中包括了很的Config) // 具體的服務實現類 Class<?> beanClass = resolveClass(beanDefinitionHolder); // @Service可以對服務進行各種配置 Annotation service = findServiceAnnotation(beanClass); AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false); // 服務實現類對應的介面 Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass); // 服務實現類對應的bean的名字,比如:demoServiceImpl String annotatedServiceBeanName = beanDefinitionHolder.getBeanName(); // 生成一個ServiceBean,核心方法4的調用 AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName); // ServiceBean Bean name ServiceBean表示服務,我們要使用一個服務應該拿ServiceBean String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass); if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean // 把ServiceBean註冊進去,對應的beanName為ServiceBean:org.apache.dubbo.demo.DemoService registry.registerBeanDefinition(beanName, serviceBeanDefinition); if (logger.isInfoEnabled()) { logger.info(..); } } else { if (logger.isWarnEnabled()) { logger.warn(...); } } } ... //核心方法4 private AbstractBeanDefinition buildServiceBeanDefinition(Annotation serviceAnnotation,AnnotationAttributes serviceAnnotationAttributes,Class<?> interfaceClass,String annotatedServiceBeanName) { // 生成一個ServiceBean對應的BeanDefinition 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"); // 把serviceAnnotation中的參數值賦值給ServiceBean的屬性 // 如:@Service(test = "test") propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames)); // References "ref" property to annotated-@Service Bean // 如:@Service(protocol = "P1"),這種就是要根據對應的值找到對應的P1的config對象裡面的值 // ref屬性賦值為另外一個bean, 對應的就是被@Service註解的服務實現類對應的bean addPropertyReference(builder, "ref", annotatedServiceBeanName); // Set interface builder.addPropertyValue("interface", interfaceClass.getName()); // Convert parameters into map builder.addPropertyValue("parameters", convertParameters(serviceAnnotationAttributes.getStringArray("parameters"))); // 配置了methods屬性,則給ServiceBean對應的methods屬性賦值 // 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)