You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/08/16 06:12:49 UTC

[dubbo] branch 3.0 updated: Extract DubboSpringInitializer and support customize initialization (#8495)

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

albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0 by this push:
     new 0809a16  Extract DubboSpringInitializer and support customize initialization (#8495)
0809a16 is described below

commit 0809a168db5fd71a58dd3f87b0bce00bd5ed8916
Author: Gong Dewei <ky...@qq.com>
AuthorDate: Mon Aug 16 14:12:04 2021 +0800

    Extract DubboSpringInitializer and support customize initialization (#8495)
---
 .../context/DubboSpringInitializationContext.java  | 36 +++++++++
 .../DubboSpringInitializationCustomizer.java       | 42 ++++++++++
 .../spring/context/DubboSpringInitializer.java     | 63 +++++++++++++++
 .../annotation/DubboComponentScanRegistrar.java    |  7 +-
 .../DubboConfigConfigurationRegistrar.java         |  8 +-
 .../spring/schema/DubboNamespaceHandler.java       | 12 ++-
 .../config/spring/util/SpringCompatUtils.java      |  8 +-
 .../test/spring/SpringAnnotationBeanTest.java      |  4 +
 .../test/spring/SpringJavaConfigBeanTest.java      |  3 +
 .../dubbo/test/spring/SpringXmlConfigTest.java     |  4 +
 .../MockSpringInitializationCustomizer.java        | 91 ++++++++++++++++++++++
 ...ing.context.DubboSpringInitializationCustomizer |  1 +
 12 files changed, 263 insertions(+), 16 deletions(-)

diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
new file mode 100644
index 0000000..08a5e09
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
@@ -0,0 +1,36 @@
+/*
+ * 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.context;
+
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+
+/**
+ * Dubbo spring initialization context object
+ */
+public class DubboSpringInitializationContext {
+
+    private BeanDefinitionRegistry registry;
+
+    public BeanDefinitionRegistry getRegistry() {
+        return registry;
+    }
+
+    void setRegistry(BeanDefinitionRegistry registry) {
+        this.registry = registry;
+    }
+
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java
new file mode 100644
index 0000000..9637996
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.context;
+
+import org.apache.dubbo.common.extension.SPI;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * Custom dubbo spring initialization
+ */
+@SPI
+public interface DubboSpringInitializationCustomizer {
+
+    /**
+     * <p>Customize dubbo spring initialization on bean registry processing phase.</p>
+     * <p>You can register a {@link BeanFactoryPostProcessor} or {@link BeanPostProcessor} for custom processing.</p>
+     *
+     * <p><b>Note:</b></p>
+     * <p>1. The bean factory may be not ready yet when triggered by parsing dubbo xml definition.</p>
+     * <p>2. Some bean definitions may be not registered at this moment. If you plan to process all bean definitions,
+     * it is recommended to register a custom {@link BeanFactoryPostProcessor} to do so.</p>
+     *
+     * @param context
+     */
+    void customize(DubboSpringInitializationContext context);
+
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java
new file mode 100644
index 0000000..2ae3d37
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java
@@ -0,0 +1,63 @@
+/*
+ * 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.context;
+
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Dubbo spring initialization entry point
+ */
+public class DubboSpringInitializer {
+
+    private static Map<BeanDefinitionRegistry, DubboSpringInitializationContext> contextMap = new ConcurrentHashMap<>();
+
+    public static void initialize(BeanDefinitionRegistry registry) {
+
+        if (contextMap.putIfAbsent(registry, new DubboSpringInitializationContext()) != null) {
+            return;
+        }
+
+        // register common beans
+        DubboBeanUtils.registerCommonBeans(registry);
+
+        // prepare context and do customize
+        DubboSpringInitializationContext context = contextMap.get(registry);
+        context.setRegistry(registry);
+        customize(context);
+    }
+
+    private DubboSpringInitializer() {
+    }
+
+    private static void customize(DubboSpringInitializationContext context) {
+
+        // find initialization customizers
+        Set<DubboSpringInitializationCustomizer> customizers = ExtensionLoader
+            .getExtensionLoader(DubboSpringInitializationCustomizer.class)
+            .getSupportedExtensionInstances();
+
+        for (DubboSpringInitializationCustomizer customizer : customizers) {
+            customizer.customize(context);
+        }
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
index 25821d2..d1db4db 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.config.spring.context.annotation;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
 import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
-
+import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -35,7 +35,6 @@ import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
-import static org.apache.dubbo.config.spring.util.DubboBeanUtils.registerCommonBeans;
 import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
 
 /**
@@ -53,8 +52,8 @@ public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistra
     @Override
     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 
-        // @since 2.7.6 Register the common beans
-        registerCommonBeans(registry);
+        // initialize dubbo beans
+        DubboSpringInitializer.initialize(registry);
 
         Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java
index c455023..c8e51b8 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java
@@ -17,13 +17,12 @@
 package org.apache.dubbo.config.spring.context.annotation;
 
 import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
 import org.springframework.core.Ordered;
 import org.springframework.core.type.AnnotationMetadata;
 
-import static org.apache.dubbo.config.spring.util.DubboBeanUtils.registerCommonBeans;
-
 /**
  * Dubbo {@link AbstractConfig Config} {@link ImportBeanDefinitionRegistrar register}, which order can be configured
  *
@@ -37,6 +36,9 @@ public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRe
     @Override
     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 
+        // initialize dubbo beans
+        DubboSpringInitializer.initialize(registry);
+
         // Config beans creating from props have move to DubboBootstrap
 //        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
 //                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
@@ -50,7 +52,5 @@ public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRe
 //            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
 //        }
 
-        // Since 2.7.6
-        registerCommonBeans(registry);
     }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index ec7ded6..7993feb 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -32,6 +32,7 @@ import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
 import org.apache.dubbo.config.spring.beans.factory.config.ConfigurableSourceBeanMetadataElement;
 
+import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
@@ -39,8 +40,6 @@ import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.context.annotation.AnnotationConfigUtils;
 import org.w3c.dom.Element;
 
-import static org.apache.dubbo.config.spring.util.DubboBeanUtils.registerCommonBeans;
-
 /**
  * DubboNamespaceHandler
  *
@@ -82,11 +81,10 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport implements Co
     public BeanDefinition parse(Element element, ParserContext parserContext) {
         BeanDefinitionRegistry registry = parserContext.getRegistry();
         registerAnnotationConfigProcessors(registry);
-        /**
-         * @since 2.7.8
-         * issue : https://github.com/apache/dubbo/issues/6275
-         */
-        registerCommonBeans(registry);
+
+        // initialize dubbo beans
+        DubboSpringInitializer.initialize(registry);
+
         BeanDefinition beanDefinition = super.parse(element, parserContext);
         setSource(beanDefinition);
         return beanDefinition;
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java
index 9faed82..a6a4d93 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java
@@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.PropertyValue;
 import org.springframework.beans.PropertyValues;
 import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.config.TypedStringValue;
 import org.springframework.core.type.MethodMetadata;
 import org.springframework.core.type.StandardMethodMetadata;
 
@@ -39,7 +40,12 @@ public class SpringCompatUtils {
 
     public static <T> T getPropertyValue(PropertyValues pvs, String propertyName) {
         PropertyValue pv = pvs.getPropertyValue(propertyName);
-        return (pv != null ? (T) pv.getValue() : null);
+        Object val = pv != null ? pv.getValue() : null;
+        if (val instanceof TypedStringValue) {
+            TypedStringValue typedString = (TypedStringValue) val;
+            return (T) typedString.getValue();
+        }
+        return (T) val;
     }
 
     public static boolean isFactoryMethodMetadataEnabled() {
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java
index d0cc44c..9398865 100644
--- a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.apache.dubbo.test.common.ZooKeeperServer;
 import org.apache.dubbo.test.common.api.DemoService;
+import org.apache.dubbo.test.spring.context.MockSpringInitializationCustomizer;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -41,6 +42,9 @@ public class SpringAnnotationBeanTest {
         AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfiguration.class);
         TestService testService = applicationContext.getBean(TestService.class);
         testService.test();
+
+        // check initialization customizer
+        MockSpringInitializationCustomizer.checkCustomizer(applicationContext);
     }
 
     @EnableDubbo(scanBasePackages = "org.apache.dubbo.test.common.impl")
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
index bcd2e5d..074baeb 100644
--- a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
@@ -33,6 +33,7 @@ import org.apache.dubbo.test.common.SysProps;
 import org.apache.dubbo.test.common.ZooKeeperServer;
 import org.apache.dubbo.test.common.api.DemoService;
 import org.apache.dubbo.test.common.impl.DemoServiceImpl;
+import org.apache.dubbo.test.spring.context.MockSpringInitializationCustomizer;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -119,6 +120,8 @@ public class SpringJavaConfigBeanTest {
             String result = referProxy.sayHello("dubbo");
             Assertions.assertEquals("Hello dubbo", result);
 
+            // check initialization customizer
+            MockSpringInitializationCustomizer.checkCustomizer(consumerContext);
         } finally {
             consumerContext.close();
         }
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java
index 492ee1a..d600ca2 100644
--- a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.test.common.ZooKeeperServer;
 import org.apache.dubbo.test.common.api.DemoService;
 import org.apache.dubbo.test.common.api.GreetingService;
 import org.apache.dubbo.test.common.api.RestDemoService;
+import org.apache.dubbo.test.spring.context.MockSpringInitializationCustomizer;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -55,6 +56,9 @@ public class SpringXmlConfigTest {
             RestDemoService restDemoService = applicationContext.getBean("restDemoService", RestDemoService.class);
             String resetHelloResult = restDemoService.sayHello("dubbo");
             Assertions.assertEquals("Hello, dubbo", resetHelloResult);
+
+            // check initialization customizer
+            MockSpringInitializationCustomizer.checkCustomizer(applicationContext);
         } finally {
             SysProps.clear();
             if (applicationContext != null) {
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/context/MockSpringInitializationCustomizer.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/context/MockSpringInitializationCustomizer.java
new file mode 100644
index 0000000..093f419
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/context/MockSpringInitializationCustomizer.java
@@ -0,0 +1,91 @@
+/*
+ * 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.test.spring.context;
+
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializationContext;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializationCustomizer;
+import org.junit.jupiter.api.Assertions;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.context.ConfigurableApplicationContext;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class MockSpringInitializationCustomizer implements DubboSpringInitializationCustomizer {
+
+    private List<DubboSpringInitializationContext> contexts = new ArrayList<>();
+
+    @Override
+    public void customize(DubboSpringInitializationContext context) {
+        this.contexts.add(context);
+
+        // register post-processor bean, expecting the bean is loaded and invoked by spring container
+        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
+            .rootBeanDefinition(CustomBeanFactoryPostProcessor.class)
+            .getBeanDefinition();
+        context.getRegistry().registerBeanDefinition(CustomBeanFactoryPostProcessor.class.getName(), beanDefinition);
+    }
+
+    public List<DubboSpringInitializationContext> getContexts() {
+        return contexts;
+    }
+
+    private static class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+        private ConfigurableListableBeanFactory beanFactory;
+
+        @Override
+        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+            this.beanFactory = beanFactory;
+        }
+    }
+
+    public static void checkCustomizer(ConfigurableApplicationContext applicationContext) {
+        Set<DubboSpringInitializationCustomizer> customizers = ExtensionLoader
+            .getExtensionLoader(DubboSpringInitializationCustomizer.class)
+            .getSupportedExtensionInstances();
+
+        MockSpringInitializationCustomizer mockCustomizer = null;
+        for (DubboSpringInitializationCustomizer customizer : customizers) {
+            if (customizer instanceof MockSpringInitializationCustomizer) {
+                mockCustomizer = (MockSpringInitializationCustomizer) customizer;
+                break;
+            }
+        }
+        Assertions.assertNotNull(mockCustomizer);
+
+        // check applicationContext
+        boolean foundInitContext = false;
+        List<DubboSpringInitializationContext> contexts = mockCustomizer.getContexts();
+        for (DubboSpringInitializationContext initializationContext : contexts) {
+            if (initializationContext.getRegistry() == applicationContext.getBeanFactory()) {
+                foundInitContext = true;
+                break;
+            }
+        }
+        Assertions.assertEquals(true, foundInitContext);
+
+        // expect CustomBeanFactoryPostProcessor is loaded and invoked
+        CustomBeanFactoryPostProcessor customBeanFactoryPostProcessor = applicationContext.getBean(CustomBeanFactoryPostProcessor.class);
+        Assertions.assertEquals(applicationContext.getBeanFactory(), customBeanFactoryPostProcessor.beanFactory);
+    }
+}
diff --git a/dubbo-test/dubbo-test-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.spring.context.DubboSpringInitializationCustomizer b/dubbo-test/dubbo-test-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.spring.context.DubboSpringInitializationCustomizer
new file mode 100644
index 0000000..5b63f73
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.spring.context.DubboSpringInitializationCustomizer
@@ -0,0 +1 @@
+mock=org.apache.dubbo.test.spring.context.MockSpringInitializationCustomizer