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,25 @@ 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
+ if (winner != null ) {
122
+ addGetMethod (propName , winner , isAmbiguous );
123
+ }
123
124
}
124
125
}
125
126
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
- }
127
+ private void addGetMethod (String name , Method method , boolean isAmbiguous ) {
128
+ MethodInvoker invoker = isAmbiguous
129
+ ? new AmbiguousMethodInvoker (method , MessageFormat .format (
130
+ "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results." ,
131
+ name , method .getDeclaringClass ().getName ()))
132
+ : new MethodInvoker (method );
133
+ getMethods .put (name , invoker );
134
+ Type returnType = TypeParameterResolver .resolveReturnType (method , type );
135
+ getTypes .put (name , typeToClass (returnType ));
132
136
}
133
137
134
138
private void addSetMethods (Class <?> clazz ) {
@@ -140,35 +144,26 @@ private void addSetMethods(Class<?> clazz) {
140
144
}
141
145
142
146
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 );
147
+ if (isValidPropertyName (name )) {
148
+ List <Method > list = conflictingMethods .computeIfAbsent (name , k -> new ArrayList <>());
149
+ list .add (method );
150
+ }
145
151
}
146
152
147
153
private void resolveSetterConflicts (Map <String , List <Method >> conflictingSetters ) {
148
154
for (String propName : conflictingSetters .keySet ()) {
149
155
List <Method > setters = conflictingSetters .get (propName );
150
156
Class <?> getterType = getTypes .get (propName );
151
157
Method match = null ;
152
- ReflectionException exception = null ;
153
158
for (Method setter : setters ) {
154
159
if (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
- }
167
- }
164
+ match = pickBetterSetter (match , setter , propName );
168
165
}
169
- if (match == null ) {
170
- throw exception ;
171
- } else {
166
+ if (match != null ) {
172
167
addSetMethod (propName , match );
173
168
}
174
169
}
@@ -185,17 +180,21 @@ private Method pickBetterSetter(Method setter1, Method setter2, String property)
185
180
} else if (paramType2 .isAssignableFrom (paramType1 )) {
186
181
return setter1 ;
187
182
}
188
- throw new ReflectionException ("Ambiguous setters defined for property '" + property + "' in class '"
189
- + setter2 .getDeclaringClass () + "' with types '" + paramType1 .getName () + "' and '"
190
- + paramType2 .getName () + "'." );
183
+ MethodInvoker invoker = new AmbiguousMethodInvoker (setter1 ,
184
+ MessageFormat .format (
185
+ "Ambiguous setters defined for property ''{0}'' in class ''{1}'' with types ''{2}'' and ''{3}''." ,
186
+ property , setter2 .getDeclaringClass ().getName (), paramType1 .getName (), paramType2 .getName ()));
187
+ setMethods .put (property , invoker );
188
+ Type [] paramTypes = TypeParameterResolver .resolveParamTypes (setter1 , type );
189
+ setTypes .put (property , typeToClass (paramTypes [0 ]));
190
+ return null ;
191
191
}
192
192
193
193
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
- }
194
+ MethodInvoker invoker = new MethodInvoker (method );
195
+ setMethods .put (name , invoker );
196
+ Type [] paramTypes = TypeParameterResolver .resolveParamTypes (method , type );
197
+ setTypes .put (name , typeToClass (paramTypes [0 ]));
199
198
}
200
199
201
200
private Class <?> typeToClass (Type src ) {
0 commit comments