Spring Integration 示例

工程 | Mark Fisher | 2007年12月21日 | ...

在我最近的帖子中,我提到 Spring Integration 的 Subversion 存储库很快就会公开访问,我很高兴现在提供该链接。您可以使用以下命令检出该项目

svn co https://anonsvn.springframework.org/svn/spring-integration/base/trunk spring-integration

如果检出成功,您应该看到以下目录结构

spring-integration/
  +--build-spring-integration/
  +--spring-build/
  +--spring-integration-core/
  +--spring-integration-samples/

我想借此机会介绍一下 'spring-integration-samples' 中的几个示例。 请记住,此项目绝对是一个正在进行中的工作(目前是 0.5 SNAPSHOT),但这些示例应该让您了解编程模型是如何形成的,我非常期待收到一些反馈。

Hello World

第一个示例是强制性的“Hello World”演示。 这演示了主要组件:消息通道和消息端点。 此演示还揭示了 Spring Integration 方法是如何非侵入性的 - 在业务逻辑和消息传递之间提供完全的分离。 在这种情况下,“业务逻辑”是一个简单的 HelloService

public class HelloService {

    public String sayHello(String name) {
        return "Hello " + name;
    }
}

此示例使用基于 XML 的配置来配置消息端点(我们接下来将看到注解方法)


<endpoint input-channel="inputChannel"
               default-output-channel="outputChannel"
               handler-ref="helloService"
               handler-method="sayHello"/>

您会看到“handler-ref”只是指向一个 Spring 管理的 bean。 如果您已经使用 Spring 的 MessageListenerAdapter 进行异步 JMS 接收,那么这应该看起来很熟悉 - 特别是如果您正在使用 Spring 2.5 的新 jms 命名空间和“jms:listener”元素。 最后,HelloWorldDemo 启动应用程序上下文,然后与通道交互


ChannelRegistry channelRegistry = (ChannelRegistry) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
MessageChannel inputChannel = channelRegistry.lookupChannel("inputChannel");
MessageChannel outputChannel = channelRegistry.lookupChannel("outputChannel");
inputChannel.send(new StringMessage(1, "World"));
System.out.println(outputChannel.receive().getPayload());

该示例涉及查找 MessageBus bean - 它实现了 ChannelRegistry 接口。 但是,在非演示“真实世界”场景中,任何访问通道的组件都可以通过依赖注入提供注册表。 它所需要做的就是实现 ChannelRegistryAware(或使用 @Autowired)。 这与 Spring 中其他地方使用的方法相同 - 例如 ApplicationEventPublisherAware

注解驱动的端点和订阅者

下一个示例展示了如何使用注解配置消息端点。 事实上,这个特定的端点甚至提供了数据,这些数据(在幕后)使用 @Polled 方法注解转换为消息有效负载内容。 它可以选择为异步接收消息提供输入通道。

@MessageEndpoint(defaultOutput="quotes")
public class QuotePublisher {

    @Polled(period=300)
    public Quote getQuote() {
        BigDecimal price = new BigDecimal(new Random().nextDouble() * 100);
        return new Quote(generateTicker(), price.setScale(2, RoundingMode.HALF_EVEN));
    }

    private String generateTicker() {
        // randomly generates 3-letter tickers
    }
}

在接收端,有一个 @Subscriber 注解


public class QuoteSubscriber {

    @Subscriber(channel="quotes")
    public void log(Object o) {
        System.out.println(o);
    }
}

这是注册注解后处理器和 2 个 Spring 管理的 bean 的 XML(请注意,此示例使用 'spring-integration' schema 作为主要命名空间。


<beans:beans xmlns="http://www.springframework.org/schema/integration"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/integration
                http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">

    <message-bus/>

    <annotation-driven/>

    <channel id="quotes"/>

    <beans:bean id="publisher" class="org.springframework.integration.samples.quote.QuotePublisher"/>

    <beans:bean id="subscriber" class="org.springframework.integration.samples.quote.QuoteSubscriber"/>

</beans:beans>

顺便说一句,“annotation-driven”元素还启用了 @Publisher 注解,该注解触发 AOP advice 的创建,用于将任何带注解的方法的返回值异步发送到通道。

简单路由

路由示例的特点是消息端点每 3 秒生成一个递增的整数,以及一个路由器解析目标通道名称(请注意,路由器方法也可以返回多个结果,并且可以返回实际的 MessageChannel 实例,而不是名称)。

@MessageEndpoint
public class Counter {

    private AtomicInteger count = new AtomicInteger();

    @Polled(period=3000)
    public int getNumber() {
        return count.incrementAndGet();
    }

    @Router
    public String resolveChannel(int i) {
        if (i % 2 == 0) {
            return "even";
        }
        return "odd";
    }
}

在这些通道的接收端,我们有 2 个不同的方法,它们只是记录消息有效负载


@Component
public class NumberLogger {

    @Subscriber(channel="even")
    public void even(int i) {
        System.out.println("even: " + i);
    }

    @Subscriber(channel="odd")
    public void odd(int i) {
        System.out.println("odd:  " + i);
    }
}

顺便说一句,请注意 NumberLogger 使用 Spring 的 @Component 进行注解。 @MessageEndpoint 注解还包含 @Component 作为元注解。 因此,两者都是“原型”,并且有资格使用 Spring 2.5 的类路径扫描进行自动检测。 此示例的 XML 非常简单


<context:component-scan base-package="org.springframework.integration.samples.oddeven"/>

<message-bus auto-create-channels="true"/>

<annotation-driven/>

希望这能对 Spring Integration 编程模型提供一个不错的介绍。 随意检出代码并亲自尝试这些示例。 我目前正在编写“入门”指南,我将在假期后提供该指南。 如果您检出代码,请务必经常更新。 代码在不断发展,特别是,我正在重构许多核心的 consumer/dispatcher 代码,目的是为添加轮询或事件驱动的消息源提供尽可能简单的扩展点。 在下一篇博客文章中,我计划展示一些添加到“spring-integration-samples”的新内容,这些新内容具有这些扩展点。

获取 Spring 新闻简报

通过 Spring 新闻简报保持联系

订阅

更上一层楼

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部