Unlocking Spring Security’s ResolvableType: Simplify Generic Reflection

This article explores Spring Security’s ResolvableType class, demonstrating how its static factory methods—such as forClass, forClassWithGenerics, forField, and forMethodParameter—simplify obtaining generic type information via reflection, and shows practical code examples that replace cumbersome traditional Java reflection techniques.

macrozheng
macrozheng
macrozheng
Unlocking Spring Security’s ResolvableType: Simplify Generic Reflection

1. Introduction

While reading Spring Security source code I noticed two lines that use ResolvableType to obtain a generic type, which prompted me to investigate.

ResolvableType type = ResolvableType.forClassWithGenerics(OAuth2UserService.class, OAuth2UserRequest.class, OAuth2User.class);
ApplicationContext context = getContext();
String[] names = context.getBeanNamesForType(type);
if (names.length == 1) {
    OAuth2UserService<OAuth2UserRequest, OAuth2User> bean = (OAuth2UserService<OAuth2UserRequest, OAuth2User>) context.getBean(names[0]);
}

The ResolvableType class can retrieve a generic type, so I explored its capabilities.

2. ResolvableType

Normally we obtain type information via Java reflection on a Class, which is low‑level and cumbersome. ResolvableType simplifies this process by providing static methods that describe generic types such as OAuth2UserService<OAuth2UserRequest, OAuth2User> and allow retrieval of the corresponding Spring Bean. ResolvableType cannot be instantiated directly, but it offers many static factory methods.

forClass

Gets type information from a Class object; an overloaded version can combine a base class and an implementation class.

// java.lang.String
ResolvableType resolvableType1 = ResolvableType.forClass(String.class);
// java.util.Map<?, ?>
ResolvableType resolvableType2 = ResolvableType.forClass(Map.class, HashMap.class);

forClassWithGenerics

Gets type information from a Class together with its generic parameters, as shown in the opening example.

forConstructorParameter

Obtains metadata of a specific constructor parameter.

User user = new User("Zhang San");
Constructor<?> constructor = user.getClass().getConstructors()[0];
ResolvableType.forConstructorParameter(constructor, 0);

forField

Gets the type of a field.

private HashMap<String, List<Object>> map;

public void test() throws NoSuchFieldException {
    Field field = getClass().getDeclaredField("map");
    ResolvableType resolvableType = ResolvableType.forField(field);
}

forMethodParameter

Gets the type of a method parameter.

User user = new User("Zhang San");
Method method = user.getClass().getMethods()[0];
ResolvableType.forMethodParameter(method, 0);

forMethodReturnType

Gets the return‑type information of a method.

forArrayComponent

Gets the component type of an array.

ResolvableType resolvableType = ResolvableType.forClass(String.class);
// java.lang.String[]
ResolvableType arrayComponent = ResolvableType.forArrayComponent(resolvableType);

forInstance

Can also retrieve type information from an object instance.

Instance methods

So what is the practical use?

When you need to use reflection to obtain class instances, fields, or method information, ResolvableType provides convenient access to super‑type, generic arguments, and map representations, reducing boilerplate reflection code.

For example, from a field you can retrieve its generic key and value types, resolve them, and convert the type to a Map view.

private HashMap<Integer, List<String>> myMap;

public void example() throws NoSuchFieldException {
    ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
    t.getSuperType(); // AbstractMap<Integer, List<String>>
    t.asMap(); // Map<Integer, List<String>>
    t.getGeneric(0).resolve(); // Integer
    t.getGeneric(1).resolve(); // List
    t.getGeneric(1); // List<String>
    t.resolveGeneric(1, 0); // String
}

It feels like a more user‑friendly replacement for many common reflection operations.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentReflectionResolvableType
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.