Skip to content

Commit 9568941

Browse files
committed
Reduce overhead of ClassPropertyFetcher
1 parent 361734c commit 9568941

File tree

1 file changed

+61
-76
lines changed

1 file changed

+61
-76
lines changed

grails-core/src/main/groovy/org/grails/core/util/ClassPropertyFetcher.java

Lines changed: 61 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@
2020
import java.lang.reflect.InvocationTargetException;
2121
import java.lang.reflect.Method;
2222
import java.lang.reflect.Modifier;
23-
import java.util.ArrayList;
24-
import java.util.Collections;
25-
import java.util.HashMap;
26-
import java.util.List;
27-
import java.util.Map;
23+
import java.util.*;
2824
import java.util.concurrent.ConcurrentHashMap;
2925

3026
import grails.util.GrailsClassUtils;
31-
import org.grails.beans.support.CachedIntrospectionResults;
27+
import grails.util.GrailsNameUtils;
28+
import groovy.lang.GroovyObjectSupport;
29+
import groovy.lang.Script;
30+
import org.springframework.beans.BeanUtils;
3231
import org.springframework.util.ReflectionUtils;
3332
import org.springframework.util.ReflectionUtils.FieldCallback;
3433
import org.springframework.util.ReflectionUtils.MethodCallback;
@@ -45,11 +44,16 @@
4544
*/
4645
public class ClassPropertyFetcher {
4746

47+
private static final Set<String> IGNORED_FIELD_NAMES = new HashSet<String>() {{
48+
add("class");
49+
add("metaClass");
50+
}};
4851
private final Class<?> clazz;
49-
final Map<String, PropertyFetcher> staticFetchers = new HashMap<String, PropertyFetcher>();
50-
final Map<String, PropertyFetcher> instanceFetchers = new HashMap<String, PropertyFetcher>();
52+
private final Map<String, PropertyFetcher> staticFetchers = new HashMap<>();
53+
private final Map<String, PropertyFetcher> instanceFetchers = new HashMap<>();
5154
private final ReferenceInstanceCallback callback;
52-
private PropertyDescriptor[] propertyDescriptors;
55+
private final FieldCallback fieldCallback;
56+
private final MethodCallback methodCallback;
5357

5458
private static Map<Class<?>, ClassPropertyFetcher> cachedClassPropertyFetchers = new ConcurrentHashMap<Class<?>, ClassPropertyFetcher>();
5559

@@ -92,27 +96,7 @@ public Object getReferenceInstance() {
9296
protected ClassPropertyFetcher(Class<?> clazz, ReferenceInstanceCallback callback) {
9397
this.clazz = clazz;
9498
this.callback = callback;
95-
init();
96-
}
97-
98-
public Object getReference() {
99-
if (callback != null) {
100-
return callback.getReferenceInstance();
101-
}
102-
return null;
103-
}
104-
105-
public PropertyDescriptor[] getPropertyDescriptors() {
106-
return propertyDescriptors;
107-
}
108-
109-
public boolean isReadableProperty(String name) {
110-
return staticFetchers.containsKey(name)
111-
|| instanceFetchers.containsKey(name);
112-
}
113-
114-
private void init() {
115-
FieldCallback fieldCallback = new ReflectionUtils.FieldCallback() {
99+
fieldCallback = new ReflectionUtils.FieldCallback() {
116100
public void doWith(Field field) {
117101
if (field.isSynthetic()) {
118102
return;
@@ -124,29 +108,31 @@ public void doWith(Field field) {
124108

125109
final String name = field.getName();
126110
if (name.indexOf('$') == -1) {
111+
if(IGNORED_FIELD_NAMES.contains(name)) return;
112+
127113
boolean staticField = Modifier.isStatic(modifiers);
128114
if (staticField) {
129-
staticFetchers.put(name, new FieldReaderFetcher(field,
130-
staticField));
115+
staticFetchers.put(name, new FieldReaderFetcher(field,true));
131116
} else {
132-
instanceFetchers.put(name, new FieldReaderFetcher(
133-
field, staticField));
117+
instanceFetchers.put(name, new FieldReaderFetcher(field, false));
134118
}
135119
}
136120
}
137121
};
138122

139-
MethodCallback methodCallback = new ReflectionUtils.MethodCallback() {
123+
methodCallback = new ReflectionUtils.MethodCallback() {
140124
public void doWith(Method method) throws IllegalArgumentException,
141125
IllegalAccessException {
142126
if (method.isSynthetic()) {
143127
return;
144128
}
145-
if (!Modifier.isPublic(method.getModifiers())) {
129+
int modifiers = method.getModifiers();
130+
Class<?> returnType = method.getReturnType();
131+
132+
if (!Modifier.isPublic(modifiers)) {
146133
return;
147134
}
148-
if (Modifier.isStatic(method.getModifiers())
149-
&& method.getReturnType() != Void.class) {
135+
if (returnType != Void.class && returnType != void.class) {
150136
if (method.getParameterTypes().length == 0) {
151137
String name = method.getName();
152138
if (name.indexOf('$') == -1) {
@@ -156,22 +142,46 @@ public void doWith(Method method) throws IllegalArgumentException,
156142
} else if (name.length() > 2
157143
&& name.startsWith("is")
158144
&& Character.isUpperCase(name.charAt(2))
159-
&& (method.getReturnType() == Boolean.class ||
160-
method.getReturnType() == boolean.class)) {
145+
&& (returnType == Boolean.class ||
146+
returnType == boolean.class)) {
161147
name = name.substring(2);
162148
}
163-
PropertyFetcher fetcher = new GetterPropertyFetcher(
164-
method, true);
165-
staticFetchers.put(name, fetcher);
166-
staticFetchers.put(StringUtils.uncapitalize(name), fetcher);
149+
if (Modifier.isStatic(modifiers)) {
150+
GetterPropertyFetcher fetcher = new GetterPropertyFetcher(method, true);
151+
staticFetchers.put(name, fetcher);
152+
staticFetchers.put(StringUtils.uncapitalize(name),
153+
fetcher);
154+
} else {
155+
instanceFetchers.put(StringUtils.uncapitalize(name),
156+
new GetterPropertyFetcher(method, false));
157+
}
167158
}
168159
}
169160
}
170161
}
171162
};
163+
init();
164+
}
165+
166+
public Object getReference() {
167+
if (callback != null) {
168+
return callback.getReferenceInstance();
169+
}
170+
return null;
171+
}
172+
173+
public PropertyDescriptor[] getPropertyDescriptors() {
174+
return getPropertyDescriptors(clazz);
175+
}
176+
177+
public boolean isReadableProperty(String name) {
178+
return staticFetchers.containsKey(name)
179+
|| instanceFetchers.containsKey(name);
180+
}
172181

182+
private void init() {
173183
Class<?> superclass = clazz.getSuperclass();
174-
while (superclass != Object.class && superclass != null) {
184+
while (superclass != Object.class && superclass != Script.class && superclass != GroovyObjectSupport.class && superclass != null) {
175185
ClassPropertyFetcher superFetcher = ClassPropertyFetcher.forClass(superclass);
176186
staticFetchers.putAll(superFetcher.staticFetchers);
177187
instanceFetchers.putAll(superFetcher.instanceFetchers);
@@ -199,35 +209,10 @@ public void doWith(Method method) throws IllegalArgumentException,
199209
}
200210
}
201211

202-
propertyDescriptors = getPropertyDescriptors(clazz);
203-
for (PropertyDescriptor desc : propertyDescriptors) {
204-
Method readMethod = desc.getReadMethod();
205-
if (readMethod != null) {
206-
boolean staticReadMethod = Modifier.isStatic(readMethod.getModifiers());
207-
if (staticReadMethod) {
208-
staticFetchers.put(desc.getName(),
209-
new GetterPropertyFetcher(readMethod, staticReadMethod));
210-
} else {
211-
instanceFetchers.put(desc.getName(),
212-
new GetterPropertyFetcher(readMethod, staticReadMethod));
213-
}
214-
}
215-
}
216212
}
217213

218214
private PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) {
219-
return CachedIntrospectionResults.forClass(clazz).getPropertyDescriptors();
220-
}
221-
222-
private List<Class<?>> resolveAllClasses(Class<?> c) {
223-
List<Class<?>> list = new ArrayList<Class<?>>();
224-
Class<?> currentClass = c;
225-
while (currentClass != Object.class) {
226-
list.add(currentClass);
227-
currentClass = currentClass.getSuperclass();
228-
}
229-
Collections.reverse(list);
230-
return list;
215+
return BeanUtils.getPropertyDescriptors(clazz);
231216
}
232217

233218
public Object getPropertyValue(String name) {
@@ -311,14 +296,14 @@ public Class<?> getPropertyType(String name, boolean onlyInstanceProperties) {
311296
return null;
312297
}
313298

314-
public static interface ReferenceInstanceCallback {
315-
public Object getReferenceInstance();
299+
public interface ReferenceInstanceCallback {
300+
Object getReferenceInstance();
316301
}
317302

318-
static interface PropertyFetcher {
319-
public Object get(ReferenceInstanceCallback callback)
303+
interface PropertyFetcher {
304+
Object get(ReferenceInstanceCallback callback)
320305
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
321-
public Class<?> getPropertyType(String name);
306+
Class<?> getPropertyType(String name);
322307
}
323308

324309
static class GetterPropertyFetcher implements PropertyFetcher {

0 commit comments

Comments
 (0)