You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/11/25 06:20:09 UTC

[dubbo] 23/45: improve config bean initialization

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch release/3.0.14-rpccontext-bugfix
in repository https://gitbox.apache.org/repos/asf/dubbo.git

commit 278aaef1acad984bf33c1ab387772c4621d86088
Author: 赫炎 <de...@alibaba-inc.com>
AuthorDate: Tue Dec 1 22:43:20 2020 +0800

    improve config bean initialization
---
 .../org/apache/dubbo/config/AbstractConfig.java    |   4 +-
 .../apache/dubbo/config/spring/ReferenceBean.java  |  59 ++------
 .../annotation/DubboConfigAliasPostProcessor.java  |   3 +
 .../config/DubboConfigBeanPostProcessor.java       | 149 +++++++++++++++++++++
 ...onfigDefaultPropertyValueBeanPostProcessor.java |   2 +
 .../dubbo/config/spring/util/DubboBeanUtils.java   |  13 +-
 6 files changed, 172 insertions(+), 58 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 16e1180..ab8f5f4 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -571,10 +571,12 @@ public abstract class AbstractConfig implements Serializable {
      * <p>
      * Current method will invoked by Spring or Java EE container automatically, or should be triggered manually.
      *
+     * @deprecated this init method is replace with DubboConfigBeanPostProcessor
+     *
      * @see ConfigManager#addConfig(AbstractConfig)
      * @since 2.7.5
      */
-    @PostConstruct
+    @Deprecated
     public void addIntoConfigManager() {
         ApplicationModel.getConfigManager().addConfig(this);
     }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index be9cd71..4ca3a84 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -16,34 +16,22 @@
  */
 package org.apache.dubbo.config.spring;
 
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConsumerConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.MetricsConfig;
-import org.apache.dubbo.config.ModuleConfig;
-import org.apache.dubbo.config.MonitorConfig;
-import org.apache.dubbo.config.ProtocolConfig;
-import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.ReferenceConfig;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.SslConfig;
 import org.apache.dubbo.config.annotation.Reference;
+import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigBeanPostProcessor;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.apache.dubbo.config.support.Parameter;
-
-import org.springframework.beans.factory.DisposableBean;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
 import org.springframework.beans.factory.FactoryBean;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 
-import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
-
 /**
  * ReferenceFactoryBean
  */
-public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
-        ApplicationContextAware, InitializingBean, DisposableBean {
+public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware,
+        InitializingBean {
 
     private static final long serialVersionUID = 213195494150089726L;
 
@@ -79,43 +67,14 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
         return true;
     }
 
-    /**
-     * Initializes there Dubbo's Config Beans before @Reference bean autowiring
-     */
-    private void prepareDubboConfigBeans() {
-        beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class);
-        beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class);
-        beansOfTypeIncludingAncestors(applicationContext, SslConfig.class);
-    }
-
     @Override
