1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
41
41
import org .springframework .beans .testfixture .beans .DerivedTestBean ;
42
42
import org .springframework .beans .testfixture .beans .ITestBean ;
43
43
import org .springframework .beans .testfixture .beans .TestBean ;
44
+ import org .springframework .cglib .proxy .Enhancer ;
45
+ import org .springframework .cglib .proxy .MethodInterceptor ;
44
46
import org .springframework .core .io .Resource ;
45
47
import org .springframework .core .io .ResourceEditor ;
46
48
import org .springframework .lang .Nullable ;
51
53
import static org .assertj .core .api .SoftAssertions .assertSoftly ;
52
54
53
55
/**
54
- * Unit tests for {@link BeanUtils}.
56
+ * Tests for {@link BeanUtils}.
55
57
*
56
58
* @author Juergen Hoeller
57
59
* @author Rob Harrop
@@ -321,12 +323,13 @@ void copyPropertiesIgnoresGenericsIfSourceOrTargetHasUnresolvableGenerics() thro
321
323
Order original = new Order ("test" , List .of ("foo" , "bar" ));
322
324
323
325
// Create a Proxy that loses the generic type information for the getLineItems() method.
324
- OrderSummary proxy = proxyOrder (original );
326
+ OrderSummary proxy = (OrderSummary ) Proxy .newProxyInstance (getClass ().getClassLoader (),
327
+ new Class <?>[] {OrderSummary .class }, new OrderInvocationHandler (original ));
325
328
assertThat (OrderSummary .class .getDeclaredMethod ("getLineItems" ).toGenericString ())
326
- .contains ("java.util.List<java.lang.String>" );
329
+ .contains ("java.util.List<java.lang.String>" );
327
330
assertThat (proxy .getClass ().getDeclaredMethod ("getLineItems" ).toGenericString ())
328
- .contains ("java.util.List" )
329
- .doesNotContain ("<java.lang.String>" );
331
+ .contains ("java.util.List" )
332
+ .doesNotContain ("<java.lang.String>" );
330
333
331
334
// Ensure that our custom Proxy works as expected.
332
335
assertThat (proxy .getId ()).isEqualTo ("test" );
@@ -339,6 +342,23 @@ void copyPropertiesIgnoresGenericsIfSourceOrTargetHasUnresolvableGenerics() thro
339
342
assertThat (target .getLineItems ()).containsExactly ("foo" , "bar" );
340
343
}
341
344
345
+ @ Test // gh-32888
346
+ public void copyPropertiesWithGenericCglibClass () {
347
+ Enhancer enhancer = new Enhancer ();
348
+ enhancer .setSuperclass (User .class );
349
+ enhancer .setCallback ((MethodInterceptor ) (obj , method , args , proxy ) -> proxy .invokeSuper (obj , args ));
350
+ User user = (User ) enhancer .create ();
351
+ user .setId (1 );
352
+ user .setName ("proxy" );
353
+ user .setAddress ("addr" );
354
+
355
+ User target = new User ();
356
+ BeanUtils .copyProperties (user , target );
357
+ assertThat (target .getId ()).isEqualTo (user .getId ());
358
+ assertThat (target .getName ()).isEqualTo (user .getName ());
359
+ assertThat (target .getAddress ()).isEqualTo (user .getAddress ());
360
+ }
361
+
342
362
@ Test
343
363
void copyPropertiesWithEditable () throws Exception {
344
364
TestBean tb = new TestBean ();
@@ -518,6 +538,7 @@ public void setNumber(Number number) {
518
538
}
519
539
}
520
540
541
+
521
542
@ SuppressWarnings ("unused" )
522
543
private static class IntegerHolder {
523
544
@@ -532,6 +553,7 @@ public void setNumber(Integer number) {
532
553
}
533
554
}
534
555
556
+
535
557
@ SuppressWarnings ("unused" )
536
558
private static class WildcardListHolder1 {
537
559
@@ -546,6 +568,7 @@ public void setList(List<?> list) {
546
568
}
547
569
}
548
570
571
+
549
572
@ SuppressWarnings ("unused" )
550
573
private static class WildcardListHolder2 {
551
574
@@ -560,6 +583,7 @@ public void setList(List<?> list) {
560
583
}
561
584
}
562
585
586
+
563
587
@ SuppressWarnings ("unused" )
564
588
private static class NumberUpperBoundedWildcardListHolder {
565
589
@@ -574,6 +598,7 @@ public void setList(List<? extends Number> list) {
574
598
}
575
599
}
576
600
601
+
577
602
@ SuppressWarnings ("unused" )
578
603
private static class NumberListHolder {
579
604
@@ -588,6 +613,7 @@ public void setList(List<Number> list) {
588
613
}
589
614
}
590
615
616
+
591
617
@ SuppressWarnings ("unused" )
592
618
private static class IntegerListHolder1 {
593
619
@@ -602,6 +628,7 @@ public void setList(List<Integer> list) {
602
628
}
603
629
}
604
630
631
+
605
632
@ SuppressWarnings ("unused" )
606
633
private static class IntegerListHolder2 {
607
634
@@ -616,6 +643,7 @@ public void setList(List<Integer> list) {
616
643
}
617
644
}
618
645
646
+
619
647
@ SuppressWarnings ("unused" )
620
648
private static class LongListHolder {
621
649
@@ -796,6 +824,7 @@ public void setValue(String aValue) {
796
824
}
797
825
}
798
826
827
+
799
828
private static class BeanWithNullableTypes {
800
829
801
830
private Integer counter ;
@@ -826,6 +855,7 @@ public String getValue() {
826
855
}
827
856
}
828
857
858
+
829
859
private static class BeanWithPrimitiveTypes {
830
860
831
861
private boolean flag ;
@@ -838,7 +868,6 @@ private static class BeanWithPrimitiveTypes {
838
868
private char character ;
839
869
private String text ;
840
870
841
-
842
871
@ SuppressWarnings ("unused" )
843
872
public BeanWithPrimitiveTypes (boolean flag , byte byteCount , short shortCount , int intCount , long longCount ,
844
873
float floatCount , double doubleCount , char character , String text ) {
@@ -889,21 +918,22 @@ public char getCharacter() {
889
918
public String getText () {
890
919
return text ;
891
920
}
892
-
893
921
}
894
922
923
+
895
924
private static class PrivateBeanWithPrivateConstructor {
896
925
897
926
private PrivateBeanWithPrivateConstructor () {
898
927
}
899
928
}
900
929
930
+
901
931
@ SuppressWarnings ("unused" )
902
932
private static class Order {
903
933
904
934
private String id ;
905
- private List <String > lineItems ;
906
935
936
+ private List <String > lineItems ;
907
937
908
938
Order () {
909
939
}
@@ -935,6 +965,7 @@ public String toString() {
935
965
}
936
966
}
937
967
968
+
938
969
private interface OrderSummary {
939
970
940
971
String getId ();
@@ -943,17 +974,10 @@ private interface OrderSummary {
943
974
}
944
975
945
976
946
- private OrderSummary proxyOrder (Order order ) {
947
- return (OrderSummary ) Proxy .newProxyInstance (getClass ().getClassLoader (),
948
- new Class <?>[] { OrderSummary .class }, new OrderInvocationHandler (order ));
949
- }
950
-
951
-
952
977
private static class OrderInvocationHandler implements InvocationHandler {
953
978
954
979
private final Order order ;
955
980
956
-
957
981
OrderInvocationHandler (Order order ) {
958
982
this .order = order ;
959
983
}
@@ -971,4 +995,46 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
971
995
}
972
996
}
973
997
998
+
999
+ private static class GenericBaseModel <T > {
1000
+
1001
+ private T id ;
1002
+
1003
+ private String name ;
1004
+
1005
+ public T getId () {
1006
+ return id ;
1007
+ }
1008
+
1009
+ public void setId (T id ) {
1010
+ this .id = id ;
1011
+ }
1012
+
1013
+ public String getName () {
1014
+ return name ;
1015
+ }
1016
+
1017
+ public void setName (String name ) {
1018
+ this .name = name ;
1019
+ }
1020
+ }
1021
+
1022
+
1023
+ private static class User extends GenericBaseModel <Integer > {
1024
+
1025
+ private String address ;
1026
+
1027
+ public User () {
1028
+ super ();
1029
+ }
1030
+
1031
+ public String getAddress () {
1032
+ return address ;
1033
+ }
1034
+
1035
+ public void setAddress (String address ) {
1036
+ this .address = address ;
1037
+ }
1038
+ }
1039
+
974
1040
}
0 commit comments