From fc5e3c335f2b7901d2bdfa2d783dec4352dde906 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 10 Nov 2020 16:31:31 +0100 Subject: [PATCH] Introduce and() methods in MethodFilter & FieldFilter for composition This commit introduces `and()` default methods in the MethodFilter and FieldFilter functional interfaces in ReflectionUtils in order to simplify uses cases that need to compose filter logic. Closes gh-26063 --- .../springframework/util/ReflectionUtils.java | 26 ++++++++++++++++++- .../util/ReflectionUtilsTests.java | 7 +---- .../junit/jupiter/SpringExtension.java | 8 +++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java index 531d5976615..e00fef835c6 100644 --- a/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ReflectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -824,6 +824,18 @@ public abstract class ReflectionUtils { * @param method the method to check */ boolean matches(Method method); + + /** + * Create a composite filter based on this filter and the provided + * filter. + *

If this filter does not match, the next filter will not be applied. + * @param next the next {@code MethodFilter} + * @return a composite {@code MethodFilter} + * @since 5.3.2 + */ + default MethodFilter and(MethodFilter next) { + return method -> matches(method) && next.matches(method); + } } @@ -852,6 +864,18 @@ public abstract class ReflectionUtils { * @param field the field to check */ boolean matches(Field field); + + /** + * Create a composite filter based on this filter and the provided + * filter. + *

If this filter does not match, the next filter will not be applied. + * @param next the next {@code FieldFilter} + * @return a composite {@code FieldFilter} + * @since 5.3.2 + */ + default FieldFilter and(FieldFilter next) { + return field -> matches(field) && next.matches(field); + } } } diff --git a/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java index 53859222465..8ca69ddc9a0 100644 --- a/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ReflectionUtilsTests.java @@ -186,12 +186,7 @@ class ReflectionUtilsTests { @Test void doWithProtectedMethods() { ListSavingMethodCallback mc = new ListSavingMethodCallback(); - ReflectionUtils.doWithMethods(TestObject.class, mc, new ReflectionUtils.MethodFilter() { - @Override - public boolean matches(Method m) { - return Modifier.isProtected(m.getModifiers()); - } - }); + ReflectionUtils.doWithMethods(TestObject.class, mc, method -> Modifier.isProtected(method.getModifiers())); assertThat(mc.getMethodNames().isEmpty()).isFalse(); assertThat(mc.getMethodNames().contains("clone")).as("Must find protected method on Object").isTrue(); assertThat(mc.getMethodNames().contains("finalize")).as("Must find protected method on Object").isTrue(); diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java index 97b5f1428f8..cf72a2b2413 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java @@ -98,10 +98,10 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes private static final List> JUPITER_ANNOTATION_TYPES = Arrays.asList(BeforeAll.class, AfterAll.class, BeforeEach.class, AfterEach.class, Testable.class); - private static final MethodFilter autowiredTestOrLifecycleMethodFilter = method -> - (ReflectionUtils.USER_DECLARED_METHODS.matches(method) && - !Modifier.isPrivate(method.getModifiers()) && - isAutowiredTestOrLifecycleMethod(method)); + private static final MethodFilter autowiredTestOrLifecycleMethodFilter = + ReflectionUtils.USER_DECLARED_METHODS + .and(method -> !Modifier.isPrivate(method.getModifiers())) + .and(SpringExtension::isAutowiredTestOrLifecycleMethod); /**