Skip to content

Commit 5ff7a1d

Browse files
ronmamodependabot[bot]hejczkerwin612ileler
authored
ref-0.10.2 (#356)
* fix npe on empty Resources store * ReflectionUtils.Methods to use getDeclaredMethods * add ReflectionUtils.Resources * add JdkTests * fragile/flaky * fix scanner index for deprecated scanners :( * deprecated scanners javadocs * JdkTests cleanup * Bump maven-javadoc-plugin from 3.1.1 to 3.3.1 (#352) * Detect annotations during expand super types step (#354) * Add subtypes to SubTypes store during expand super types step * Detect annotations during expandSuperType step Co-authored-by: Julian Rubin <[email protected]> * npe fix * ConfigurationBuilder.setParallel fluent * readme * arranged ReflectionsExpandSupertypesTest * Correct the wrong match (#334) * Correct the wrong matc * Fetch upstream Co-authored-by: ileler <[email protected]> * arranged VfsTest * minors Co-authored-by: ronma <ronma@> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Julian Rubin <[email protected]> Co-authored-by: Julian Rubin <[email protected]> Co-authored-by: Kerwin Bryant <[email protected]> Co-authored-by: ileler <[email protected]>
1 parent e9ed4e1 commit 5ff7a1d

24 files changed

+594
-168
lines changed

README.md

+78-70
Original file line numberDiff line numberDiff line change
@@ -40,50 +40,61 @@ Set<Class<?>> subTypes =
4040
reflections.get(SubTypes.of(SomeType.class).asClass());
4141

4242
Set<Class<?>> annotated =
43-
reflections.get(TypesAnnotated.with(SomeAnnotation.class).asClass());
43+
reflections.get(SubTypes.of(TypesAnnotated.with(SomeAnnotation.class)).asClass());
4444
```
4545

46-
*Note that there are some breaking changes with Reflections 0.10+, along with performance improvements and more functional API. Migration is encouraged and should be easy though.*
46+
Or using previous 0.9.x APIs, for example:
47+
48+
```java
49+
Set<Class<? extends SomeType>> subTypes =
50+
reflections.getSubTypesOf(SomeType.class);
51+
52+
Set<Class<?>> annotated =
53+
reflections.getTypesAnnotatedWith(SomeAnnotation.class);
54+
```
55+
56+
*Note that there are some breaking changes with Reflections 0.10+, along with performance improvements and more functional API, see below.*
4757

4858
### Scan
49-
Creating Reflections instance requires providing scanning configuration:
59+
Creating Reflections instance requires [ConfigurationBuilder](https://ronmamo.github.io/reflections/org/reflections/util/ConfigurationBuilder.html), typically configured with packages and [Scanners](https://ronmamo.github.io/reflections/org/reflections/scanners/Scanners.html) to use:
5060

5161
```java
52-
// scan for:
53-
// urls in classpath that contain 'com.my.project' package
54-
// filter types starting with 'com.my.project'
55-
// use the default scanners SubTypes and TypesAnnotated
62+
// typical usage: scan package with the default scanners SubTypes, TypesAnnotated
5663
Reflections reflections = new Reflections(
5764
new ConfigurationBuilder()
5865
.forPackage("com.my.project")
5966
.filterInputsBy(new FilterBuilder().includePackage("com.my.project")));
6067

61-
// or similarly
68+
// or similarly using the convenient constructor
6269
Reflections reflections = new Reflections("com.my.project");
70+
```
6371

64-
// another example
72+
Other examples:
73+
```java
74+
import static org.reflections.scanners.Scanners.*;
75+
76+
// scan package with specific scanners
6577
Reflections reflections = new Reflections(
6678
new ConfigurationBuilder()
67-
.addUrls(ClasspathHelper.forPackage("com.my.project")) // same as forPackage
68-
.setScanners(Scanners.values()) // all standard scanners
69-
.filterInputsBy(new FilterBuilder() // optionally include/exclude packages
70-
.includePackage("com.my.project")
71-
.excludePackage("com.my.project.exclude")));
72-
```
79+
.forPackage("com.my.project")
80+
.filterInputsBy(new FilterBuilder().includePackage("com.my.project").excludePackage("com.my.project.exclude"))
81+
.setScanners(TypesAnnotated, MethodsAnnotated, MethodsReturn));
7382

74-
*See more in [ConfigurationBuilder](https://ronmamo.github.io/reflections/org/reflections/util/ConfigurationBuilder.html).*
83+
// scan package with all standard scanners
84+
Reflections reflections = new Reflections("com.my.project", Scanners.values());
85+
```
7586

7687
Note that:
77-
* **Scanners must be configured in order to be queried, otherwise an empty result is returned.**
78-
If not specified, default scanners are `SubTypes` and `TypesAnnotated`. For all standard [Scanners](https://ronmamo.github.io/reflections/org/reflections/scanners/Scanners.html) use `Scanners.values()` [(src)](src/main/java/org/reflections/scanners/Scanners.java).
79-
* **All relevant URLs should be configured.**
88+
* **Scanner must be configured in order to be queried, otherwise an empty result is returned**
89+
If not specified, default scanners will be used SubTypes, TypesAnnotated.
90+
For all standard scanners use `Scanners.values()`. See more scanners in the source [package](https://ronmamo.github.io/reflections/org/reflections/scanners).
91+
* **All relevant URLs should be configured**
92+
Consider `.filterInputsBy()` in case too many classes are scanned.
8093
If required, Reflections will [expand super types](https://ronmamo.github.io/reflections/org/reflections/Reflections.html#expandSuperTypes(java.util.Map)) in order to get the transitive closure metadata without scanning large 3rd party urls.
81-
Consider adding inputs filter in case too many classes are scanned.
8294
* Classloader can optionally be used for resolving runtime classes from names.
8395

8496
### Query
8597
Once Reflections was instantiated and scanning was successful, it can be used for querying the indexed metadata.
86-
Standard [Scanners](https://ronmamo.github.io/reflections/org/reflections/scanners/Scanners.html) are provided for query using `reflections.get()`, for example:
8798

8899
```java
89100
import static org.reflections.scanners.Scanners.*;
@@ -92,18 +103,14 @@ import static org.reflections.scanners.Scanners.*;
92103
Set<Class<?>> modules =
93104
reflections.get(SubTypes.of(Module.class).asClass());
94105

95-
// TypesAnnotated
106+
// TypesAnnotated (*1)
96107
Set<Class<?>> singletons =
97108
reflections.get(TypesAnnotated.with(Singleton.class).asClass());
98109

99-
// MethodAnnotated
110+
// MethodsAnnotated
100111
Set<Method> resources =
101112
reflections.get(MethodsAnnotated.with(GetMapping.class).as(Method.class));
102113

103-
// ConstructorsAnnotated
104-
Set<Constructor> injectables =
105-
reflections.get(ConstructorsAnnotated.with(Inject.class).as(Constructor.class));
106-
107114
// FieldsAnnotated
108115
Set<Field> ids =
109116
reflections.get(FieldsAnnotated.with(Id.class).as(Field.class));
@@ -113,7 +120,7 @@ Set<String> properties =
113120
reflections.get(Resources.with(".*\\.properties"));
114121
```
115122

116-
Member scanners:
123+
More scanners:
117124

118125
```java
119126
// MethodsReturn
@@ -128,51 +135,52 @@ Set<Method> someMethods =
128135
Set<Method> pathParam =
129136
reflections.get(MethodsParameter.of(PathParam.class).as(Method.class));
130137

138+
// ConstructorsAnnotated
139+
Set<Constructor> injectables =
140+
reflections.get(ConstructorsAnnotated.with(Inject.class).as(Constructor.class));
141+
131142
// ConstructorsSignature
132143
Set<Constructor> someConstructors =
133144
reflections.get(ConstructorsSignature.of(String.class).as(Constructor.class));
134145

135-
// ConstructorsParameter
136-
Set<Constructor> pathParam =
137-
reflections.get(ConstructorsParameter.of(PathParam.class).as(Constructor.class));
146+
// MethodParameterNamesScanner
147+
List<String> parameterNames =
148+
reflections.getMemberParameterNames(member);
149+
150+
// MemberUsageScanner
151+
Set<Member> usages =
152+
reflections.getMemberUsages(member)
138153
```
139154

140155
*See more examples in [ReflectionsQueryTest](src/test/java/org/reflections/ReflectionsQueryTest.java).*
141156

142-
Scanner queries return `Set<String>` by default, if not using `as() / asClass()` mappers:
143-
```java
144-
Set<String> moduleNames =
145-
reflections.get(SubTypes.of(Module.class));
146-
147-
Set<String> singleNames =
148-
reflections.get(TypesAnnotated.with(Singleton.class));
149-
```
150-
Note that previous 0.9.x API is still supported, for example:
151-
```java
152-
Set<Class<?>> modules =
153-
reflections.getSubTypesOf(Module.class);
157+
*Note that previous 0.9.x APIs are still supported*
154158

155-
Set<Class<?>> singletons =
156-
reflections.getTypesAnnotatedWith(Singleton.class);
157-
```
158159
<details>
159-
<summary>Compare Scanners and previous 0.9.x API</summary>
160-
161-
| Scanners | previous 0.9.x API |
162-
| -------- | ------------------ |
163-
| `get(SubType.of(T))` | getSubTypesOf(T) |
164-
| `get(TypesAnnotated.with(A))` | getTypesAnnotatedWith(A) |
165-
| `get(MethodsAnnotated.with(A))` | getMethodsAnnotatedWith(A) |
166-
| `get(ConstructorsAnnotated.with(A))` | getConstructorsAnnotatedWith(A) |
167-
| `get(FieldsAnnotated.with(A))` | getFieldsAnnotatedWith(A) |
168-
| `get(Resources.with(regex))` | getResources(regex) |
169-
| `get(MethodsParameter.with(P))` | getMethodsWithParameter(P) |
170-
| `get(MethodsSignature.of(P, ...))` | getMethodsWithSignature(P, ...) |
171-
| `get(MethodsReturn.of(T))` | getMethodsReturn(T) |
172-
| `get(ConstructorsParameter.with(P))` | getConstructorsWithParameter(P) |
173-
| `get(ConstructorsSignature.of(P, ...))` | getConstructorsWithSignature(P, ...) |
160+
<summary><i>Compare Scanners and previous 0.9.x API (*)</i></summary>
161+
162+
| Scanners | previous 0.9.x API | previous Scanner |
163+
| -------- | ------------------ | ------ |
164+
| `get(SubType.of(T))` | getSubTypesOf(T) | ~~SubTypesScanner~~ |
165+
| `get(SubTypes.of(`<br>&nbsp;&nbsp;&nbsp;&nbsp;`TypesAnnotated.with(A)))` | getTypesAnnotatedWith(A) *(1)*| ~~TypeAnnotationsScanner~~ |
166+
| `get(MethodsAnnotated.with(A))` | getMethodsAnnotatedWith(A) | ~~MethodAnnotationsScanner~~ |
167+
| `get(ConstructorsAnnotated.with(A))` | getConstructorsAnnotatedWith(A) *(2)*| ~~MethodAnnotationsScanner~~ |
168+
| `get(FieldsAnnotated.with(A))` | getFieldsAnnotatedWith(A) | ~~FieldAnnotationsScanner~~ |
169+
| `get(Resources.with(regex))` | getResources(regex) | ~~ResourcesScanner~~ |
170+
| `get(MethodsParameter.with(P))` | getMethodsWithParameter(P) *(3)*<br>~~getMethodsWithAnyParamAnnotated(P)~~| ~~MethodParameterScanner~~<br>*obsolete* |
171+
| `get(MethodsSignature.of(P, ...))` | getMethodsWithSignature(P, ...) *(3)<br>~~getMethodsMatchParams(P, ...)~~*| " |
172+
| `get(MethodsReturn.of(T))` | getMethodsReturn(T) *(3)*| " |
173+
| `get(ConstructorsParameter.with(P))` | getConstructorsWithParameter(P) *(3)<br>~~getConstructorsWithAnyParamAnnotated(P)~~*| " |
174+
| `get(ConstructorsSignature.of(P, ...))` | getConstructorsWithSignature(P, ...) *(3)<br>~~getConstructorsMatchParams(P, ...)~~*| " |
174175

175176
*Note: `asClass()` and `as()` mappings were omitted*
177+
178+
*(1): The equivalent of `getTypesAnnotatedWith(A)` is `get(SubTypes.of(TypesAnnotated.with(A)))`, including SubTypes*
179+
180+
*(2): MethodsAnnotatedScanner does not include constructor annotation scanning, use instead Scanners.ConstructorsAnnotated*
181+
182+
*(3): MethodParameterScanner is obsolete, use instead as required:
183+
Scanners.MethodsParameter, Scanners.MethodsSignature, Scanners.MethodsReturn, Scanners.ConstructorsParameter, Scanners.ConstructorsSignature*
176184
</details>
177185

178186
## ReflectionUtils
@@ -187,13 +195,15 @@ Set<Class<?>> superTypes = get(SuperTypes.of(T));
187195
Set<Field> fields = get(Fields.of(T));
188196
Set<Constructor> constructors = get(Constructors.of(T));
189197
Set<Methods> methods = get(Methods.of(T));
198+
Set<URL> resources = get(Resources.with(T));
199+
190200
Set<Annotation> annotations = get(Annotations.of(T));
191-
Set<Class<? extends Annotation>> annotationTypes = get(AnnotationTypess.of(T));
201+
Set<Class<? extends Annotation>> annotationTypes = get(AnnotationTypes.of(T));
192202
```
193203

194204
*Previous ReflectionUtils 0.9.x API is still supported though marked for removal, more info in the javadocs.*
195205

196-
## QueryBuilder and QueryFunction
206+
## Query API
197207
Each Scanner and ReflectionUtils function implements [QueryBuilder](https://ronmamo.github.io/reflections/org/reflections/util/QueryBuilder.html), and supports:
198208
* `get()` - function returns direct values
199209
* `with()` or `of()` - function returns all transitive values
@@ -206,21 +216,19 @@ Next, each function implements [QueryFunction](https://ronmamo.github.io/reflect
206216
and provides fluent functional interface for composing `filter()`, `map()`, `flatMap()`, `as()` and more, such that:
207217

208218
```java
219+
// filter, as/map
209220
QueryFunction<Store, Method> getters =
210221
Methods.of(C1.class)
211222
.filter(withModifier(Modifier.PUBLIC))
212223
.filter(withPrefix("get").and(withParametersCount(0)))
213224
.as(Method.class);
214-
```
215225

216-
Query functions can be composed, for example:
217-
```java
218-
// compose Scanner and ReflectionUtils functions
226+
// compose Scanners and ReflectionUtils functions
219227
QueryFunction<Store, Method> methods =
220228
SubTypes.of(type).asClass() // <-- classpath scanned metadata
221229
.flatMap(Methods::of); // <-- java reflection api
222230

223-
// compose function of function
231+
// function of function
224232
QueryFunction<Store, Class<? extends Annotation>> queryAnnotations =
225233
Annotations.of(Methods.of(C4.class))
226234
.map(Annotation::annotationType);
@@ -256,11 +264,11 @@ Check the [tests](src/test/java/org/reflections) folder for more examples and AP
256264

257265
### What else?
258266
- **Integrating with build lifecycle**
259-
It is sometime useful to save the scanned metadata into xml/json as part of the build lifecycle for generating resources,
267+
It is sometime useful to `Reflections.save()` the scanned metadata into xml/json as part of the build lifecycle for generating resources,
260268
and then collect it on bootstrap with `Reflections.collect()` and avoid scanning. *See [reflections-maven](https://github.com/ronmamo/reflections-maven/) for example*.
261269
- [JavaCodeSerializer](https://ronmamo.github.io/reflections/org/reflections/serializers/JavaCodeSerializer.html) - scanned metadata can be persisted into a generated Java source code.
262270
Although less common, it can be useful for accessing types and members in a strongly typed manner. *(see [example](src/test/java/org/reflections/MyTestModelStore.java))*
263-
- [AnnotationMergeCollector](https://ronmamo.github.io/reflections/org/reflections/util/AnnotationMergeCollector.html) - can be used to merge similar annotations, for example for finding effective REST controller endpoints. *(see [test](src/test/java/org/reflections/ReflectionUtilsQueryTest.java#L216))*
271+
- [AnnotationMergeCollector](https://ronmamo.github.io/reflections/org/reflections/util/AnnotationMergeCollector.html) - can be used to merge similar annotations. *(see [test](src/test/java/org/reflections/ReflectionUtilsQueryTest.java#L216))*
264272
- `MemberUsageScanner` - experimental scanner allow querying for member usages `getMemberUsages()` of packages/types/elements in the classpath.
265273
Can be used for finding usages between packages, layers, modules, types etc.
266274

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
<plugin>
153153
<groupId>org.apache.maven.plugins</groupId>
154154
<artifactId>maven-javadoc-plugin</artifactId>
155-
<version>3.1.1</version>
155+
<version>3.3.1</version>
156156
<executions>
157157
<execution>
158158
<id>attach-javadocs</id>

src/main/java/org/reflections/Configuration.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ public interface Configuration {
2828
ClassLoader[] getClassLoaders();
2929

3030
/** if true (default), expand super types after scanning, for super types that were not scanned.
31-
* <p>see {@link org.reflections.Reflections#expandSuperTypes(Map)}*/
31+
* <p>see {@link Reflections#expandSuperTypes(Map, Map)}*/
3232
boolean shouldExpandSuperTypes();
3333
}

src/main/java/org/reflections/ReflectionUtils.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.reflections;
22

3+
import org.reflections.util.ClasspathHelper;
34
import org.reflections.util.QueryFunction;
45
import org.reflections.util.ReflectionUtilsPredicates;
56
import org.reflections.util.UtilQueryBuilder;
@@ -10,8 +11,10 @@
1011
import java.lang.reflect.Field;
1112
import java.lang.reflect.Method;
1213
import java.lang.reflect.Proxy;
14+
import java.net.URL;
1315
import java.util.Arrays;
1416
import java.util.Collections;
17+
import java.util.HashSet;
1518
import java.util.LinkedHashSet;
1619
import java.util.List;
1720
import java.util.Map;
@@ -137,7 +140,7 @@ public QueryFunction<Store, Class<? extends Annotation>> of(AnnotatedElement ele
137140

138141
/** query methods <pre>{@code get(Methods.of(type)) -> Set<Method>}</pre> */
139142
public static final UtilQueryBuilder<Class<?>, Method> Methods =
140-
element -> ctx -> Arrays.stream(element.getMethods()).filter(notObjectMethod).collect(Collectors.toCollection(LinkedHashSet::new));
143+
element -> ctx -> Arrays.stream(element.getDeclaredMethods()).filter(notObjectMethod).collect(Collectors.toCollection(LinkedHashSet::new));
141144

142145
/** query constructors <pre>{@code get(Constructors.of(type)) -> Set<Constructor> }</pre> */
143146
public static final UtilQueryBuilder<Class<?>, Constructor> Constructors =
@@ -147,6 +150,10 @@ public QueryFunction<Store, Class<? extends Annotation>> of(AnnotatedElement ele
147150
public static final UtilQueryBuilder<Class<?>, Field> Fields =
148151
element -> ctx -> Arrays.stream(element.getDeclaredFields()).collect(Collectors.toCollection(LinkedHashSet::new));
149152

153+
/** query url resources using {@link ClassLoader#getResources(java.lang.String)} <pre>{@code get(Resources.with(name)) -> Set<URL> }</pre> */
154+
public static final UtilQueryBuilder<String, URL> Resources =
155+
element -> ctx -> new HashSet<>(ClasspathHelper.forResource(element));
156+
150157
public static <T extends AnnotatedElement> UtilQueryBuilder<AnnotatedElement, T> extendType() {
151158
return element -> {
152159
if (element instanceof Class && !((Class<?>) element).isAnnotation()) {

0 commit comments

Comments
 (0)