diff --git a/common/cdc-debezium-common/pom.xml b/common/cdc-debezium-common/pom.xml
index 0a1092b8..0aa44d60 100644
--- a/common/cdc-debezium-common/pom.xml
+++ b/common/cdc-debezium-common/pom.xml
@@ -74,11 +74,6 @@
org.springframework.integrationspring-integration-ip
-
- org.springframework.cloud.fn
- config-common
- ${revision}
-
diff --git a/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizationAutoConfiguration.java b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizationAutoConfiguration.java
new file mode 100644
index 00000000..758ed4a6
--- /dev/null
+++ b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizationAutoConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022-2022 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.common.config;
+
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * An auto-configuration to expose customizer strategy beans to accept user-provided component customizers.
+ *
+ * @author Artem Bilan
+ *
+ * @since 1.2.1
+ *
+ * @see ComponentCustomizerBeanPostProcessor
+ */
+public class ComponentCustomizationAutoConfiguration {
+
+ @Bean
+ @ConditionalOnBean(ComponentCustomizer.class)
+ static BeanPostProcessor componentCustomizerBeanPostProcessor() {
+ return new ComponentCustomizerBeanPostProcessor();
+ }
+
+}
diff --git a/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizer.java b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizer.java
new file mode 100644
index 00000000..e77917cf
--- /dev/null
+++ b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022-2022 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.common.config;
+
+/**
+ * The customizer contract to apply to beans in the application context which are marked
+ * with the {@link CustomizationAware} annotation and their type is matching to generic
+ * type of the instance of this interface.
+ *
+ * The bean for {@link ComponentCustomizer} has to be declared as a {@code static} bean
+ * method to avoid early bean initialization syndrome when not all bean post processors
+ * are configured into the application context yet. Its dependencies have to be {@code static}
+ * as well, or all of related beans can be declared in the dedicated {@code @Configuration} class.
+ *
+ * @param the target component (bean) type in the application context to customize.
+ *
+ * @author Artem Bilan
+ *
+ * @since 1.2.1
+ */
+@FunctionalInterface
+public interface ComponentCustomizer {
+
+ void customize(T component, String beanName);
+
+}
diff --git a/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizerBeanPostProcessor.java b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizerBeanPostProcessor.java
new file mode 100644
index 00000000..4343ded9
--- /dev/null
+++ b/common/config-common/src/main/java/org/springframework/cloud/fn/common/config/ComponentCustomizerBeanPostProcessor.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2022-2022 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.fn.common.config;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.aop.framework.AopProxyUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.log.LogMessage;
+import org.springframework.core.type.MethodMetadata;
+
+/**
+ * The {@link MergedBeanDefinitionPostProcessor} to apply a {@link ComponentCustomizer} for a bean
+ * in process if this bean is marked with the {@link CustomizationAware} annotation and
+ * a customizer for a type of this bean is present in the application context.
+ *
+ * @author Artem Bilan
+ *
+ * @since 1.2.1
+ */
+class ComponentCustomizerBeanPostProcessor implements MergedBeanDefinitionPostProcessor, BeanFactoryAware {
+
+ private static final Log logger = LogFactory.getLog(ComponentCustomizerBeanPostProcessor.class);
+
+ private final Set customizationAwareBeanNames = new HashSet<>();
+
+ private BeanFactory beanFactory;
+
+ @Override
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+
+ @Override
+ public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
+ if (beanDefinition instanceof AnnotatedBeanDefinition) {
+ AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
+ MethodMetadata factoryMethodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
+ if (factoryMethodMetadata != null &&
+ factoryMethodMetadata.isAnnotated(CustomizationAware.class.getName())) {
+
+ this.customizationAwareBeanNames.add(beanName);
+ }
+ }
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (this.customizationAwareBeanNames.remove(beanName)) {
+ ResolvableType integrationComponentCustomizerType =
+ ResolvableType.forClassWithGenerics(ComponentCustomizer.class,
+ AopProxyUtils.ultimateTargetClass(bean));
+
+ ComponentCustomizer