From 690a2c3c3e6ec0ad8cdb00edb901076ae0d2b96f Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Tue, 22 Jan 2019 18:27:08 -0500 Subject: [PATCH] Implement Lifecycle for IntegrationComponentSpec Since an `IntegrationComponentSpec` is a `FactoryBean`, all it's target callbacks and lifecycle is controlled over a `FactoryBean`. * Add `SmartLifecycle` for the `IntegrationComponentSpec` to delegate lifecycle hooks to the `target` if necessary * Refactor `IntegrationComponentSpec` to be an `AbstractFactoryBean` which is a central place for the `FactoryBean`, `InitializingBean` and `DisposableBean` interfaces **Cherry-pick to 5.0.x** --- .../dsl/IntegrationComponentSpec.java | 78 +++++++++++++++---- .../integration/http/dsl/HttpDslTests.java | 13 +++- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationComponentSpec.java b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationComponentSpec.java index 9326ba97ed..059d589db4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationComponentSpec.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationComponentSpec.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 the original author or authors. + * Copyright 2016-2019 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. @@ -20,8 +20,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.context.Lifecycle; +import org.springframework.context.SmartLifecycle; import org.springframework.expression.spel.standard.SpelExpressionParser; /** @@ -35,7 +37,8 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; * @since 5.0 */ public abstract class IntegrationComponentSpec, T> - implements FactoryBean, InitializingBean, DisposableBean { + extends AbstractFactoryBean + implements SmartLifecycle { protected static final SpelExpressionParser PARSER = new SpelExpressionParser(); @@ -70,27 +73,74 @@ public abstract class IntegrationComponentSpec getObjectType() { return get().getClass(); } @Override - public void afterPropertiesSet() throws Exception { - if (this.target instanceof InitializingBean) { - ((InitializingBean) this.target).afterPropertiesSet(); + protected T createInstance() throws Exception { + T instance = get(); + if (instance instanceof InitializingBean) { + ((InitializingBean) instance).afterPropertiesSet(); + } + return instance; + } + + @Override + protected void destroyInstance(T instance) throws Exception { + if (instance instanceof DisposableBean) { + ((DisposableBean) instance).destroy(); } } @Override - public void destroy() throws Exception { - if (this.target instanceof DisposableBean) { - ((DisposableBean) this.target).destroy(); + public void start() { + T instance = get(); + if (instance instanceof Lifecycle) { + ((Lifecycle) instance).start(); + } + } + + @Override + public void stop() { + T instance = get(); + if (instance instanceof Lifecycle) { + ((Lifecycle) instance).stop(); + } + } + + @Override + public boolean isRunning() { + T instance = get(); + return !(instance instanceof Lifecycle) || ((Lifecycle) instance).isRunning(); + } + + @Override + public boolean isAutoStartup() { + T instance = get(); + return instance instanceof SmartLifecycle && ((SmartLifecycle) instance).isAutoStartup(); + } + + @Override + public void stop(Runnable callback) { + T instance = get(); + if (instance instanceof SmartLifecycle) { + ((SmartLifecycle) instance).stop(callback); + } + else { + callback.run(); + } + } + + @Override + public int getPhase() { + T instance = get(); + if (instance instanceof SmartLifecycle) { + return ((SmartLifecycle) instance).getPhase(); + } + else { + return 0; } } diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java index b8498884c3..400dd96ba8 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/dsl/HttpDslTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 the original author or authors. + * Copyright 2016-2019 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. @@ -210,12 +210,17 @@ public class HttpDslTests { .get(); } + @Bean + public HttpRequestHandlerEndpointSpec httpService() { + return Http.inboundGateway("/service") + .requestMapping(r -> r.params("name")) + .errorChannel("httpProxyErrorFlow.input"); + } + @Bean public IntegrationFlow httpProxyFlow() { return IntegrationFlows - .from(Http.inboundGateway("/service") - .requestMapping(r -> r.params("name")) - .errorChannel("httpProxyErrorFlow.input")) + .from(httpService()) .handle(Http.outboundGateway("/service/internal?{params}") .uriVariable("params", "payload") .expectedResponseType(String.class)