Unlock Spring’s Hidden Power: Essential Utility Classes for Faster Backend Development
This article explores Spring 5.3.23’s core utility classes—including ID generators, concurrent LRU cache, concurrency throttling, StopWatch timing, digest calculation, method invocation, reflection helpers, route matching, collection utilities, and placeholder parsing—providing code examples, usage guidelines, and best practices to boost backend development efficiency.
1. Introduction
Spring framework offers many powerful utility classes that help developers work more efficiently. This article delves into the features, usage, and best practices of Spring’s core utilities.
2. Spring Core Utility Classes
2.1 Unique ID Generators
Spring provides three default ID generators and an extensible IdGenerator interface.
<code>@FunctionalInterface
public interface IdGenerator {
UUID generateId();
}</code>Examples:
<code>SimpleIdGenerator idG = new SimpleIdGenerator();
for (int i = 0; i < 3; i++) {
System.out.println(idG.generateId());
}</code>Output:
<code>00000000-0000-0000-0000-000000000001
00000000-0000-0000-0000-000000000002
00000000-0000-0000-0000-000000000003</code>JdkIdGenerator uses UUID.randomUUID():
<code>JdkIdGenerator idG = new JdkIdGenerator();
for (int i = 0; i < 3; i++) {
System.out.println(idG.generateId());
}</code> <code>c63482d8-7a87-465a-a421-ef52d1fedf42
8eafc317-d994-4a1f-884a-dc4911a6e12b
f969bef3-1d2b-448e-9272-8810db002fb9</code>AlternativeJdkIdGenerator uses SecureRandom for better security and performance.
<code>AlternativeJdkIdGenerator idG = new AlternativeJdkIdGenerator();
for (int i = 0; i < 3; i++) {
System.out.println(idG.generateId());
}</code>2.2 Concurrent Local Cache (LRU)
A simple LRU cache backed by ConcurrentHashMap and ConcurrentLinkedDeque.
<code>// Cache with capacity 2, value generated when missing
ConcurrentLruCache<String, String> cache = new ConcurrentLruCache<>(2, key -> {
return String.format("%s-%d", key, new Random().nextInt(1000000));
});
cache.get("a");
System.out.println(cache.get("a"));
System.out.println("------------");
System.out.println(cache.get("b"));
System.out.println("------------");
System.out.println(cache.get("a"));
System.out.println("------------");
System.out.println(cache.get("c"));
System.out.println("------------");
System.out.println(cache.get("b"));
</code>Output example:
<code>a-988467
------------
b-604481
------------
a-988467
------------
c-435476
------------
b-491324</code>2.3 Concurrency Throttle
Abstract class to limit concurrent access, with a default AOP‑based interceptor.
<code>public abstract class ConcurrencyThrottleSupport implements Serializable {
public static final int UNBOUNDED_CONCURRENCY = -1;
public static final int NO_CONCURRENCY = 0;
private transient Object monitor = new Object();
private int concurrencyLimit = UNBOUNDED_CONCURRENCY;
private int concurrencyCount = 0;
protected void beforeAccess() { /* TODO */ }
protected void afterAccess() { /* TODO */ }
}</code> <code>public class ConcurrencyThrottleInterceptor extends ConcurrencyThrottleSupport implements MethodInterceptor, Serializable {
public ConcurrencyThrottleInterceptor() {
setConcurrencyLimit(1);
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
beforeAccess();
try {
return methodInvocation.proceed();
} finally {
afterAccess();
}
}
}</code>Usage via a Spring advisor:
<code>@Component
public class PackAdvisor extends DefaultPointcutAdvisor {
public PackAdvisor() {
super(new ConcurrencyThrottleInterceptor());
}
}</code>2.4 StopWatch – Measuring Execution Time
<code>static StopWatch watch = new StopWatch("task");
public static void entry() throws Exception {
watch.start("task - 1");
System.out.println("TODO - 1");
TimeUnit.SECONDS.sleep(2);
watch.stop();
task2();
task3();
}
public static void task2() throws Exception {
watch.start("task - 2");
System.out.println("TODO - 2");
TimeUnit.SECONDS.sleep(1);
watch.stop();
}
public static void task3() throws Exception {
watch.start("task - 3");
System.out.println("TODO - 3");
TimeUnit.SECONDS.sleep(3);
watch.stop();
}
public static void main(String[] args) throws Exception {
entry();
System.out.println(watch.prettyPrint());
}
</code>Sample output shows total time and per‑task percentages.
2.5 DigestUtils – MD5 Hashing
Utility for MD5 digest without extra dependencies.
<code>byte[] datas = "这是敏感数据".getBytes(StandardCharsets.UTF_8);
String ret = DigestUtils.md5DigestAsHex(datas);
System.out.println(ret);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(datas);
System.out.println(HexUtils.toHexString(digest));
</code>Both methods produce identical results.
2.6 MethodInvoker – Declarative Method Calls
<code>static class PersonService {
private void save(String name) {
System.out.printf("save...%s%n", name);
}
}
public static void main(String[] args) throws Exception {
MethodInvoker invoker = new MethodInvoker();
invoker.setTargetObject(new PersonService());
invoker.setTargetMethod("save");
invoker.setArguments("张三");
invoker.prepare();
invoker.invoke();
}
</code>2.7 ReflectionUtils – Simplified Reflection
<code>@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@interface Pack {}
static class PersonService {
private int age;
@Pack private String name;
public void save(String name) { System.out.printf("save...%s%n", name); }
@Pack public void query() { System.out.println("query..."); }
}
public static void main(String[] args) {
List<Field> fields = new ArrayList<>();
ReflectionUtils.doWithFields(PersonService.class, fields::add,
field -> field.isAnnotationPresent(Pack.class));
System.out.println(fields);
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(PersonService.class, methods::add,
method -> method.isAnnotationPresent(Pack.class));
System.out.println(methods);
}
</code>2.8 RouteMatcher – Path Pattern Matching
<code>String pattern = "/api-1/**";
PathPatternRouteMatcher routeMatcher = new PathPatternRouteMatcher();
Route route = routeMatcher.parseRoute("/api-1/users/666");
boolean ret = routeMatcher.match(pattern, route);
System.out.printf("ret = %b%n", ret);
route = routeMatcher.parseRoute("/api-2/demos");
ret = routeMatcher.match(pattern, route);
System.out.printf("ret = %b%n", ret);
</code>2.9 CollectionUtils – Common Collection Operations
<code>List<String> datas = new ArrayList<>();
boolean ret = CollectionUtils.isEmpty(datas);
System.out.printf("ret = %b%n", ret);
int[] nums = {1,2,3,4,5,6};
List<?> list = CollectionUtils.arrayToList(nums);
System.out.println(list);
List<String> source = new ArrayList<>();
source.add("a"); source.add("b"); source.add("c");
List<String> candidates = new ArrayList<>();
candidates.add("a"); candidates.add("e");
ret = CollectionUtils.containsAny(source, candidates);
System.out.printf("ret = %b%n", ret);
</code>2.10 PropertyPlaceholderHelper – Placeholder Resolution
<code>PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
Properties properties = new Properties();
properties.put("pack.name", "张三");
String value = helper.replacePlaceholders("${pack.name}", properties);
System.out.println(value);
</code>Output: 张三
In summary, the article examined Spring’s core utility classes, which can significantly improve developer productivity.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.