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**
This commit is contained in:
Artem Bilan
2019-01-22 18:27:08 -05:00
committed by Gary Russell
parent 119db815c2
commit 690a2c3c3e
2 changed files with 73 additions and 18 deletions

View File

@@ -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<S extends IntegrationComponentSpec<S, T>, T>
implements FactoryBean<T>, InitializingBean, DisposableBean {
extends AbstractFactoryBean<T>
implements SmartLifecycle {
protected static final SpelExpressionParser PARSER = new SpelExpressionParser();
@@ -70,27 +73,74 @@ public abstract class IntegrationComponentSpec<S extends IntegrationComponentSpe
return this.target;
}
@Override
public T getObject() {
return get();
}
@Override
public Class<?> 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;
}
}

View File

@@ -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)