Skip to content

Commit d96b91a

Browse files
author
Phillip Webb
committed
Fix SerializableTypeWrapper equals() performance
Change SerializableTypeWrapper proxies to directly call equals() methods on the underlying Type, rather than possibly generating more wrappers. This should help to improve performance, especially as the equals() method is called many times when the ResolvableType cache is checked. Issue: SPR-11335
1 parent ae06c3a commit d96b91a

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -57,6 +57,11 @@ abstract class SerializableTypeWrapper {
5757
private static final Class<?>[] SUPPORTED_SERIALIZABLE_TYPES = {
5858
GenericArrayType.class, ParameterizedType.class, TypeVariable.class, WildcardType.class};
5959

60+
private static final Method EQUALS_METHOD = ReflectionUtils.findMethod(Object.class,
61+
"equals", Object.class);
62+
63+
private static final Method GET_TYPE_PROVIDER_METHOD = ReflectionUtils.findMethod(
64+
SerializableTypeProxy.class, "getTypeProvider");
6065

6166
/**
6267
* Return a {@link Serializable} variant of {@link Field#getGenericType()}.
@@ -134,7 +139,8 @@ static Type forTypeProvider(final TypeProvider provider) {
134139
for (Class<?> type : SUPPORTED_SERIALIZABLE_TYPES) {
135140
if (type.isAssignableFrom(provider.getType().getClass())) {
136141
ClassLoader classLoader = provider.getClass().getClassLoader();
137-
Class<?>[] interfaces = new Class<?>[] { type, Serializable.class };
142+
Class<?>[] interfaces = new Class<?>[] { type,
143+
SerializableTypeProxy.class, Serializable.class };
138144
InvocationHandler handler = new TypeProxyInvocationHandler(provider);
139145
return (Type) Proxy.newProxyInstance(classLoader, interfaces, handler);
140146
}
@@ -143,6 +149,19 @@ static Type forTypeProvider(final TypeProvider provider) {
143149
}
144150

145151

152+
/**
153+
* Additional interface implemented by the type proxy.
154+
*/
155+
static interface SerializableTypeProxy {
156+
157+
/**
158+
* Return the underlying type provider.
159+
*/
160+
TypeProvider getTypeProvider();
161+
162+
}
163+
164+
146165
/**
147166
* A {@link Serializable} interface providing access to a {@link Type}.
148167
*/
@@ -190,6 +209,17 @@ public TypeProxyInvocationHandler(TypeProvider provider) {
190209

191210
@Override
192211
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
212+
if (GET_TYPE_PROVIDER_METHOD.equals(method)) {
213+
return this.provider;
214+
}
215+
if (EQUALS_METHOD.equals(method)) {
216+
Object other = args[0];
217+
// Unwrap proxies for speed
218+
while (other instanceof SerializableTypeProxy) {
219+
other = ((SerializableTypeProxy) other).getTypeProvider().getType();
220+
}
221+
return this.provider.getType().equals(other);
222+
}
193223
if (Type.class.equals(method.getReturnType()) && args == null) {
194224
return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
195225
}

0 commit comments

Comments
 (0)