-    @SuppressWarnings({"unchecked"})
     public void afterPropertiesSet() throws Exception {
-
-        // Initializes Dubbo's Config Beans before @Reference bean autowiring
-        prepareDubboConfigBeans();
-
-        // lazy init by default.
-        if (init == null) {
-            init = false;
+        // Abort initializing when config beans are not loaded
+        if (!DubboConfigBeanPostProcessor.isConfigBeansLoaded()) {
+            throw new IllegalStateException("dubbo config beans are not loaded");
         }
 
-        // eager init if necessary.
-        if (shouldInit()) {
-            getObject();
-        }
-    }
-
-    @Override
-    public void destroy() {
-        // do nothing
+        // Abort initializing when property values are not autowired probably
+        ConfigValidationUtils.validateReferenceConfig(this);
     }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java
index 28b6a6c..5f55343 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/DubboConfigAliasPostProcessor.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.config.spring.beans.factory.annotation;
 
 import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigBeanPostProcessor;
 import org.apache.dubbo.config.spring.context.annotation.DubboConfigConfigurationRegistrar;
 
 import org.springframework.beans.BeansException;
@@ -32,8 +33,10 @@ import static org.springframework.util.StringUtils.hasText;
 /**
  * A Post-Processor class to set the alias of Dubbo Config bean using its {@link AbstractConfig#getId()}
  *
+ * @deprecated replace with {@link DubboConfigBeanPostProcessor}
  * @since 2.7.5
  */
+@Deprecated
 public class DubboConfigAliasPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanPostProcessor {
 
     /**
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigBeanPostProcessor.java
new file mode 100644
index 0000000..fb72ce8
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigBeanPostProcessor.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring.beans.factory.config;
+
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.MetricsConfig;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.SslConfig;
+import org.apache.dubbo.config.spring.ConfigCenterBean;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static com.alibaba.spring.util.BeanRegistrar.hasAlias;
+import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
+import static org.springframework.util.ObjectUtils.nullSafeEquals;
+import static org.springframework.util.StringUtils.hasText;
+
+/**
+ * A Post-Processor to config Dubbo Config bean
+ *
+ * @since 2.7.9
+ */
+public class DubboConfigBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanPostProcessor,
+        ApplicationContextAware {
+
+    /**
+     * The bean name of {@link DubboConfigBeanPostProcessor}
+     */
+    public final static String BEAN_NAME = "dubboConfigBeanPostProcessor";
+
+    private BeanDefinitionRegistry registry;
+    private ApplicationContext applicationContext;
+    private static AtomicBoolean configBeansLoading = new AtomicBoolean();
+    private static volatile boolean configBeansLoaded;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+    @Override
+    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
+        this.registry = registry;
+    }
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+        // DO NOTHING
+    }
+
+    @Override
+    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+        if (configBeansLoading.compareAndSet(false, true)) {
+            // Initializes Dubbo's Config Beans before @Reference bean autowiring
+            prepareDubboConfigBeans();
+            configBeansLoaded = true;
+        }
+
+        // DO NOTHING
+        return bean;
+    }
+
+    private void prepareDubboConfigBeans() {
+        // Refactor 2.7.9
+        final boolean includeNonSingletons = true;
+        final boolean allowEagerInit = false;
+        beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class, includeNonSingletons, allowEagerInit);
+        beansOfTypeIncludingAncestors(applicationContext, SslConfig.class, includeNonSingletons, allowEagerInit);
+    }
+
+    @Override
+    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+        if (bean instanceof AbstractConfig) {
+            AbstractConfig configBean = (AbstractConfig) bean;
+            setDefaultConfigId(configBean, beanName);
+            setConfigBeanAlias(configBean, beanName);
+            addConfigBeanToManager(configBean);
+        }
+        return bean;
+    }
+
+    private void setDefaultConfigId(AbstractConfig configBean, String beanName) {
+        // if config bean's id is not set, use beanName as config id
+        // https://github.com/apache/dubbo/issues/5721
+        if (StringUtils.isEmpty(configBean.getId())) {
+            configBean.setId(beanName);
+        }
+    }
+
+    private void setConfigBeanAlias(AbstractConfig configBean, String beanName) {
+        // set dubbo config bean alias from id property
+        // https://github.com/apache/dubbo/issues/5093
+        String id = configBean.getId();
+        if (hasText(id)                                     // id MUST be present in AbstractConfig
+                && !nullSafeEquals(id, beanName)            // id MUST NOT be equal to bean name
+                && !hasAlias(registry, beanName, id)) {     // id MUST NOT be present in AliasRegistry
+            registry.registerAlias(beanName, id);
+        }
+    }
+
+    private void addConfigBeanToManager(AbstractConfig configBean) {
+        // Add AbstractConfig instance into ConfigManager,
+        // no need to call org.apache.dubbo.config.AbstractConfig.addIntoConfigManager()
+        ApplicationModel.getConfigManager().addConfig(configBean);
+    }
+
+    public static boolean isConfigBeansLoaded() {
+        return configBeansLoaded;
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
index ec99c1c..52f52d6 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
@@ -41,8 +41,10 @@ import static org.springframework.util.ReflectionUtils.invokeMethod;
 /**
  * The {@link BeanPostProcessor} class for the default property value of {@link AbstractConfig Dubbo's Config Beans}
  *
+ * @deprecated replace with {@link DubboConfigBeanPostProcessor}
  * @since 2.7.6
  */
+@Deprecated
 public class DubboConfigDefaultPropertyValueBeanPostProcessor extends GenericBeanPostProcessorAdapter<AbstractConfig>
         implements MergedBeanDefinitionPostProcessor, PriorityOrdered {
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
index 3b2c31c..03dd533 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.config.spring.util;
 
 import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigAliasPostProcessor;
 import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
+import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigBeanPostProcessor;
 import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigDefaultPropertyValueBeanPostProcessor;
 import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener;
 import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener;
@@ -49,10 +50,6 @@ public interface DubboBeanUtils {
         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.5 Register DubboLifecycleComponentApplicationListener as an infrastructure Bean
         registerInfrastructureBean(registry, DubboLifecycleComponentApplicationListener.BEAN_NAME,
                 DubboLifecycleComponentApplicationListener.class);
@@ -61,8 +58,10 @@ public interface DubboBeanUtils {
         registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
                 DubboBootstrapApplicationListener.class);
 
-        // Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
-        registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
-                DubboConfigDefaultPropertyValueBeanPostProcessor.class);
+        // Since 2.7.9 Register DubboConfigBeanPostProcessor as an infrastructure Bean,
+        // merge processing logics of all DubboConfigAliasPostProcessor, DubboConfigDefaultPropertyValueBeanPostProcessor
+        // and DubboConfigEarlyInitializationPostProcessor
+        registerInfrastructureBean(registry, DubboConfigBeanPostProcessor.BEAN_NAME,
+                DubboConfigBeanPostProcessor.class);
     }
 }