-
Notifications
You must be signed in to change notification settings - Fork 38.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Search for annotations on enclosing classes with MergedAnnotations API #23378
Comments
On the surface this seems quite reasonable, but I think there's a few things we should consider before adding an extra strategy. The first thing I think we need to define is the ordering of annotations when enclosing classes are considered. Currently I think we we order like this:
We will need to extended this to include the enclosing classes and define it in a way that makes sense. For example: @Example("animal")
public static class Animal {
}
@Example("cat")
public static class Cat extends Animal {
@Example("garfield")
public static class Garfield extends Animal {
}
} Should the order of annotations for We probably also need to consider the case where an inner class extends the outer class so could end up both inheriting and contained by the same class. Finally, I guess this strategy would only make sense for |
Yes, that's typically what we do.
Assuming you didn't mean to make the Though I'm wondering if we should really revisit classes with constructs like that (i.e., when an enclosing class extends the same class that the enclosed member class extends). In other words, I'm wondering if the result shouldn't simply be "garfield", "animal", "cat". With this example, we only see one additional annotation/value duplicated, but if a superclass like Technically, I suppose the caller could apply uniqueness to the streamed annotations or filter out entire aggregate indexes with the same source (declaring class). Long story, short: what do you think about "not revisiting classes"? Although I didn't spell it out in this issue's description, I think this new search algorithm should apply to what people traditionally refer to as inner classes, where such classes are technically non-static member classes according to the JLS. See In light of recent offline discussions, we may wish to rename
I know that's technically possible, but I wonder how often people actually do that (or would do that for code on which they want Spring to find annotations). In any case, this comes back to the question I raised above: do we want to revisit classes?
Yes, I agree: limit it to non-static member class sources. |
I remember considering this when implementing the search algorithm but decided against it at the time because adds some additional complication. I think I was also worried about the performance /garbage impact of needing to track visited class, but I must confess that I never actually measured that. |
Rename `SearchStrategy.EXHAUSTIVE` from `MergedAnnotations` to `SearchStrategy.TYPE_HIERARCHY` See gh-23378
Reopening due to the following issue. Summary: annotations on enclosing classes are not found if the "start" class is an inner class that is not annotated. In @EnclosedOne
public class AnnotationEnclosingClassSample {
@EnclosedTwo
public class EnclosedInner {
@EnclosedThree
public class EnclosedInnerInner {
}
public class NonAnnotatedEnclosedInnerInner {
}
}
} Then, executing the following passes. @Test
public void typeHierarchyWithEnclosedStrategyOnEnclosedInnerClassFindsAnnotations() {
Class<?> source = AnnotationEnclosingClassSample.EnclosedInner.EnclosedInnerInner.class;
List<String> list = MergedAnnotations.from(source,
SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(
mergedAnnotation -> mergedAnnotation.getType().getSimpleName()).collect(toList());
assertThat(list).containsExactly("EnclosedThree", "EnclosedTwo", "EnclosedOne");
} But executing the following fails with an empty list. @Test
public void typeHierarchyWithEnclosedStrategyOnNonAnnotatedEnclosedInnerClassFindsAnnotations() {
Class<?> source = AnnotationEnclosingClassSample.EnclosedInner.NonAnnotatedEnclosedInnerInner.class;
List<String> list = MergedAnnotations.from(source,
SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(
mergedAnnotation -> mergedAnnotation.getType().getSimpleName()).collect(toList());
assertThat(list).containsExactly("EnclosedTwo", "EnclosedOne");
} |
The TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy for MergedAnnotations was originally introduced to support @nested test classes in JUnit Jupiter (see spring-projects#23378). However, while implementing spring-projects#19930, we determined that the TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy unfortunately could not be used since it does not allow the user to control when to recurse up the enclosing class hierarchy. For example, this search strategy will automatically search on enclosing classes for static nested classes as well as for inner classes, when the user probably only wants one such category of "enclosing class" to be searched. Consequently, TestContextAnnotationUtils was introduced in the Spring TestContext Framework to address the shortcomings of the TYPE_HIERARCHY_AND_ENCLOSING_CLASSES search strategy. Since this search strategy is unlikely to be useful to general users, the team has decided to deprecate this search strategy in Spring Framework 5.3.x and remove it in 6.0. Closes spring-projectsgh-28079
Overview
The
MergedAnnotations
API currently supports four search strategies via theSearchStrategy
enum; however, none of those support searches on enclosing classes.In a typical Spring application, it is not necessary to search for an annotation on an enclosing class; however, in order to provide first-class support for Spring configuration in
@Nested
test class hierarchies in JUnit Jupiter, we need a mechanism for searching on enclosing classes as well (see gh-19930). There may be other use cases as well.Proposal
Introduce a new
SearchStrategy
for theMergedAnnotations
API that supports searching for annotations on "enclosing classes". This would likely be in addition to the semantics currently associated with theEXHAUSTIVE
enum.In one way, this would be
EXHAUSTIVE
++, but I don't know that we want to change the current semantics ofEXHAUSTIVE
. So, perhaps something likeEXHAUSTIVE_PLUS_ENCLOSING_CLASSES
would be more suitable.Providing such support in
MergedAnnotations
could alleviate some of the challenges of providing custom workarounds as can be seen in the current work for gh-19930.The text was updated successfully, but these errors were encountered: