Spring Integration Annotations和SmartLifecycle接口

时间:2014-12-01 15:38:36

标签: java spring spring-integration

我需要将一些遗留代码移植到基于Spring集成的应用程序中。我决定通过@InboundChannelAdapter注释配置入站通道适配器,该注释按预期工作。

问题是,当调用入站通道适配器的start()stop()方法时,我需要执行一些代码。

我尝试通过实现SmartLifecycle接口来解决这个问题,但这并没有让我感到满意。有没有人有任何其他建议我应该尝试?我现在卡住了...

编辑:代码示例

@MessageEndpoint
@Component
public class InputSource implements SmartLifecycle {
    public void start() {
        //my code to be executed
    }

    public void stop() {
        //my code
    }

    @InboundChannelAdapter("some.channel")
    public Message<?> read() {
        //my code that returns a message
    }

}

启动入站通道适配器时会调用read()方法中的代码,但在创建上下文时不会调用start()

1 个答案:

答案 0 :(得分:1)

什么版本的Spring Integration?对于4.1.0 ...

,这对我来说很好
@EnableIntegration
@MessageEndpoint
@Component
public class InputSource implements SmartLifecycle {

    private boolean running;

    @Override
    public void start() {
        System.out.println("start");
        running = true;
    }

    @Override
    public void stop() {
        running = false;
    }

    @InboundChannelAdapter(value = "toRabbit", poller = @Poller(fixedDelay = "5000", maxMessagesPerPoll = "1"))
    public Message<?> read() {
        return new GenericMessage<String>("foo");
    }

    @Override
    public boolean isRunning() {
        return running;
    }

    @Override
    public int getPhase() {
        return 0;
    }

    @Override
    public boolean isAutoStartup() {
        return true;
    }

    @Override
    public void stop(Runnable callback) {
        stop();
        callback.run();
    }

}

(即使没有@EnableIntegration调用start()方法也是如此。

在任何情况下,请记住这里的开始/停止位于不同的bean(InputSource)上,而适配器上的开始/停止位于SourcePollingChannelAdapter上。您可以使用phase控制订单。

修改

根据您的评论,您希望适配器启动其来源。即使我们这样做了......

if (this.source implements Lifecycle) {
    ((Lifecycle) source).start();
}

...它在这里不起作用,因为源不是你的组件,它是MethodInvokingMessageSource,它对bean的其余部分一无所知,只是read()方法。

一个解决方法是继承SourcePollingChannelAdapter并覆盖它的doStart()方法......

@Override // guarded by super#lifecycleLock
protected void doStart() {
     myInputSource.start();
     super.doStart();
}

您必须手动连接此(和您的bean)。可能最容易做的就是使用InputSource工具MessageSource ...

@Component
public class InputSource implements MessageSource<String>, Lifecycle {

    private boolean running;

    @Override
    public void start() {
        System.out.println("start");
        running = true;
    }

    @Override
    public void stop() {
        running = false;
    }

    @Override
    public Message<String> receive() {
        return new GenericMessage<String>("foo");
    }

    @Override
    public boolean isRunning() {
        return running;
    }

}

并将其与投票信息一起发送到MySPCA

我创建了一个Improvement JIRA Issue来支持这个用例。

谢谢!