10 Essential Spring Boot Utility Classes to Cut Your Code in Half

This article showcases ten built‑in Spring Boot utilities—including version retrieval, system property access, temporary and home directory handling, method introspection, generic type resolution, process ID extraction, property binding, and package path registration—each illustrated with concise code examples that dramatically reduce the need for custom helper classes.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
10 Essential Spring Boot Utility Classes to Cut Your Code in Half

Environment: Spring Boot 3.5.0

Spring & Boot version information

SpringVersion.getVersion(); // reads version from JAR metadata
SpringBootVersion.getVersion(); // returns "3.5.0" (hard‑coded in source)

Accessing system properties

Utility class SystemProperties provides a static get method that checks a system property first and falls back to the corresponding environment variable.

public static String get(String... properties) {
    for (String property : properties) {
        try {
            String override = System.getProperty(property);
            override = (override != null) ? override : System.getenv(property);
            if (override != null) {
                return override;
            }
        } catch (Exception ignored) {}
    }
    return null;
}

Temporary directory

ApplicationTemp

gives access to a per‑application temporary directory that remains the same across restarts.

@Component
public class UtilRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.err.println(new ApplicationTemp().getDir());
        System.err.println(new ApplicationTemp(ExcelExportMain.class).getDir());
    }
}

Sample output:

C:\xxx\Local\Temp\6CE6073CFBB362554F12857D5719C56C45591EED
C:\xxx\Local\Temp\751B29068A945FC52288380FF45197427579C0CF

Application home directory

ApplicationHome

locates the main directory of a running application, handling JAR files, exploded archives, and plain classpath runs.

@Component
public class HomeRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.err.println(new ApplicationHome().getDir());
        System.err.println(new ApplicationHome(ExcelExportMain.class).getDir());
    }
}

Typical output when running from a JAR:

D:\xxx\spring-boot-comprehensive
D:\xxx\spring-boot-comprehensive\target\classes

Method discovery

MethodIntrospector.selectMethods

can locate all methods annotated with a specific annotation, traversing interfaces, super‑classes, and handling generic signatures.

Set<Method> methods = MethodIntrospector.selectMethods(
    UserService.class,
    new ReflectionUtils.MethodFilter() {
        @Override
        public boolean matches(Method method) {
            return method.isAnnotationPresent(Pack.class);
        }
    }
);

Method parameter utilities

MethodParameter

encapsulates a Method or Constructor together with a parameter index, allowing retrieval of parameter annotations and generic types.

Method method = UserService.class.getDeclaredMethod("create", String.class, Integer.class);
MethodParameter param = new MethodParameter(method, 0);
Pack annotation = param.getParameterAnnotation(Pack.class);
System.err.println(annotation);

Method method2 = UserService.class.getDeclaredMethod("create", List.class);
MethodParameter param2 = new MethodParameter(method2, 0);
ParameterizedType type = (ParameterizedType) param2.getGenericParameterType();
System.err.println(type.getActualTypeArguments()[0]);

Running result:

@com.pack.inner.Pack()
class com.pack.inner.User

Generic type resolution

GenericTypeResolver

resolves actual generic arguments of classes, interfaces, or super‑classes, overcoming type erasure.

public class GenericTypeResolverTest {
    public interface BaseDao<T, ID> {}
    public abstract class AbstractService<T> {}
    public class UserDao implements BaseDao<User, Long> {}
    public class UserService extends AbstractService<User> {}
    public static void main(String[] args) {
        Class<?> entityCls = GenericTypeResolver.resolveTypeArgument(UserService.class, AbstractService.class);
        System.out.println("UserDao generic entity type: " + entityCls.getSimpleName()); // User
        Class<?>[] allTypes = GenericTypeResolver.resolveTypeArguments(UserDao.class, BaseDao.class);
        System.out.println("Primary key type: " + allTypes[1].getSimpleName()); // Long
    }
}

Running result:

UserDao generic entity type: User
Primary key type: Long

Process ID

ApplicationPid

returns the current JVM PID (e.g., "26052"). Registering ApplicationPidFileWriter via META-INF/spring.factories writes the PID to application.pid on startup.

// META-INF/spring.factories
org.springframework.context.ApplicationListener=\
org.springframework.boot.context.ApplicationPidFileWriter

Property binding

Use @ConfigurationProperties to bind a group of configuration entries to a POJO.

@Component
@ConfigurationProperties(prefix = "pack.app")
public class NameProperties {
    private String title;
    private String version;
    private List<String> author;
}

# application.yml
pack:
  app:
    title: xxxooo
    version: 1.0.0
    author: pack,xg,wcy

If a property name differs from the field name, @Name can rename it; @Delimiter changes the list separator.

@Name("v")
private String version;

@Delimiter("@")
private List<String> author;

# yaml example
pack:
  app:
    v: 1.0.0
    author: pack@xg@wcy

Package path retrieval and registration

AutoConfigurationPackages.get(context)

returns the base packages detected by Spring Boot. Custom packages can be registered with AutoConfigurationPackages.register, which is useful for third‑party auto‑configuration components.

@Component
public class PackagePathRunner implements CommandLineRunner {
    private final ApplicationContext context;
    public PackagePathRunner(ApplicationContext context) { this.context = context; }
    @Override
    public void run(String... args) throws Exception {
        System.err.println(AutoConfigurationPackages.get(context));
    }
}

public class PkgBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        AutoConfigurationPackages.register(registry, "cn.pack", "org.pack");
    }
}

Note: registering packages does not trigger component scanning for those packages; it merely makes the package list available to other auto‑configuration mechanisms.

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.

JavaConfigurationSpring BootCode SimplificationUtility ClassesGenericTypeResolverMethodIntrospector
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

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.