|
97 | 97 | * <p>When executing transactional tests, it is sometimes useful to be able to
|
98 | 98 | * execute certain <em>set up</em> or <em>tear down</em> code outside of a
|
99 | 99 | * transaction. {@code TransactionalTestExecutionListener} provides such
|
100 |
| - * support for methods annotated with |
101 |
| - * {@link BeforeTransaction @BeforeTransaction} or |
102 |
| - * {@link AfterTransaction @AfterTransaction}. |
| 100 | + * support for methods annotated with {@link BeforeTransaction @BeforeTransaction} |
| 101 | + * or {@link AfterTransaction @AfterTransaction}. As of Spring Framework 4.3, |
| 102 | + * {@code @BeforeTransaction} and {@code @AfterTransaction} may also be declared |
| 103 | + * on Java 8 based interface default methods. |
103 | 104 | *
|
104 | 105 | * <h3>Configuring a Transaction Manager</h3>
|
105 | 106 | * <p>{@code TransactionalTestExecutionListener} expects a
|
@@ -431,90 +432,23 @@ protected final boolean isRollback(TestContext testContext) throws Exception {
|
431 | 432 | }
|
432 | 433 |
|
433 | 434 | /**
|
434 |
| - * Gets all superclasses of the supplied {@link Class class}, including the |
435 |
| - * class itself. The ordering of the returned list will begin with the |
436 |
| - * supplied class and continue up the class hierarchy, excluding {@link Object}. |
437 |
| - * <p>Note: This code has been borrowed from |
438 |
| - * {@link org.junit.internal.runners.TestClass#getSuperClasses(Class)} and |
439 |
| - * adapted. |
440 |
| - * @param clazz the class for which to retrieve the superclasses |
441 |
| - * @return all superclasses of the supplied class, excluding {@code Object} |
442 |
| - */ |
443 |
| - private List<Class<?>> getSuperClasses(Class<?> clazz) { |
444 |
| - List<Class<?>> results = new ArrayList<Class<?>>(); |
445 |
| - Class<?> current = clazz; |
446 |
| - while (current != null && Object.class != current) { |
447 |
| - results.add(current); |
448 |
| - current = current.getSuperclass(); |
449 |
| - } |
450 |
| - return results; |
451 |
| - } |
452 |
| - |
453 |
| - /** |
454 |
| - * Gets all methods in the supplied {@link Class class} and its superclasses |
| 435 | + * Get all methods in the supplied {@link Class class} and its superclasses |
455 | 436 | * which are annotated with the supplied {@code annotationType} but
|
456 | 437 | * which are not <em>shadowed</em> by methods overridden in subclasses.
|
457 |
| - * <p>Note: This code has been borrowed from |
458 |
| - * {@link org.junit.internal.runners.TestClass#getAnnotatedMethods(Class)} |
459 |
| - * and adapted. |
| 438 | + * <p>Default methods on interfaces are also detected. |
460 | 439 | * @param clazz the class for which to retrieve the annotated methods
|
461 | 440 | * @param annotationType the annotation type for which to search
|
462 | 441 | * @return all annotated methods in the supplied class and its superclasses
|
| 442 | + * as well as annotated interface default methods |
463 | 443 | */
|
464 | 444 | private List<Method> getAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotationType) {
|
465 |
| - List<Method> results = new ArrayList<Method>(); |
466 |
| - for (Class<?> current : getSuperClasses(clazz)) { |
467 |
| - for (Method method : current.getDeclaredMethods()) { |
468 |
| - Annotation annotation = AnnotationUtils.getAnnotation(method, annotationType); |
469 |
| - if (annotation != null && !isShadowed(method, results)) { |
470 |
| - results.add(method); |
471 |
| - } |
472 |
| - } |
473 |
| - } |
474 |
| - return results; |
475 |
| - } |
476 |
| - |
477 |
| - /** |
478 |
| - * Determine if the supplied {@link Method method} is <em>shadowed</em> by |
479 |
| - * a method in the supplied {@link List list} of previous methods. |
480 |
| - * <p>Note: This code has been borrowed from |
481 |
| - * {@link org.junit.internal.runners.TestClass#isShadowed(Method, List)}. |
482 |
| - * @param method the method to check for shadowing |
483 |
| - * @param previousMethods the list of methods which have previously been processed |
484 |
| - * @return {@code true} if the supplied method is shadowed by a |
485 |
| - * method in the {@code previousMethods} list |
486 |
| - */ |
487 |
| - private boolean isShadowed(Method method, List<Method> previousMethods) { |
488 |
| - for (Method each : previousMethods) { |
489 |
| - if (isShadowed(method, each)) { |
490 |
| - return true; |
491 |
| - } |
492 |
| - } |
493 |
| - return false; |
494 |
| - } |
495 |
| - |
496 |
| - /** |
497 |
| - * Determine if the supplied {@linkplain Method current method} is |
498 |
| - * <em>shadowed</em> by a {@linkplain Method previous method}. |
499 |
| - * <p>Note: This code has been borrowed from |
500 |
| - * {@link org.junit.internal.runners.TestClass#isShadowed(Method, Method)}. |
501 |
| - * @param current the current method |
502 |
| - * @param previous the previous method |
503 |
| - * @return {@code true} if the previous method shadows the current one |
504 |
| - */ |
505 |
| - private boolean isShadowed(Method current, Method previous) { |
506 |
| - if (!previous.getName().equals(current.getName())) { |
507 |
| - return false; |
508 |
| - } |
509 |
| - if (previous.getParameterTypes().length != current.getParameterTypes().length) { |
510 |
| - return false; |
511 |
| - } |
512 |
| - for (int i = 0; i < previous.getParameterTypes().length; i++) { |
513 |
| - if (!previous.getParameterTypes()[i].equals(current.getParameterTypes()[i])) { |
514 |
| - return false; |
| 445 | + List<Method> methods = new ArrayList<Method>(4); |
| 446 | + for (Method method : ReflectionUtils.getUniqueDeclaredMethods(clazz)) { |
| 447 | + if (AnnotationUtils.getAnnotation(method, annotationType) != null) { |
| 448 | + methods.add(method); |
515 | 449 | }
|
516 | 450 | }
|
517 |
| - return true; |
| 451 | + return methods; |
518 | 452 | }
|
519 | 453 |
|
520 | 454 | /**
|
|
0 commit comments