アノテーションサポート
メッセージエンドポイントを構成するための XML 名前空間のサポートに加えて、アノテーションも使用できます。まず、Spring Integration は、クラスレベルの @MessageEndpoint
をステレオタイプアノテーションとして提供します。つまり、Spring の @Component
アノテーションが付けられているため、Spring のコンポーネントスキャンによって Bean 定義として自動的に認識されます。
さらに重要なのは、さまざまなメソッドレベルのアノテーションです。それらは、アノテーション付きメソッドがメッセージを処理できることを示しています。次の例は、クラスレベルとメソッドレベルの両方のアノテーションを示しています。
@MessageEndpoint
public class FooService {
@ServiceActivator
public void processMessage(Message message) {
...
}
}
メソッドがメッセージを「処理」することの正確な意味は、特定のアノテーションに依存します。Spring Integration で使用できるアノテーションは次のとおりです。
@Aggregator
( アグリゲーターを参照してください)@Filter
( フィルターを参照してください)@Router
( ルーターを参照してください)@ServiceActivator
( サービスアクティベーターを参照してください)@Splitter
( スプリッターを参照してください)@Transformer
(Transformer を参照してください)@InboundChannelAdapter
( チャンネルアダプターを参照してください)@BridgeFrom
(Java 構成を使用したブリッジの構成を参照してください)@BridgeTo
(Java 構成を使用したブリッジの構成を参照してください)@MessagingGateway
( メッセージングゲートウェイを参照してください)@IntegrationComponentScan
( 構成と@EnableIntegration
を参照してください)
XML 構成をアノテーションと組み合わせて使用する場合、@MessageEndpoint アノテーションは必要ありません。<service-activator/> 要素の ref 属性から POJO 参照を設定する場合、メソッドレベルのアノテーションのみを提供できます。その場合、メソッドレベルの属性が <service-activator/> 要素に存在しない場合でも、アノテーションによってあいまいさが回避されます。 |
ほとんどの場合、アノテーション付きハンドラーメソッドは、パラメーターとして Message
型を必要としません。代わりに、次の例に示すように、メソッドパラメーター型はメッセージのペイロード型と一致できます。
public class ThingService {
@ServiceActivator
public void bar(Thing thing) {
...
}
}
メソッドパラメーターを MessageHeaders
の値からマップする必要がある場合、別のオプションはパラメーターレベルの @Header
アノテーションを使用することです。一般に、Spring Integration アノテーションが付けられたメソッドは、Message
自体、メッセージペイロード、ヘッダー値(@Header
を使用)をパラメーターとして受け入れることができます。実際、次の例に示すように、メソッドは組み合わせを受け入れることができます。
public class ThingService {
@ServiceActivator
public void otherThing(String payload, @Header("x") int valueX, @Header("y") int valueY) {
...
}
}
次の例に示すように、@Headers
アノテーションを使用して、すべてのメッセージヘッダーを Map
として提供することもできます。
public class ThingService {
@ServiceActivator
public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
...
}
}
アノテーションの値は SpEL 式(someHeader.toUpperCase() など)にすることもできます。これは、挿入する前にヘッダー値を操作する場合に便利です。また、オプションの required プロパティも提供します。このプロパティは、ヘッダー内で属性値を使用可能にする必要があるかどうかを指定します。required プロパティのデフォルト値は true です。 |
これらのアノテーションのいくつかについて、メッセージ処理メソッドが null 以外の値を返すと、エンドポイントは応答を送信しようとします。これは、このようなエンドポイントの出力チャネルが使用され(使用可能な場合)、REPLY_CHANNEL
メッセージヘッダー値がフォールバックとして使用されるという点で、両方の構成オプション(名前空間とアノテーション)で一貫しています。
エンドポイントの出力チャネルと応答チャネルメッセージヘッダーの組み合わせにより、パイプラインアプローチが可能になります。複数のコンポーネントに出力チャネルがあり、最終コンポーネントにより応答メッセージを応答チャネルに転送できます(元のリクエストメッセージで指定されています)。つまり、最終的なコンポーネントは元の送信者から提供された情報に依存し、結果として任意の数のクライアントを動的にサポートできます。これは、返信先アドレス (英語) パターンの例です。 |
ここに示す例に加えて、これらのアノテーションは、次の例が示すように、inputChannel
および outputChannel
プロパティもサポートします。
@Service
public class ThingService {
@ServiceActivator(inputChannel="input", outputChannel="output")
public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
...
}
}
これらのアノテーションの処理により、対応する XML コンポーネント (AbstractEndpoint
インスタンスおよび MessageHandler
インスタンス (または受信チャネルアダプターの場合は MessageSource
インスタンス)) と同じ Bean が作成されます。@Bean
メソッドのアノテーションを参照してください。Bean 名は、パターン [componentName].[methodName].[decapitalizedAnnotationClassShortName]
から生成されます。前述の例では、Bean 名は AbstractEndpoint
の場合は thingService.otherThing.serviceActivator
であり、MessageHandler
(MessageSource
) Bean の場合は同じ名前に .handler
(.source
) サフィックスが追加されています。このような名前は、これらのメッセージングアノテーションとともに @EndpointId
アノテーションを使用してカスタマイズできます。MessageHandler
インスタンス (MessageSource
インスタンス) もメッセージ履歴で追跡できます。
バージョン 4.0 以降、すべてのメッセージングアノテーションは、アプリケーションコンテキストの初期化時にエンドポイントのライフサイクル制御を可能にするために、SmartLifecycle
オプション (autoStartup
および phase
) を提供します。これらは、それぞれ true
および 0
にデフォルト設定されます。エンドポイント ( start()
や stop()
など) の状態を変更するには、BeanFactory
(またはオートワイヤリング) を使用してエンドポイント Bean への参照を取得し、メソッドを呼び出します。または、制御バスにコマンドメッセージを送信することもできます。これらの目的には、前の段落で前述した beanName
を使用する必要があります。
上記のアノテーション(特定のチャネル Bean が構成されていない場合)の解析後に自動的に作成されたチャネル、および対応するコンシューマーエンドポイントは、コンテキスト初期化の終わり近くで Bean として宣言されます。これらの Bean は他のサービスでオートワイヤーできますが、通常は通常のオートワイヤー処理中に定義がまだ利用できないため、
|
バージョン 6.0 から、すべてのメッセージングアノテーションが @Repeatable
になりました。そのため、同じ型のいくつかを同じサービスメソッドで宣言できます。これは、それらのアノテーションが繰り返されるのと同じ数のエンドポイントを作成するという意味です。
@Transformer(inputChannel = "inputChannel1", outputChannel = "outputChannel1")
@Transformer(inputChannel = "inputChannel2", outputChannel = "outputChannel2")
public String transform(String input) {
return input.toUpperCase();
}
@Poller
アノテーションの使用
Spring Integration 4.0 より前のメッセージングアノテーションでは、inputChannel
が SubscribableChannel
への参照である必要がありました。PollableChannel
インスタンスの場合、<int:poller/>
を構成し、複合エンドポイントを PollingConsumer
にするために <int:bridge/>
要素が必要でした。次の例に示すように、バージョン 4.0 には @Poller
アノテーションが導入され、メッセージングアノテーションで poller
属性を直接設定できるようになりました。
public class AnnotationService {
@Transformer(inputChannel = "input", outputChannel = "output",
poller = @Poller(maxMessagesPerPoll = "${poller.maxMessagesPerPoll}", fixedDelay = "${poller.fixedDelay}"))
public String handle(String payload) {
...
}
}
@Poller
アノテーションは、単純な PollerMetadata
オプションのみを提供します。プロパティプレースホルダーを使用して、@Poller
アノテーションの属性(maxMessagesPerPoll
、fixedDelay
、fixedRate
、cron
)を構成できます。また、バージョン 5.1 以降、PollingConsumer
用の receiveTimeout
オプションも提供されます。より多くのポーリングオプション(たとえば、transaction
、advice-chain
、error-handler
など)を提供する必要がある場合は、PollerMetadata
を汎用 Bean として構成し、その Bean 名を @Poller
の value
属性として使用する必要があります。この場合、他の属性は許可されません(PollerMetadata
Bean で指定する必要があります)。inputChannel
が PollableChannel
であり、@Poller
が構成されていない場合、デフォルトの PollerMetadata
が使用されることに注意してください(アプリケーションコンテキストに存在する場合)。@Configuration
アノテーションを使用してデフォルトのポーラーを宣言するには、次の例のようなコードを使用します。
@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(10));
return pollerMetadata;
}
次の例は、デフォルトのポーラーの使用方法を示しています。
public class AnnotationService {
@Transformer(inputChannel = "aPollableChannel", outputChannel = "output")
public String handle(String payload) {
...
}
}
次の例は、名前付きポーラーの使用方法を示しています。
@Bean
public PollerMetadata myPoller() {
PollerMetadata pollerMetadata = new PollerMetadata();
pollerMetadata.setTrigger(new PeriodicTrigger(1000));
return pollerMetadata;
}
次の例は、デフォルトのポーラーを使用するエンドポイントを示しています。
public class AnnotationService {
@Transformer(inputChannel = "aPollableChannel", outputChannel = "output"
poller = @Poller("myPoller"))
public String handle(String payload) {
...
}
}
バージョン 4.3.3 以降、@Poller
アノテーションには errorChannel
属性があり、基礎となる MessagePublishingErrorHandler
を簡単に構成できます。この属性は、<poller>
XML コンポーネントの error-channel
と同じロールを果たします。詳細については、エンドポイント名前空間のサポートを参照してください。
メッセージングアノテーションの poller()
属性は、reactive()
属性と相互に排他的です。詳細については、次のセクションを参照してください。
@Reactive
アノテーションの使用
ReactiveStreamsConsumer
はバージョン 5.0 から存在しますが、エンドポイントの入力チャネルが FluxMessageChannel
(または任意の org.reactivestreams.Publisher
実装)である場合にのみ適用されました。バージョン 5.3 以降、ターゲットメッセージハンドラーが入力チャネル型に関係なく ReactiveMessageHandler
である場合、そのインスタンスもフレームワークによって作成されます。@Reactive
サブアノテーション(上記の @Poller
と同様)は、バージョン 5.5 以降のすべてのメッセージングアノテーションに導入されました。オプションの Function<? super Flux<Message<?>>, ? extends Publisher<Message<?>>>
Bean 参照を受け入れ、入力チャネル型およびメッセージハンドラーとは関係なく、ターゲットエンドポイントを ReactiveStreamsConsumer
インスタンスに変換します。この関数は、Flux.transform()
オペレーターから使用され、入力チャネルからのリアクティブストリームソースにカスタマイズ(publishOn()
、doOnNext()
、log()
、retry()
など)を適用します。
次の例は、最終的なサブスクライバーとプロデューサーに関係なく、公開スレッドを入力チャネルからその DirectChannel
に変更する方法を示しています。
@Bean
public Function<Flux<?>, Flux<?>> publishOnCustomizer() {
return flux -> flux.publishOn(Schedulers.parallel());
}
@ServiceActivator(inputChannel = "directChannel", reactive = @Reactive("publishOnCustomizer"))
public void handleReactive(String payload) {
...
}
メッセージングアノテーションの reactive()
属性は、poller()
属性と相互に排他的です。詳細については、@Poller
アノテーションの使用および Reactive Streams サポートを参照してください。
@InboundChannelAdapter
アノテーションの使用
バージョン 4.0 では、@InboundChannelAdapter
メソッドレベルのアノテーションが導入されました。アノテーション付きメソッドの MethodInvokingMessageSource
に基づいて SourcePollingChannelAdapter
統合コンポーネントを生成します。このアノテーションは <int:inbound-channel-adapter>
XML コンポーネントに類似しており、同じ制限があります。メソッドにはパラメーターを指定できません。戻り値の型は void
であってはなりません。(とオプションの @Poller
アノテーション、value
(必要な MessageChannel
Bean 名)と poller
: これは、2 つの属性があり、前述の)。MessageHeaders
を提供する必要がある場合は、Message<?>
戻り型を使用し、MessageBuilder
を使用して Message<?>
を作成します。MessageBuilder
を使用すると、MessageHeaders
を構成できます。次の例は、@InboundChannelAdapter
アノテーションの使用方法を示しています。
@InboundChannelAdapter("counterChannel")
public Integer count() {
return this.counter.incrementAndGet();
}
@InboundChannelAdapter(value = "fooChannel", poller = @Poller(fixed-rate = "5000"))
public String foo() {
return "foo";
}
バージョン 4.3 では、value
アノテーション属性の channel
エイリアスが導入され、ソースコードの読みやすさが向上しました。また、ターゲット MessageChannel
Bean は、初期化段階ではなく、最初の receive()
呼び出しで提供された名前(outputChannelName
オプションで設定)によって SourcePollingChannelAdapter
で解決されます。これにより、「遅延バインディング」ロジックが可能になります。コンシューマーの観点からのターゲット MessageChannel
Bean が作成され、@InboundChannelAdapter
解析フェーズよりも少し遅れて登録されます。
最初の例では、デフォルトポーラーがアプリケーションコンテキストの他の場所で宣言されている必要があります。
@MessagingGateway
アノテーションの使用
@MessagingGateway
アノテーションを参照してください。
@IntegrationComponentScan
アノテーションの使用
標準の Spring Framework @ComponentScan
アノテーションは、ステレオタイプ @Component
アノテーションのインターフェースをスキャンしません。この制限を克服し、@MessagingGateway
(@MessagingGateway
アノテーションを参照)の構成を可能にするために、@IntegrationComponentScan
メカニズムを導入しました。このアノテーションは、@Configuration
アノテーションとともに配置し、basePackages
や basePackageClasses
などのスキャンオプションを定義するようにカスタマイズする必要があります。この場合、@MessagingGateway
のアノテーションが付けられたすべての検出されたインターフェースが解析され、GatewayProxyFactoryBean
インスタンスとして登録されます。他のすべてのクラスベースのコンポーネントは、標準の @ComponentScan
によって解析されます。