diff --git a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessor.java b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessor.java
index 04184a564d..7e57a522d5 100644
--- a/spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessor.java
+++ b/spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessor.java
@@ -12,19 +12,17 @@
*/
package io.kubernetes.client.spring.extended.controller;
-import io.kubernetes.client.extended.controller.Controller;
-import io.kubernetes.client.extended.controller.ControllerManager;
+import static org.springframework.util.Assert.notNull;
+
import io.kubernetes.client.extended.controller.reconciler.Reconciler;
import io.kubernetes.client.informer.SharedInformerFactory;
-import io.kubernetes.client.spring.extended.controller.annotation.KubernetesReconciler;
import io.kubernetes.client.spring.extended.controller.factory.KubernetesControllerFactory;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import java.util.function.Supplier;
+import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
/**
@@ -34,18 +32,21 @@
*
It will create a {@link io.kubernetes.client.extended.controller.Controller} for every
* reconciler instances registered in the spring bean-factory.
*/
-public class KubernetesReconcilerProcessor implements BeanFactoryPostProcessor, Ordered {
+public class KubernetesReconcilerProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {
- private static final Logger log = LoggerFactory.getLogger(KubernetesReconcilerProcessor.class);
+ public static final String DEFAULT_SHARED_INFORMER_FACTORY_BEAN_NAME = "sharedInformerFactory";
- private ControllerManager controllerManager;
+ private final String sharedInformerFactoryBeanName;
- private ExecutorService controllerManagerDaemon = Executors.newSingleThreadExecutor();
+ private BeanDefinitionRegistry registry;
- private SharedInformerFactory sharedInformerFactory;
+ public KubernetesReconcilerProcessor() {
+ this(DEFAULT_SHARED_INFORMER_FACTORY_BEAN_NAME);
+ }
- public KubernetesReconcilerProcessor(SharedInformerFactory sharedInformerFactory) {
- this.sharedInformerFactory = sharedInformerFactory;
+ public KubernetesReconcilerProcessor(String sharedInformerFactoryBeanName) {
+ notNull(sharedInformerFactoryBeanName, "SharedInformerFactory bean name is required");
+ this.sharedInformerFactoryBeanName = sharedInformerFactoryBeanName;
}
@Override
@@ -54,20 +55,27 @@ public int getOrder() {
}
@Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
- throws BeansException {
- String[] names = beanFactory.getBeanNamesForType(Reconciler.class);
- for (String name : names) {
- Reconciler reconciler = (Reconciler) beanFactory.getBean(name);
- KubernetesReconciler kubernetesReconciler =
- reconciler.getClass().getAnnotation(KubernetesReconciler.class);
- String reconcilerName = kubernetesReconciler.value();
+ public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
+ this.registry = registry;
+ }
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ for (String reconcilerName : beanFactory.getBeanNamesForType(Reconciler.class)) {
+
+ Supplier kubernetesControllerFactorySupplier =
+ () ->
+ new KubernetesControllerFactory(
+ beanFactory.getBean(sharedInformerFactoryBeanName, SharedInformerFactory.class),
+ beanFactory.getBean(reconcilerName, Reconciler.class));
- KubernetesControllerFactory controllerFactory =
- new KubernetesControllerFactory(sharedInformerFactory, reconciler);
+ BeanDefinition controllerFactoryBeanDefinition =
+ BeanDefinitionBuilder.genericBeanDefinition(
+ KubernetesControllerFactory.class, kubernetesControllerFactorySupplier)
+ .getBeanDefinition();
- Controller controller = controllerFactory.getObject();
- beanFactory.registerSingleton(reconcilerName, controller);
+ registry.registerBeanDefinition(
+ reconcilerName + "Controller", controllerFactoryBeanDefinition);
}
}
}
diff --git a/spring/src/test/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessorTest.java b/spring/src/test/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessorTest.java
new file mode 100644
index 0000000000..db3e4f7df3
--- /dev/null
+++ b/spring/src/test/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessorTest.java
@@ -0,0 +1,107 @@
+/*
+Copyright 2020 The Kubernetes 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
+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 io.kubernetes.client.spring.extended.controller;
+
+import static org.junit.Assert.assertNotNull;
+
+import io.kubernetes.client.extended.controller.Controller;
+import io.kubernetes.client.extended.controller.reconciler.Reconciler;
+import io.kubernetes.client.extended.controller.reconciler.Request;
+import io.kubernetes.client.extended.controller.reconciler.Result;
+import io.kubernetes.client.informer.SharedInformer;
+import io.kubernetes.client.informer.SharedInformerFactory;
+import io.kubernetes.client.openapi.models.V1Pod;
+import io.kubernetes.client.openapi.models.V1PodList;
+import io.kubernetes.client.spring.extended.controller.annotation.GroupVersionResource;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesReconciler;
+import io.kubernetes.client.spring.extended.controller.annotation.KubernetesReconcilerWatches;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = KubernetesReconcilerProcessorTest.App.class)
+public class KubernetesReconcilerProcessorTest {
+
+ @SpringBootApplication
+ static class App {
+
+ @Bean
+ KubernetesReconcilerProcessor reconcilerProcessorUnderTesting() {
+ return new KubernetesReconcilerProcessor();
+ }
+
+ @Bean
+ SharedInformerFactory sharedInformerFactory() {
+ return new TestSharedInformerFactory();
+ }
+
+ @KubernetesInformers({
+ @KubernetesInformer(
+ apiTypeClass = V1Pod.class,
+ apiListTypeClass = V1PodList.class,
+ groupVersionResource = @GroupVersionResource(resourcePlural = "pods"))
+ })
+ static class TestSharedInformerFactory extends SharedInformerFactory {}
+
+ @Bean("testReconciler1")
+ TestReconciler testReconciler1ToBeInjected() {
+ return new TestReconciler();
+ }
+
+ @Bean("testReconciler2")
+ TestReconciler testReconciler2ToBeInjected() {
+ return new TestReconciler();
+ }
+ }
+
+ @KubernetesReconciler(watches = @KubernetesReconcilerWatches())
+ static class TestReconciler implements Reconciler {
+
+ @Autowired private SharedInformer informerToBeInjected;
+
+ @Override
+ public Result reconcile(Request request) {
+ return new Result(false);
+ }
+ }
+
+ @Autowired
+ @Qualifier("testReconciler1Controller")
+ private Controller controller1CreatedByReconcilerProcessor;
+
+ @Autowired
+ @Qualifier("testReconciler2Controller")
+ private Controller controller2CreatedByReconcilerProcessor;
+
+ @Autowired
+ @Qualifier("testReconciler1")
+ private TestReconciler testReconciler1ToBeInjected;
+
+ @Autowired
+ @Qualifier("testReconciler2")
+ private TestReconciler testReconciler2ToBeInjected;
+
+ @Test
+ public void testAutowiredFieldsOfReconcilerBeansAreSet() {
+ assertNotNull(testReconciler1ToBeInjected.informerToBeInjected);
+ assertNotNull(testReconciler2ToBeInjected.informerToBeInjected);
+ }
+}