32
32
import org .springframework .transaction .support .TransactionSynchronization ;
33
33
import org .springframework .transaction .support .TransactionSynchronizationManager ;
34
34
import org .springframework .util .Assert ;
35
+ import org .springframework .util .ReflectionUtils ;
36
+ import org .springframework .util .StringUtils ;
35
37
36
38
/**
37
39
* Helper class that provides static methods for obtaining {@link RedisConnection} from a
@@ -320,8 +322,8 @@ private static RedisConnection getTargetConnection(RedisConnection connection) {
320
322
*/
321
323
public static void unbindConnection (RedisConnectionFactory factory ) {
322
324
323
- RedisConnectionHolder connectionHolder =
324
- ( RedisConnectionHolder ) TransactionSynchronizationManager .getResource (factory );
325
+ RedisConnectionHolder connectionHolder = ( RedisConnectionHolder ) TransactionSynchronizationManager
326
+ .getResource (factory );
325
327
326
328
if (connectionHolder == null ) {
327
329
return ;
@@ -358,7 +360,8 @@ public static void unbindConnection(RedisConnectionFactory factory) {
358
360
* @param connectionFactory Redis connection factory that the connection was created with
359
361
* @return whether the connection is transactional or not
360
362
*/
361
- public static boolean isConnectionTransactional (RedisConnection connection , RedisConnectionFactory connectionFactory ) {
363
+ public static boolean isConnectionTransactional (RedisConnection connection ,
364
+ RedisConnectionFactory connectionFactory ) {
362
365
363
366
Assert .notNull (connectionFactory , "No RedisConnectionFactory specified" );
364
367
@@ -448,9 +451,16 @@ public void afterCompletion(int status) {
448
451
static class ConnectionSplittingInterceptor implements MethodInterceptor {
449
452
450
453
private final RedisConnectionFactory factory ;
454
+ private final @ Nullable String commandInterface ;
451
455
452
456
public ConnectionSplittingInterceptor (RedisConnectionFactory factory ) {
453
457
this .factory = factory ;
458
+ this .commandInterface = null ;
459
+ }
460
+
461
+ public ConnectionSplittingInterceptor (RedisConnectionFactory factory , String commandInterface ) {
462
+ this .factory = factory ;
463
+ this .commandInterface = commandInterface ;
454
464
}
455
465
456
466
@ Override
@@ -465,6 +475,22 @@ public Object intercept(Object obj, Method method, Object[] args) throws Throwab
465
475
return obj ;
466
476
}
467
477
478
+ Class <?> returnType = method .getReturnType ();
479
+ String returnTypeName = returnType .getSimpleName ();
480
+
481
+ // bridge keyCommands etc. to defer target invocations
482
+ if (returnType .isInterface () && returnType .getPackageName ().equals ("org.springframework.data.redis.connection" )
483
+ && returnTypeName .startsWith ("Redis" ) && returnTypeName .endsWith ("Commands" )) {
484
+
485
+ ProxyFactory proxyFactory = new ProxyFactory (ReflectionUtils .invokeMethod (method , obj ));
486
+
487
+ proxyFactory .addAdvice (new ConnectionSplittingInterceptor (factory , method .getName ()));
488
+ proxyFactory .addInterface (RedisConnectionProxy .class );
489
+ proxyFactory .addInterface (returnType );
490
+
491
+ return proxyFactory .getProxy ();
492
+ }
493
+
468
494
RedisCommand commandToExecute = RedisCommand .failsafeCommandLookup (method .getName ());
469
495
470
496
if (isPotentiallyThreadBoundCommand (commandToExecute )) {
@@ -481,9 +507,15 @@ public Object intercept(Object obj, Method method, Object[] args) throws Throwab
481
507
}
482
508
483
509
RedisConnection connection = factory .getConnection ();
484
-
510
+ Object target = connection ;
485
511
try {
486
- return invoke (method , connection , args );
512
+
513
+ if (StringUtils .hasText (commandInterface )) {
514
+ target = ReflectionUtils .invokeMethod (ReflectionUtils .findMethod (RedisConnection .class , commandInterface ),
515
+ connection );
516
+ }
517
+
518
+ return invoke (method , target , args );
487
519
} finally {
488
520
// properly close the unbound connection after executing command
489
521
if (!connection .isClosed ()) {
0 commit comments