Java runtime metadata analysis library that enables reverse querying of classpath metadata for type system introspection
—
Modern functional query system using QueryFunction for composable, type-safe metadata queries with filtering, mapping, and transformation capabilities. This system provides a powerful and flexible API for querying scanned metadata.
Core functional interface for creating composable queries with type safety and functional composition.
/**
* Functional interface for store queries
*/
interface QueryFunction<C, T> extends Function<C, Set<T>>, NameHelper {
/** Apply query to context and return results */
Set<T> apply(C ctx);
/** Filter results using predicate */
default QueryFunction<C, T> filter(Predicate<? super T> predicate);
/** Map results to different type */
default <R> QueryFunction<C, R> map(Function<? super T, ? extends R> function);
/** Flat map results with nested queries */
default <R> QueryFunction<C, R> flatMap(Function<T, ? extends Function<C, Set<R>>> function);
/** Get transitive results using builder function */
default QueryFunction<C, T> getAll(Function<T, QueryFunction<C, T>> builder);
/** Get transitive results with traverse function */
default <R> QueryFunction<C, R> getAll(Function<T, QueryFunction<C, R>> builder, Function<R, T> traverse);
/** Concatenate results with another query function */
default <R> QueryFunction<C, T> add(QueryFunction<C, T> function);
/** Convert results to specific type with class loaders */
default <R> QueryFunction<C, R> as(Class<? extends R> type, ClassLoader... loaders);
/** Convert results to Class objects */
default <R> QueryFunction<C, Class<?>> asClass(ClassLoader... loaders);
/** Convert results to strings */
default QueryFunction<C, String> asString();
/** Unsafe cast to different type */
default <R> QueryFunction<C, Class<? extends R>> as();
}Static methods for creating basic QueryFunction instances.
/**
* Static factory methods for QueryFunction
*/
interface QueryFunction<C, T> extends Function<C, Set<T>>, NameHelper {
/** Create empty result query */
static <C, T> QueryFunction<Store, T> empty();
/** Create single element query */
static <C, T> QueryFunction<Store, T> single(T element);
/** Create query from collection of elements */
static <C, T> QueryFunction<Store, T> set(Collection<T> elements);
}Pre-built query builders for common reflection operations using the modern functional API.
/**
* ReflectionUtils query builders for common operations
*/
abstract class ReflectionUtils extends ReflectionUtilsPredicates {
/** Apply query function to context */
static <C, T> Set<T> get(QueryFunction<C, T> function);
/** Apply query function with additional predicates */
static <T> Set<T> get(QueryFunction<Store, T> queryFunction, Predicate<? super T>... predicates);
/** Query builder for super class */
static final UtilQueryBuilder<Class<?>, Class<?>> SuperClass;
/** Query builder for interfaces */
static final UtilQueryBuilder<Class<?>, Class<?>> Interfaces;
/** Query builder for super types and interfaces */
static final UtilQueryBuilder<Class<?>, Class<?>> SuperTypes;
/** Query builder for annotations */
static final UtilQueryBuilder<AnnotatedElement, Annotation> Annotations;
/** Query builder for annotation types */
static final UtilQueryBuilder<AnnotatedElement, Class<? extends Annotation>> AnnotationTypes;
/** Query builder for methods */
static final UtilQueryBuilder<Class<?>, Method> Methods;
/** Query builder for constructors */
static final UtilQueryBuilder<Class<?>, Constructor> Constructors;
/** Query builder for fields */
static final UtilQueryBuilder<Class<?>, Field> Fields;
/** Query builder for URL resources */
static final UtilQueryBuilder<String, URL> Resources;
/** Predicate to filter out Object methods */
static final Predicate<Method> notObjectMethod;
}Specialized query builder for ReflectionUtils operations with enhanced capabilities.
/**
* Query builder for ReflectionUtils operations
*/
class UtilQueryBuilder<C, T> implements QueryBuilder {
/** Get scanner index name */
String index();
/** Get values for specific key */
QueryFunction<Store, String> get(String key);
/** Get values for annotated element */
QueryFunction<Store, String> get(AnnotatedElement element);
/** Get values for collection of keys */
QueryFunction<Store, String> get(Collection<String> keys);
/** Get transitive values for keys */
QueryFunction<Store, String> getAll(Collection<String> keys);
/** Get transitive values including specific key */
QueryFunction<Store, String> getAllIncluding(String key);
/** Get transitive values including collection of keys */
QueryFunction<Store, String> getAllIncluding(Collection<String> keys);
/** Alias for getAll(Collection) */
QueryFunction<Store, String> of(Collection<String> keys);
/** Alias for getAll with single key */
QueryFunction<Store, String> of(String key);
/** Get transitive values for annotated elements */
QueryFunction<Store, String> of(AnnotatedElement... elements);
/** Get transitive values for set of annotated elements */
QueryFunction<Store, String> of(Set<? extends AnnotatedElement> elements);
/** Various "with" aliases for "of" methods */
QueryFunction<Store, String> with(String key);
QueryFunction<Store, String> with(String... keys);
QueryFunction<Store, String> with(AnnotatedElement... elements);
QueryFunction<Store, String> with(Collection<String> keys);
QueryFunction<Store, String> with(Set<? extends AnnotatedElement> elements);
/** Compose with another query function */
<R> QueryFunction<Store, R> of(QueryFunction queryFunction);
}import org.reflections.Reflections;
import org.reflections.util.QueryFunction;
import static org.reflections.scanners.Scanners.*;
Reflections reflections = new Reflections("com.mycompany");
// Basic queries using scanner builders
Set<String> subtypeNames = reflections.get(SubTypes.of(MyInterface.class));
Set<Class<?>> subtypeClasses = reflections.get(SubTypes.of(MyInterface.class).asClass());
Set<String> annotatedTypeNames = reflections.get(TypesAnnotated.with(MyAnnotation.class));
Set<Class<?>> annotatedTypes = reflections.get(TypesAnnotated.with(MyAnnotation.class).asClass());
Set<Method> annotatedMethods = reflections.get(MethodsAnnotated.with(RequestMapping.class).as(Method.class));import java.lang.reflect.Modifier;
import static org.reflections.scanners.Scanners.*;
// Filter results using predicates
Set<Method> publicMethods = reflections.get(
MethodsAnnotated.with(RequestMapping.class)
.as(Method.class)
.filter(method -> Modifier.isPublic(method.getModifiers())));
// Chain multiple filters
Set<Class<?>> concreteServices = reflections.get(
SubTypes.of(Service.class)
.asClass()
.filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
.filter(clazz -> !clazz.isInterface()));
// Map results to different type
Set<String> methodNames = reflections.get(
MethodsAnnotated.with(RequestMapping.class)
.as(Method.class)
.map(Method::getName));
// Complex filtering with business logic
Set<Class<?>> validControllers = reflections.get(
TypesAnnotated.with(Controller.class)
.asClass()
.filter(clazz -> clazz.getPackage().getName().startsWith("com.mycompany"))
.filter(clazz -> !clazz.getSimpleName().contains("Test"))
.filter(clazz -> clazz.getDeclaredMethods().length > 0));import org.reflections.ReflectionUtils;
import static org.reflections.ReflectionUtils.*;
// Query super types
Set<Class<?>> superTypes = get(SuperTypes.of(MyClass.class));
Set<Class<?>> allSuperTypes = get(SuperTypes.of(MyClass.class)
.filter(clazz -> !clazz.equals(Object.class)));
// Query annotations
Set<Annotation> annotations = get(Annotations.of(MyClass.class));
Set<Class<? extends Annotation>> annotationTypes = get(AnnotationTypes.of(MyClass.class));
// Query methods with filtering
Set<Method> getters = get(Methods.of(MyClass.class)
.filter(method -> method.getName().startsWith("get"))
.filter(method -> method.getParameterCount() == 0));
Set<Method> setters = get(Methods.of(MyClass.class)
.filter(method -> method.getName().startsWith("set"))
.filter(method -> method.getParameterCount() == 1));
// Query fields
Set<Field> privateFields = get(Fields.of(MyClass.class)
.filter(field -> Modifier.isPrivate(field.getModifiers())));
// Query constructors
Set<Constructor> publicConstructors = get(Constructors.of(MyClass.class)
.filter(constructor -> Modifier.isPublic(constructor.getModifiers())));// Create custom query functions
QueryFunction<Store, Method> serviceMethodsQuery = store ->
reflections.get(TypesAnnotated.with(Service.class).asClass())
.stream()
.flatMap(clazz -> Arrays.stream(clazz.getDeclaredMethods()))
.collect(Collectors.toSet());
// Combine multiple queries
QueryFunction<Store, Class<?>> allServiceTypes =
SubTypes.of(Service.class)
.asClass()
.add(TypesAnnotated.with(Service.class).asClass());
Set<Class<?>> services = reflections.get(allServiceTypes);
// Create transitive queries
QueryFunction<Store, String> transitiveSubTypes = SubTypes.getAll(
Arrays.asList("com.mycompany.BaseService", "com.mycompany.BaseRepository"));
// Use flatMap for complex transformations
Set<Method> allServiceMethods = reflections.get(
TypesAnnotated.with(Service.class)
.asClass()
.flatMap(clazz -> store -> Arrays.stream(clazz.getDeclaredMethods()).collect(Collectors.toSet())));// Create empty query
QueryFunction<Store, String> empty = QueryFunction.empty();
// Create single element query
QueryFunction<Store, String> single = QueryFunction.single("com.mycompany.MyClass");
// Create query from collection
QueryFunction<Store, String> fromSet = QueryFunction.set(
Arrays.asList("com.mycompany.Class1", "com.mycompany.Class2"));
// Use in complex compositions
Set<Class<?>> combinedResults = reflections.get(
SubTypes.of(MyInterface.class)
.asClass()
.add(fromSet.asClass()));// Convert strings to classes
Set<Class<?>> classes = reflections.get(
SubTypes.of(MyInterface.class).asClass());
// Convert with specific class loaders
ClassLoader customClassLoader = MyClass.class.getClassLoader();
Set<Class<?>> customLoaderClasses = reflections.get(
SubTypes.of(MyInterface.class).as(Class.class, customClassLoader));
// Convert to methods
Set<Method> methods = reflections.get(
MethodsAnnotated.with(RequestMapping.class).as(Method.class));
// Convert to fields
Set<Field> fields = reflections.get(
FieldsAnnotated.with(Autowired.class).as(Field.class));
// Convert to constructors
Set<Constructor> constructors = reflections.get(
ConstructorsAnnotated.with(Inject.class).as(Constructor.class));// Query resources with patterns
Set<String> xmlFiles = reflections.get(Resources.with(".*\\.xml"));
Set<String> propertyFiles = reflections.get(Resources.with(".*\\.properties"));
Set<String> configFiles = reflections.get(Resources.with(".*config.*"));
// Complex resource filtering
Set<String> filteredResources = reflections.get(
Resources.with(".*")
.filter(resource -> resource.contains("config"))
.filter(resource -> !resource.contains("test")));// Create custom query function for business logic
public class CustomQueries {
public static QueryFunction<Store, Class<?>> domainEntities(Reflections reflections) {
return store -> reflections.get(TypesAnnotated.with(Entity.class).asClass())
.stream()
.filter(clazz -> clazz.getPackage().getName().contains("domain"))
.filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
.collect(Collectors.toSet());
}
public static QueryFunction<Store, Method> businessMethods(Reflections reflections) {
return store -> reflections.get(TypesAnnotated.with(Service.class).asClass())
.stream()
.flatMap(clazz -> Arrays.stream(clazz.getDeclaredMethods()))
.filter(method -> Modifier.isPublic(method.getModifiers()))
.filter(method -> !method.getName().startsWith("get"))
.filter(method -> !method.getName().startsWith("set"))
.collect(Collectors.toSet());
}
}
// Use custom queries
Set<Class<?>> entities = reflections.get(CustomQueries.domainEntities(reflections));
Set<Method> businessMethods = reflections.get(CustomQueries.businessMethods(reflections));// Validate query results
QueryFunction<Store, Class<?>> validatedQuery = SubTypes.of(MyInterface.class)
.asClass()
.filter(clazz -> {
try {
// Validate class can be instantiated
clazz.getDeclaredConstructor();
return true;
} catch (NoSuchMethodException e) {
return false;
}
});
// Handle empty results
Set<Class<?>> results = reflections.get(SubTypes.of(RareInterface.class).asClass());
if (results.isEmpty()) {
results = reflections.get(QueryFunction.single(DefaultImplementation.class));
}
// Combine with fallback queries
QueryFunction<Store, Class<?>> withFallback =
SubTypes.of(PreferredInterface.class)
.asClass()
.add(SubTypes.of(FallbackInterface.class).asClass());public class QueryBuilder {
private final Reflections reflections;
private QueryFunction<Store, Class<?>> query = QueryFunction.empty();
public QueryBuilder(Reflections reflections) {
this.reflections = reflections;
}
public QueryBuilder subtypesOf(Class<?> type) {
query = query.add(SubTypes.of(type).asClass());
return this;
}
public QueryBuilder annotatedWith(Class<? extends Annotation> annotation) {
query = query.add(TypesAnnotated.with(annotation).asClass());
return this;
}
public QueryBuilder inPackage(String packageName) {
query = query.filter(clazz -> clazz.getPackage().getName().startsWith(packageName));
return this;
}
public QueryBuilder excludeAbstract() {
query = query.filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()));
return this;
}
public Set<Class<?>> build() {
return reflections.get(query);
}
}
// Usage
Set<Class<?>> results = new QueryBuilder(reflections)
.subtypesOf(Service.class)
.annotatedWith(Component.class)
.inPackage("com.mycompany")
.excludeAbstract()
.build();// Create lazy queries that are evaluated on demand
public class LazyQueries {
private final Reflections reflections;
private Supplier<Set<Class<?>>> servicesSupplier;
private Supplier<Set<Method>> methodsSupplier;
public LazyQueries(Reflections reflections) {
this.reflections = reflections;
// Define lazy queries
this.servicesSupplier = () -> reflections.get(
TypesAnnotated.with(Service.class).asClass());
this.methodsSupplier = () -> reflections.get(
MethodsAnnotated.with(RequestMapping.class).as(Method.class));
}
public Set<Class<?>> getServices() {
return servicesSupplier.get();
}
public Set<Method> getMethods() {
return methodsSupplier.get();
}
}/**
* Predicates for reflection filtering operations
*/
abstract class ReflectionUtilsPredicates {
/** Check if member is public */
static Predicate<Member> withPublic();
/** Check parameter count */
static Predicate<Member> withParametersCount(int count);
/** Check for annotation presence */
static <T extends AnnotatedElement> Predicate<T> withAnnotation(Annotation annotation);
/** Check for annotation type presence */
static <T extends AnnotatedElement> Predicate<T> withAnnotation(Class<? extends Annotation> annotation);
/** Check method parameters */
static Predicate<Method> withParameters(Class<?>... types);
/** Check any parameter has annotation */
static Predicate<Method> withAnyParameterAnnotation(Class<? extends Annotation> annotation);
/** Check method prefix */
static <T extends Member> Predicate<T> withPrefix(String prefix);
/** Check method return type */
static <T extends Method> Predicate<T> withReturnType(Class<?> type);
}Install with Tessl CLI
npx tessl i tessl/maven-org-reflections--reflections