19
19
import java .time .Duration ;
20
20
import java .util .concurrent .CompletableFuture ;
21
21
import java .util .concurrent .TimeUnit ;
22
+ import java .util .concurrent .locks .Lock ;
23
+ import java .util .concurrent .locks .ReentrantLock ;
22
24
23
- import com .rabbitmq .client .amqp .Connection ;
24
25
import com .rabbitmq .client .amqp .Consumer ;
25
26
import com .rabbitmq .client .amqp .Environment ;
26
27
import com .rabbitmq .client .amqp .Publisher ;
27
- import com .rabbitmq .client .amqp .PublisherBuilder ;
28
28
import com .rabbitmq .client .amqp .Resource ;
29
29
import org .jspecify .annotations .Nullable ;
30
30
42
42
import org .springframework .amqp .support .converter .SmartMessageConverter ;
43
43
import org .springframework .amqp .utils .JavaUtils ;
44
44
import org .springframework .beans .factory .DisposableBean ;
45
- import org .springframework .beans .factory .InitializingBean ;
46
45
import org .springframework .core .ParameterizedTypeReference ;
47
46
import org .springframework .util .Assert ;
48
47
54
53
*
55
54
* @since 4.0
56
55
*/
57
- public class RabbitAmqpTemplate implements AsyncAmqpTemplate , InitializingBean , DisposableBean {
56
+ public class RabbitAmqpTemplate implements AsyncAmqpTemplate , DisposableBean {
58
57
59
- private final Connection connection ;
58
+ private final AmqpConnectionFactory connectionFactory ;
60
59
61
- private final PublisherBuilder publisherBuilder ;
60
+ private final Lock instanceLock = new ReentrantLock () ;
62
61
63
- @ SuppressWarnings ("NullAway.Init" )
64
- private Publisher publisher ;
62
+ private @ Nullable Object publisher ;
65
63
66
64
private MessageConverter messageConverter = new SimpleMessageConverter ();
67
65
@@ -73,17 +71,20 @@ public class RabbitAmqpTemplate implements AsyncAmqpTemplate, InitializingBean,
73
71
74
72
private @ Nullable String defaultReceiveQueue ;
75
73
76
- public RabbitAmqpTemplate (Connection amqpConnection ) {
77
- this .connection = amqpConnection ;
78
- this .publisherBuilder = amqpConnection .publisherBuilder ();
74
+ private Resource .StateListener @ Nullable [] stateListeners ;
75
+
76
+ private Duration publishTimeout = Duration .ofSeconds (60 );
77
+
78
+ public RabbitAmqpTemplate (AmqpConnectionFactory connectionFactory ) {
79
+ this .connectionFactory = connectionFactory ;
79
80
}
80
81
81
82
public void setListeners (Resource .StateListener ... listeners ) {
82
- this .publisherBuilder . listeners ( listeners ) ;
83
+ this .stateListeners = listeners ;
83
84
}
84
85
85
86
public void setPublishTimeout (Duration timeout ) {
86
- this .publisherBuilder . publishTimeout ( timeout ) ;
87
+ this .publishTimeout = timeout ;
87
88
}
88
89
89
90
/**
@@ -100,15 +101,15 @@ public void setExchange(String exchange) {
100
101
/**
101
102
* Set a default routing key.
102
103
* Mutually exclusive with {@link #setQueue(String)}.
103
- * @param key the default routing key.
104
+ * @param routingKey the default routing key.
104
105
*/
105
- public void setKey (String key ) {
106
- this .defaultRoutingKey = key ;
106
+ public void setRoutingKey (String routingKey ) {
107
+ this .defaultRoutingKey = routingKey ;
107
108
}
108
109
109
110
/**
110
111
* Set default queue for publishing.
111
- * Mutually exclusive with {@link #setExchange(String)} and {@link #setKey (String)}.
112
+ * Mutually exclusive with {@link #setExchange(String)} and {@link #setRoutingKey (String)}.
112
113
* @param queue the default queue.
113
114
*/
114
115
public void setQueue (String queue ) {
@@ -137,14 +138,36 @@ private String getRequiredQueue() throws IllegalStateException {
137
138
return name ;
138
139
}
139
140
140
- @ Override
141
- public void afterPropertiesSet () {
142
- this .publisher = this .publisherBuilder .build ();
141
+ private Publisher getPublisher () {
142
+ Object publisherToReturn = this .publisher ;
143
+ if (publisherToReturn == null ) {
144
+ this .instanceLock .lock ();
145
+ try {
146
+ publisherToReturn = this .publisher ;
147
+ if (publisherToReturn == null ) {
148
+ publisherToReturn =
149
+ this .connectionFactory .getConnection ()
150
+ .publisherBuilder ()
151
+ .listeners (this .stateListeners )
152
+ .publishTimeout (this .publishTimeout )
153
+ .build ();
154
+ this .publisher = publisherToReturn ;
155
+ }
156
+ }
157
+ finally {
158
+ this .instanceLock .unlock ();
159
+ }
160
+ }
161
+ return (Publisher ) publisherToReturn ;
143
162
}
144
163
145
164
@ Override
146
165
public void destroy () {
147
- this .publisher .close ();
166
+ Object publisherToClose = this .publisher ;
167
+ if (publisherToClose != null ) {
168
+ ((Publisher ) publisherToClose ).close ();
169
+ this .publisher = null ;
170
+ }
148
171
}
149
172
150
173
/**
@@ -178,7 +201,7 @@ public CompletableFuture<Boolean> send(String exchange, @Nullable String routing
178
201
private CompletableFuture <Boolean > doSend (@ Nullable String exchange , @ Nullable String routingKey ,
179
202
@ Nullable String queue , Message message ) {
180
203
181
- com .rabbitmq .client .amqp .Message amqpMessage = this . publisher .message ();
204
+ com .rabbitmq .client .amqp .Message amqpMessage = getPublisher () .message ();
182
205
com .rabbitmq .client .amqp .Message .MessageAddressBuilder address = amqpMessage .toAddress ();
183
206
JavaUtils .INSTANCE
184
207
.acceptIfNotNull (exchange , address ::exchange )
@@ -191,7 +214,7 @@ private CompletableFuture<Boolean> doSend(@Nullable String exchange, @Nullable S
191
214
192
215
CompletableFuture <Boolean > publishResult = new CompletableFuture <>();
193
216
194
- this . publisher .publish (amqpMessage ,
217
+ getPublisher () .publish (amqpMessage ,
195
218
(context ) -> {
196
219
switch (context .status ()) {
197
220
case ACCEPTED -> publishResult .complete (true );
@@ -271,7 +294,8 @@ public CompletableFuture<Message> receive(String queueName) {
271
294
CompletableFuture <Message > messageFuture = new CompletableFuture <>();
272
295
273
296
Consumer consumer =
274
- this .connection .consumerBuilder ()
297
+ this .connectionFactory .getConnection ()
298
+ .consumerBuilder ()
275
299
.queue (queueName )
276
300
.initialCredits (1 )
277
301
.priority (10 )
0 commit comments