22
22
import static org .hamcrest .Matchers .greaterThan ;
23
23
import static org .hamcrest .Matchers .lessThan ;
24
24
import static org .junit .Assert .assertThat ;
25
+ import static org .junit .Assert .assertTrue ;
25
26
import static org .junit .Assert .fail ;
26
27
27
28
import java .beans .BeanInfo ;
28
29
import java .beans .IndexedPropertyDescriptor ;
29
30
import java .beans .IntrospectionException ;
30
31
import java .beans .Introspector ;
31
32
import java .beans .PropertyDescriptor ;
33
+ import java .lang .reflect .Method ;
32
34
33
35
import org .junit .Test ;
34
36
import org .springframework .beans .ExtendedBeanInfo .PropertyDescriptorComparator ;
37
+ import org .springframework .util .ClassUtils ;
35
38
36
39
import test .beans .TestBean ;
37
40
@@ -660,13 +663,14 @@ private boolean hasIndexedReadMethodForProperty(BeanInfo beanInfo, String proper
660
663
return false ;
661
664
}
662
665
666
+
663
667
@ Test
664
668
public void reproSpr8806 () throws IntrospectionException {
665
669
// does not throw
666
670
Introspector .getBeanInfo (LawLibrary .class );
667
671
668
672
// does not throw after the changes introduced in SPR-8806
669
- new ExtendedBeanInfo (Introspector .getBeanInfo (LawLibrary .class ));
673
+ new ExtendedBeanInfo (Introspector .getBeanInfo (LawLibrary .class ));
670
674
}
671
675
672
676
interface Book { }
@@ -692,4 +696,51 @@ public void setBook(Book book) { }
692
696
class LawLibrary extends Library implements TextBookOperations {
693
697
public LawBook getBook () { return null ; }
694
698
}
699
+
700
+
701
+ /**
702
+ * java.beans.Introspector returns the "wrong" declaring class for overridden read
703
+ * methods, which in turn violates expectations in {@link ExtendedBeanInfo} regarding
704
+ * method equality. Spring's {@link ClassUtils#getMostSpecificMethod(Method, Class)}
705
+ * helps out here, and is now put into use in ExtendedBeanInfo as well
706
+ */
707
+ @ Test
708
+ public void demonstrateCauseSpr8949 () throws IntrospectionException {
709
+ BeanInfo info = Introspector .getBeanInfo (B .class );
710
+
711
+ for (PropertyDescriptor pd : info .getPropertyDescriptors ()) {
712
+ if ("targetMethod" .equals (pd .getName ())) {
713
+ Method readMethod = pd .getReadMethod ();
714
+ assertTrue (readMethod .getDeclaringClass ().equals (A .class )); // we expected B!
715
+
716
+ Method msReadMethod = ClassUtils .getMostSpecificMethod (readMethod , B .class );
717
+ assertTrue (msReadMethod .getDeclaringClass ().equals (B .class )); // and now we get it.
718
+ }
719
+ }
720
+ }
721
+
722
+ @ Test
723
+ public void cornerSpr8949 () throws IntrospectionException {
724
+ BeanInfo bi = Introspector .getBeanInfo (B .class );
725
+ ExtendedBeanInfo ebi = new ExtendedBeanInfo (bi );
726
+
727
+ assertThat (hasReadMethodForProperty (bi , "targetMethod" ), is (true ));
728
+ assertThat (hasWriteMethodForProperty (bi , "targetMethod" ), is (false ));
729
+
730
+ assertThat (hasReadMethodForProperty (ebi , "targetMethod" ), is (true ));
731
+ assertThat (hasWriteMethodForProperty (ebi , "targetMethod" ), is (false ));
732
+ }
733
+
734
+ static class A {
735
+ public boolean isTargetMethod () {
736
+ return false ;
737
+ }
738
+ }
739
+
740
+ static class B extends A {
741
+ @ Override
742
+ public boolean isTargetMethod () {
743
+ return false ;
744
+ }
745
+ }
695
746
}
0 commit comments