Prefer Java configuration over XML.

Closes #2416
This commit is contained in:
Mark Paluch
2022-09-27 11:31:45 +02:00
parent bc983feac2
commit 5a4fb4b1a0
6 changed files with 105 additions and 15 deletions

View File

@@ -7,6 +7,7 @@ ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1
:spring-data-commons-docs: https://raw.githubusercontent.com/spring-projects/spring-data-commons/master/src/main/asciidoc
:spring-framework-javadoc: https://docs.spring.io/spring-framework/docs/{springVersion}/javadoc-api
:spring-framework-reference: https://docs.spring.io/spring-framework/docs/{springVersion}/reference/html
:store: Redis
(C) 2011-2022 The original authors.

View File

@@ -26,7 +26,7 @@ Note that the value returned from the `RedisCallback` is required to be `null`,
[TIP]
====
The Lettuce driver supports fine grained flush control that allows to either flush commands as they appear, buffer or send them at connection close.
The Lettuce driver supports fine-grained flush control that allows to either flush commands as they appear, buffer or send them at connection close.
[source,java]
----
@@ -35,5 +35,3 @@ factory.setPipeliningFlushPolicy(PipeliningFlushPolicy.buffered(3)); <1>
----
<1> Buffer locally and flush after every 3rd command.
====
include::version-note.adoc[]

View File

@@ -65,7 +65,8 @@ Consider the following interface definition:
----
public interface MessageDelegate {
void handleMessage(String message);
void handleMessage(Map message); void handleMessage(byte[] message);
void handleMessage(Map message);
void handleMessage(byte[] message);
void handleMessage(Serializable message);
// pass the channel/pattern as well
void handleMessage(Serializable message, String channel);
@@ -83,10 +84,36 @@ public class DefaultMessageDelegate implements MessageDelegate {
Notice how the above implementation of the `MessageDelegate` interface (the above `DefaultMessageDelegate` class) has *no* Redis dependencies at all. It truly is a POJO that we make into an MDP with the following configuration:
[source,xml]
====
.Java
[source,java,role="primary"]
----
@Configuration
class MyConfig {
// …
@Bean
DefaultMessageDelegate listener() {
return new DefaultMessageDelegate();
}
@Bean
RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory, DefaultMessageDelegate listener) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(new MessageListenerAdapter(listener, "handleMessage"), ChannelTopic.of("chatroom"));
return container;
}
}
----
.XML
[source,xml,role="secondary"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
@@ -100,12 +127,13 @@ Notice how the above implementation of the `MessageDelegate` interface (the abov
<bean id="listener" class="redisexample.DefaultMessageDelegate"/>
...
<beans>
</beans>
----
====
NOTE: The listener topic can be either a channel (for example, `topic="chatroom"`) or a pattern (for example, `topic="*room"`)
The preceding example uses the Redis namespace to declare the message listener container and automatically register the POJOs as listeners. The full blown beans definition follows:
The preceding example uses the Redis namespace to declare the message listener container and automatically register the POJOs as listeners. The full-blown beans definition follows:
[source,xml]
----

View File

@@ -25,8 +25,6 @@ System.out.println("Number of items added to set: " + txResults.get(0));
`RedisTemplate` uses its value, hash key, and hash value serializers to deserialize all results of `exec` before returning.
There is an additional `exec` method that lets you pass a custom serializer for transaction results.
include::version-note.adoc[]
[[tx.spring]]
== @Transactional Support

View File

@@ -391,7 +391,30 @@ Once configured, the template is thread-safe and can be reused across multiple i
For cases where you need a certain template view, declare the view as a dependency and inject the template. The container automatically performs the conversion, eliminating the `opsFor[X]` calls, as shown in the following example:
[source,xml]
====
.Java
[source,java,role="primary"]
----
@Configuration
class MyConfig {
@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
----
.XML
[source,xml,role="secondary"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
@@ -406,6 +429,7 @@ For cases where you need a certain template view, declare the view as a dependen
</beans>
----
====
[source,java]
----
@@ -430,7 +454,30 @@ public class Example {
Since it is quite common for the keys and values stored in Redis to be `java.lang.String`, the Redis modules provides two extensions to `RedisConnection` and `RedisTemplate`, respectively the `StringRedisConnection` (and its `DefaultStringRedisConnection` implementation) and `StringRedisTemplate` as a convenient one-stop solution for intensive String operations. In addition to being bound to `String` keys, the template and the connection use the `StringRedisSerializer` underneath, which means the stored keys and values are human-readable (assuming the same encoding is used both in Redis and your code). The following listings show an example:
[source,xml]
====
.Java
[source,java,role="primary"]
----
@Configuration
class MyConfig {
@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
----
.XML
[source,xml,role="secondary"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
@@ -441,9 +488,10 @@ Since it is quite common for the keys and values stored in Redis to be `java.lan
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="redisConnectionFactory"/>
...
</beans>
----
====
[source,java]
----
@@ -662,7 +710,24 @@ Package `org.springframework.data.redis.support` offers various reusable compone
The atomic counters make it easy to wrap Redis key incrementation while the collections allow easy management of Redis keys with minimal storage exposure or API leakage. In particular, the `RedisSet` and `RedisZSet` interfaces offer easy access to the set operations supported by Redis, such as `intersection` and `union`. `RedisList` implements the `List`, `Queue`, and `Deque` contracts (and their equivalent blocking siblings) on top of Redis, exposing the storage as a FIFO (First-In-First-Out), LIFO (Last-In-First-Out) or capped collection with minimal configuration. The following example shows the configuration for a bean that uses a `RedisList`:
[source,xml]
====
.Java
[source,java,role="primary"]
----
@Configuration
class MyConfig {
// …
@Bean
RedisList<String> stringRedisTemplate(RedisTemplate<String, String> redisTemplate) {
return new DefaultRedisList<>(template, "queue-key");
}
}
----
.XML
[source,xml,role="secondary"]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
@@ -677,6 +742,7 @@ The atomic counters make it easy to wrap Redis key incrementation while the coll
</beans>
----
====
The following example shows a Java configuration example for a `Deque`:

View File

@@ -1 +0,0 @@
NOTE: As of version 1.1, an important change has been made to the `exec` methods of `RedisConnection` and `RedisTemplate`. Previously, these methods returned the results of transactions directly from the connectors. This means that the data types often differed from those returned from the methods of `RedisConnection`. For example, `zAdd` returns a boolean indicating whether the element has been added to the sorted set. Most connectors return this value as a long, and Spring Data Redis performs the conversion. Another common difference is that most connectors return a status reply (usually the string, `OK`) for operations such as `set`. These replies are typically discarded by Spring Data Redis. Prior to 1.1, these conversions were not performed on the results of `exec`. Also, results were not deserialized in `RedisTemplate`, so they often included raw byte arrays. If this change breaks your application, set `convertPipelineAndTxResults` to `false` on your `RedisConnectionFactory` to disable this behavior.