Add auto-configuration for Redis annotation-driven listeners

This commit adds support for `@RedisListener` by providing the
infrastructure to register those endpoints using a default
`RedisMessageListenerContainer`.

Users wishing to configure additional containers can benefit from
`RedisMessageListenerContainerConfigurer`. The default container can
be tuned using new properties in the `spring.data.redis.listener`
namespace.

Closes gh-49858
This commit is contained in:
Stéphane Nicoll
2026-04-13 13:24:25 +02:00
parent 3087d96686
commit 495d16b1f8
15 changed files with 688 additions and 1 deletions
@@ -108,6 +108,30 @@ spring:
[[data.nosql.redis.receiving]]
=== Receiving a Message
When the Redis infrastructure is present, any bean can be annotated with javadoc:org.springframework.data.redis.annotation.RedisListener[format=annotation] to create a listener endpoint.
If no javadoc:org.springframework.data.redis.listener.RedisMessageListenerContainer[] has been defined, a default one is configured automatically.
The following component creates a listener endpoint on the `someChannel` channel:
include-code::MyBean[]
TIP: See the javadoc:org.springframework.data.redis.annotation.EnableRedisListeners[format=annotation] API documentation for more details.
If you need to create more javadoc:org.springframework.data.redis.listener.RedisMessageListenerContainer[] instances or if you want to override the default, Spring Boot provides a javadoc:org.springframework.boot.data.redis.autoconfigure.RedisMessageListenerContainerConfigurer[] that you can use to initialize a javadoc:org.springframework.data.redis.listener.RedisMessageListenerContainer[] with the same settings as the one that is auto-configured.
For instance, the following example exposes another container that uses a specific javadoc:org.springframework.data.redis.connection.RedisConnectionFactory[]:
include-code::custom/MyRedisConfiguration[]
Then you can use the container in any javadoc:org.springframework.data.redis.annotation.RedisListener[format=annotation]-annotated method as follows:
include-code::custom/MyBean[]
[[data.nosql.mongodb]]
== MongoDB
@@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving;
import org.springframework.data.redis.annotation.RedisListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@RedisListener("someChannel")
public void processMessage(String content) {
// ...
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving.custom;
import org.springframework.data.redis.annotation.RedisListener;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@RedisListener(topic = "someChannel", container = "myRedisMessageListenerContainer")
public void processMessage(String content) {
// ...
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving.custom;
import org.springframework.boot.data.redis.autoconfigure.RedisMessageListenerContainerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
@Configuration(proxyBeanMethods = false)
public class MyRedisConfiguration {
@Bean
public RedisMessageListenerContainer myRedisMessageListenerContainer(
RedisMessageListenerContainerConfigurer configurer, RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
configurer.configure(container, connectionFactory);
// ... custom configuration
return container;
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving
import org.springframework.data.redis.annotation.RedisListener
import org.springframework.stereotype.Component
@Component
class MyBean {
@RedisListener("someChannel")
fun processMessage(content: String) {
// ...
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving.custom
import org.springframework.data.redis.annotation.RedisListener
import org.springframework.stereotype.Component
@Component
class MyBean {
@RedisListener(topic = "someChannel", container = "myRedisMessageListenerContainer")
fun processMessage(content: String) {
// ...
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2012-present 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.docs.data.nosql.redis.receiving.custom
import org.springframework.boot.data.redis.autoconfigure.RedisMessageListenerContainerConfigurer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.listener.RedisMessageListenerContainer
@Configuration(proxyBeanMethods = false)
class MyRedisConfiguration {
@Bean
fun myRedisMessageListenerContainer(
configurer: RedisMessageListenerContainerConfigurer,
connectionFactory: RedisConnectionFactory
): RedisMessageListenerContainer {
val container = RedisMessageListenerContainer()
configurer.configure(container, connectionFactory)
// ... custom configuration
return container
}
}