24
24
import java .lang .reflect .ParameterizedType ;
25
25
import java .lang .reflect .ReflectPermission ;
26
26
import java .lang .reflect .Type ;
27
+ import java .text .MessageFormat ;
27
28
import java .util .ArrayList ;
28
29
import java .util .Arrays ;
29
30
import java .util .Collection ;
33
34
import java .util .Map ;
34
35
import java .util .Map .Entry ;
35
36
37
+ import org .apache .ibatis .reflection .invoker .AmbiguousMethodInvoker ;
36
38
import org .apache .ibatis .reflection .invoker .GetFieldInvoker ;
37
39
import org .apache .ibatis .reflection .invoker .Invoker ;
38
40
import org .apache .ibatis .reflection .invoker .MethodInvoker ;
@@ -92,6 +94,7 @@ private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters
92
94
for (Entry <String , List <Method >> entry : conflictingGetters .entrySet ()) {
93
95
Method winner = null ;
94
96
String propName = entry .getKey ();
97
+ boolean isAmbiguous = false ;
95
98
for (Method candidate : entry .getValue ()) {
96
99
if (winner == null ) {
97
100
winner = candidate ;
@@ -101,10 +104,8 @@ private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters
101
104
Class <?> candidateType = candidate .getReturnType ();
102
105
if (candidateType .equals (winnerType )) {
103
106
if (!boolean .class .equals (candidateType )) {
104
- throw new ReflectionException (
105
- "Illegal overloaded getter method with ambiguous type for property "
106
- + propName + " in class " + winner .getDeclaringClass ()
107
- + ". This breaks the JavaBeans specification and can cause unpredictable results." );
107
+ isAmbiguous = true ;
108
+ break ;
108
109
} else if (candidate .getName ().startsWith ("is" )) {
109
110
winner = candidate ;
110
111
}
@@ -113,22 +114,23 @@ private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters
113
114
} else if (winnerType .isAssignableFrom (candidateType )) {
114
115
winner = candidate ;
115
116
} else {
116
- throw new ReflectionException (
117
- "Illegal overloaded getter method with ambiguous type for property "
118
- + propName + " in class " + winner .getDeclaringClass ()
119
- + ". This breaks the JavaBeans specification and can cause unpredictable results." );
117
+ isAmbiguous = true ;
118
+ break ;
120
119
}
121
120
}
122
- addGetMethod (propName , winner );
121
+ addGetMethod (propName , winner , isAmbiguous );
123
122
}
124
123
}
125
124
126
- private void addGetMethod (String name , Method method ) {
127
- if (isValidPropertyName (name )) {
128
- getMethods .put (name , new MethodInvoker (method ));
129
- Type returnType = TypeParameterResolver .resolveReturnType (method , type );
130
- getTypes .put (name , typeToClass (returnType ));
131
- }
125
+ private void addGetMethod (String name , Method method , boolean isAmbiguous ) {
126
+ MethodInvoker invoker = isAmbiguous
127
+ ? new AmbiguousMethodInvoker (method , MessageFormat .format (
128
+ "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results." ,
129
+ name , method .getDeclaringClass ().getName ()))
130
+ : new MethodInvoker (method );
131
+ getMethods .put (name , invoker );
132
+ Type returnType = TypeParameterResolver .resolveReturnType (method , type );
133
+ getTypes .put (name , typeToClass (returnType ));
132
134
}
133
135
134
136
private void addSetMethods (Class <?> clazz ) {
@@ -140,35 +142,31 @@ private void addSetMethods(Class<?> clazz) {
140
142
}
141
143
142
144
private void addMethodConflict (Map <String , List <Method >> conflictingMethods , String name , Method method ) {
143
- List <Method > list = conflictingMethods .computeIfAbsent (name , k -> new ArrayList <>());
144
- list .add (method );
145
+ if (isValidPropertyName (name )) {
146
+ List <Method > list = conflictingMethods .computeIfAbsent (name , k -> new ArrayList <>());
147
+ list .add (method );
148
+ }
145
149
}
146
150
147
151
private void resolveSetterConflicts (Map <String , List <Method >> conflictingSetters ) {
148
152
for (String propName : conflictingSetters .keySet ()) {
149
153
List <Method > setters = conflictingSetters .get (propName );
150
154
Class <?> getterType = getTypes .get (propName );
155
+ boolean isGetterAmbiguous = getMethods .get (propName ) instanceof AmbiguousMethodInvoker ;
156
+ boolean isSetterAmbiguous = false ;
151
157
Method match = null ;
152
- ReflectionException exception = null ;
153
158
for (Method setter : setters ) {
154
- if (setter .getParameterTypes ()[0 ].equals (getterType )) {
159
+ if (! isGetterAmbiguous && setter .getParameterTypes ()[0 ].equals (getterType )) {
155
160
// should be the best match
156
161
match = setter ;
157
162
break ;
158
163
}
159
- if (exception == null ) {
160
- try {
161
- match = pickBetterSetter (match , setter , propName );
162
- } catch (ReflectionException e ) {
163
- // there could still be the 'best match'
164
- match = null ;
165
- exception = e ;
166
- }
164
+ if (!isSetterAmbiguous ) {
165
+ match = pickBetterSetter (match , setter , propName );
166
+ isSetterAmbiguous = match == null ;
167
167
}
168
168
}
169
- if (match == null ) {
170
- throw exception ;
171
- } else {
169
+ if (match != null ) {
172
170
addSetMethod (propName , match );
173
171
}
174
172
}
@@ -185,17 +183,21 @@ private Method pickBetterSetter(Method setter1, Method setter2, String property)
185
183
} else if (paramType2 .isAssignableFrom (paramType1 )) {
186
184
return setter1 ;
187
185
}
188
- throw new ReflectionException ("Ambiguous setters defined for property '" + property + "' in class '"
189
- + setter2 .getDeclaringClass () + "' with types '" + paramType1 .getName () + "' and '"
190
- + paramType2 .getName () + "'." );
186
+ MethodInvoker invoker = new AmbiguousMethodInvoker (setter1 ,
187
+ MessageFormat .format (
188
+ "Ambiguous setters defined for property ''{0}'' in class ''{1}'' with types ''{2}'' and ''{3}''." ,
189
+ property , setter2 .getDeclaringClass ().getName (), paramType1 .getName (), paramType2 .getName ()));
190
+ setMethods .put (property , invoker );
191
+ Type [] paramTypes = TypeParameterResolver .resolveParamTypes (setter1 , type );
192
+ setTypes .put (property , typeToClass (paramTypes [0 ]));
193
+ return null ;
191
194
}
192
195
193
196
private void addSetMethod (String name , Method method ) {
194
- if (isValidPropertyName (name )) {
195
- setMethods .put (name , new MethodInvoker (method ));
196
- Type [] paramTypes = TypeParameterResolver .resolveParamTypes (method , type );
197
- setTypes .put (name , typeToClass (paramTypes [0 ]));
198
- }
197
+ MethodInvoker invoker = new MethodInvoker (method );
198
+ setMethods .put (name , invoker );
199
+ Type [] paramTypes = TypeParameterResolver .resolveParamTypes (method , type );
200
+ setTypes .put (name , typeToClass (paramTypes [0 ]));
199
201
}
200
202
201
203
private Class <?> typeToClass (Type src ) {
0 commit comments