mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
805 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8bfd47a8d4 | |||
| 4ec9f5df5c | |||
| 224fcc1712 | |||
| 96eba8b997 | |||
| be5229949c | |||
| 516937cfc5 | |||
| dac97f1b7d | |||
| f2694a8ed9 | |||
| 82f421bff8 | |||
| a2765c009e | |||
| 78d3164543 | |||
| afcc430481 | |||
| 062a15fbd7 | |||
| c04c8a2472 | |||
| f39adcf865 | |||
| da049f480b | |||
| 455d8ac7b9 | |||
| b80c13b722 | |||
| 7bfd683816 | |||
| fe01e5114d | |||
| b5595c3904 | |||
| 76678e9c6a | |||
| b3a34f8397 | |||
| 79adffd214 | |||
| af0a82931e | |||
| bbe5124556 | |||
| 5935b7aefe | |||
| a2d7cc7a69 | |||
| 8a56db6e4e | |||
| 50d6d90ed8 | |||
| a7ffe092ab | |||
| 6407cb9baf | |||
| 0bc0762577 | |||
| 051ab05d32 | |||
| 9d36fd0b68 | |||
| f078e057ce | |||
| 941186a359 | |||
| 27fc4d6053 | |||
| 1943a1f5bd | |||
| a158ff4c3d | |||
| a71bd7c03f | |||
| 1fefe2ab0c | |||
| 0b36c9437e | |||
| 72e7687b80 | |||
| e87355b29c | |||
| 1dc8201df1 | |||
| e3e975d7f9 | |||
| b385ff1d9f | |||
| 3c88029dd3 | |||
| c7adf28f61 | |||
| c555fef6f2 | |||
| ab0b0b31fd | |||
| d24546ad18 | |||
| 2818051aff | |||
| a3bcdbe371 | |||
| 3978d5500d | |||
| 416dee7226 | |||
| 4d69ec48b1 | |||
| 14a9d291e1 | |||
| 5183f71a78 | |||
| fd36af6fcf | |||
| 9179a4fa30 | |||
| 98335b41f7 | |||
| e9f4dec08c | |||
| 4ec695b4d9 | |||
| 2da02ccbd0 | |||
| f2cc70ecf9 | |||
| e2115594c0 | |||
| 2008e04354 | |||
| b4f83dbdc3 | |||
| 0795ae5c6a | |||
| 41ab177b6c | |||
| 8848ec73ab | |||
| 9f9481ec7b | |||
| f6275e009b | |||
| ed44262a71 | |||
| a0d37ac29e | |||
| a39938d251 | |||
| edb33331ed | |||
| a63f04df09 | |||
| 5a98516f6c | |||
| 30363c84bd | |||
| fa27130b82 | |||
| be4c07fc32 | |||
| 22f421cc51 | |||
| 9dc538a7c6 | |||
| d74a2730ec | |||
| 3e47f4564d | |||
| a9548f93e4 | |||
| f2e77c292d | |||
| 8b051ab06e | |||
| 5a1d7f9c4b | |||
| b55f69deb1 | |||
| de1eb343e7 | |||
| 417bb302c3 | |||
| b0aa08a671 | |||
| 9dc79982e2 | |||
| 43f2334e82 | |||
| 6c6e44b58e | |||
| c6b60f0c00 | |||
| 7aba6ca9d6 | |||
| dca77c0666 | |||
| df6e690e33 | |||
| a702ef8074 | |||
| f7376bdde3 | |||
| f9e31b503c | |||
| 3551dd92fb | |||
| c23297fe76 | |||
| a5622d0dd2 | |||
| 72cfe41f30 | |||
| 4ff595e2bc | |||
| 2c766b9501 | |||
| 2960a558d7 | |||
| d69a281e5c | |||
| d3ed7b624d | |||
| 66bd277671 | |||
| 881343e928 | |||
| 922fd1e785 | |||
| ea8317a1f9 | |||
| 053ffe808f | |||
| daa2d37ad4 | |||
| f800df12e3 | |||
| 26652a6b83 | |||
| 4cd43dc793 | |||
| 91c8b62817 | |||
| 9d37c099a8 | |||
| eb573d8b9e | |||
| b312a62f64 | |||
| 567733d2a1 | |||
| 0f91f4b960 | |||
| c1385f52c2 | |||
| c3bc125093 | |||
| b5922f75bb | |||
| bbe850d33a | |||
| 295929cc16 | |||
| 4763154193 | |||
| 8f7e5e7c1a | |||
| cd79966c52 | |||
| 7631aa6062 | |||
| 02e09098e4 | |||
| 230c8f93e8 | |||
| c4296fa785 | |||
| ab78854f1b | |||
| 96a465a749 | |||
| 861b9dc938 | |||
| eda2720471 | |||
| 7fe28ce8b7 | |||
| de8c4179fb | |||
| 433877e5cb | |||
| ffa4f03fd4 | |||
| 7068282e1f | |||
| 3879179927 | |||
| 007da2a58d | |||
| 1be585562f | |||
| 7a896d7d80 | |||
| be1aaa06e7 | |||
| 2fa060f0e9 | |||
| 4d2d889142 | |||
| 4b9bc50fd0 | |||
| 3fb8d16ff7 | |||
| 40d5e7cc80 | |||
| 7be4193933 | |||
| aa0face9a1 | |||
| 475c4d4425 | |||
| 9601d4bb5b | |||
| 5d0700b936 | |||
| 6102715b8d | |||
| 65fdd0efeb | |||
| 9dd3cd98ac | |||
| cc379f1cc7 | |||
| 666037ec5c | |||
| 66a3a82fb3 | |||
| 97735e4ffc | |||
| 28ea718d2d | |||
| bc07a54075 | |||
| 8a9321652d | |||
| d9e17a62ce | |||
| 912c270f2b | |||
| 4454ffd2b1 | |||
| 129c05bcff | |||
| b8d32095a9 | |||
| 6393e5ce0c | |||
| 4da27c2a73 | |||
| b1048975d2 | |||
| d232fffa63 | |||
| 8f525f07e9 | |||
| 22a8a668c9 | |||
| 78681c6369 | |||
| 0bc01fcd55 | |||
| 7a8d41e5d6 | |||
| 8dd0974e2f | |||
| e5096be660 | |||
| f79562f8d1 | |||
| a6c45f0cd9 | |||
| 240d6f52c9 | |||
| d553ddc5b3 | |||
| 1cc513d7db | |||
| 9a722b4558 | |||
| 93abe0e94b | |||
| ab96bb5428 | |||
| c1ff97e2a8 | |||
| dd96c873e3 | |||
| a546cf0a3b | |||
| 5fb4c8254f | |||
| 30b63a71bd | |||
| 9244090ba0 | |||
| 17703e5dde | |||
| 7c28152c13 | |||
| b165475eb6 | |||
| 08dad4e3ac | |||
| 695bf2961f | |||
| 53d01392d7 | |||
| 3ac46da22f | |||
| 82cb5dbf2b | |||
| f4813f5b4c | |||
| 8d2f64fe2d | |||
| f9e6ea5482 | |||
| e6020ed377 | |||
| b8d72516e1 | |||
| 4b9e3a9211 | |||
| d95bbb6b1b | |||
| b2d87abcbb | |||
| d1a0b8d53f | |||
| 5861e9685b | |||
| e00384a6fd | |||
| 4aae6a6dda | |||
| 224d52e032 | |||
| f3994467c4 | |||
| 9a27bc9b3e | |||
| c072c6deb5 | |||
| 98ad23bef8 | |||
| 75f70b269e | |||
| b6e9d1c9ad | |||
| 13356a7ee2 | |||
| e3d0ef6015 | |||
| 10cb2ccaef | |||
| 24aae2e104 | |||
| f59ea610df | |||
| c60cefa331 | |||
| 19875d8e3f | |||
| c441d60d1d | |||
| 8d5587fe4f | |||
| 9128226da4 | |||
| a989ea0867 | |||
| 729d0d2796 | |||
| ab2410c754 | |||
| f6ea7407e6 | |||
| d007c25585 | |||
| 0af847c01c | |||
| b2f900e518 | |||
| f00afe3247 | |||
| 8d8e218b52 | |||
| 937cd48fcb | |||
| 38dcd179d5 | |||
| 94924566d5 | |||
| 3b4c7a40c0 | |||
| c56317928f | |||
| 1b83f129a2 | |||
| a8688880b1 | |||
| 51c57d77d9 | |||
| 025ee83403 | |||
| f18d8c31e2 | |||
| d3a0a8e007 | |||
| e0de9126ed | |||
| 19293b9847 | |||
| b5511645b8 | |||
| 94c525cdc8 | |||
| c1405ef140 | |||
| ba5ef6456f | |||
| 639d2c6fe7 | |||
| 1fd5935afa | |||
| 91b803a231 | |||
| f9df8c738a | |||
| 88a17a4b10 | |||
| 0e28bee0f1 | |||
| fdd756ce8a | |||
| 442ddb0845 | |||
| 2ff35daf9b | |||
| 26bb3a0893 | |||
| 8651b8d4c1 | |||
| 99399084a6 | |||
| 578c04ea17 | |||
| 702b27e1e4 | |||
| 2c7efbb9d0 | |||
| b7c423813d | |||
| 3c1adf7f6a | |||
| 9d63f805b3 | |||
| 30583a62cf | |||
| 842c29103f | |||
| 313c6cef32 | |||
| 4fef1fe820 | |||
| 914b2470dc | |||
| b31d55dfce | |||
| 04c2a2990d | |||
| f8588e364a | |||
| 7de2650a70 | |||
| 72bbb2619d | |||
| 541ee13934 | |||
| f7e75a5b82 | |||
| 8d51d6769b | |||
| 2096676b3f | |||
| d4a8f76bf9 | |||
| b8d94f8a20 | |||
| cb8c6e3251 | |||
| 58011f71e9 | |||
| c4e9ce8d0e | |||
| 3988dd9ebb | |||
| 356ef45e99 | |||
| cc12afdea2 | |||
| 5f4d5f17f7 | |||
| 2c2ce55f47 | |||
| d64f2eb038 | |||
| 1db7e02de3 | |||
| 41730220f4 | |||
| 499128dae7 | |||
| 36a222acd5 | |||
| 99bb97388e | |||
| 04a8f81710 | |||
| 967a2ef2d2 | |||
| 50e980c02f | |||
| 1b1a69a144 | |||
| 42b4f6e1ff | |||
| 2575c26020 | |||
| fb7c4a3066 | |||
| 1fa1f2b58a | |||
| e228ded589 | |||
| a3d8c60aba | |||
| 3653a37e27 | |||
| 107f8bb5fd | |||
| 00fea23e6b | |||
| 2a3f90dc7b | |||
| df8061494c | |||
| cf74b1b8be | |||
| 58a5138f26 | |||
| 2f9d0a7de8 | |||
| d89f9af22d | |||
| 0c45c4c6a3 | |||
| 6163f2d32f | |||
| 32b689a994 | |||
| 407ecf7334 | |||
| ed7684d2b2 | |||
| 50253f670e | |||
| 139dc1d373 | |||
| 0f7485b01d | |||
| a02aafe5fe | |||
| eb96ff2943 | |||
| 568c93457a | |||
| e20652009d | |||
| b14301bfba | |||
| 030bc224e3 | |||
| 20287e0cb0 | |||
| 934a995acb | |||
| 0f5a3e2647 | |||
| df0b39e8ac | |||
| f57fcdee3c | |||
| 6f4d25a6e6 | |||
| 2454b31b30 | |||
| f932796201 | |||
| fef0c7b151 | |||
| 4094879daf | |||
| 27815847b1 | |||
| 7a8e0ff3c3 | |||
| eb9c43dcbc | |||
| 90d768bb7f | |||
| 82515a3f01 | |||
| 4a4f2c2f08 | |||
| e48def2d35 | |||
| 6d26e61ac7 | |||
| 4f8c4546f1 | |||
| a0cc80063d | |||
| ff818d56a4 | |||
| c543368aad | |||
| 06fef1e5a4 | |||
| 38ebb6c982 | |||
| d89d95ef1c | |||
| 129530f792 | |||
| cef98e1125 | |||
| cec7204fca | |||
| 2e164787db | |||
| ed936cbd89 | |||
| cd4f0935c5 | |||
| cf1d162e1c | |||
| 9352e3d047 | |||
| 36cfdf68b1 | |||
| fa670dd07d | |||
| bfddbbe731 | |||
| 478162741d | |||
| 6f7ad0304c | |||
| 83300c4b27 | |||
| 8080f56db8 | |||
| a19d4deb24 | |||
| 33cd160861 | |||
| 9962df6527 | |||
| 95aad9cdc2 | |||
| d1ccecd021 | |||
| bf0308b0cf | |||
| 356ef5199e | |||
| 184ed6da57 | |||
| 7bce04c06c | |||
| f835f7b500 | |||
| e12fcca1e3 | |||
| e0e90ed006 | |||
| 6663d0ff07 | |||
| c2d5ca9811 | |||
| 7d89de06e3 | |||
| 15c97b753e | |||
| c6f5acf15d | |||
| 2a379e099c | |||
| 8a56cd0e8b | |||
| b202205d77 | |||
| 49fd724d8f | |||
| 9c55dd5961 | |||
| d3eff49c59 | |||
| 3732032ee4 | |||
| 0ef9568c06 | |||
| 9e55422334 | |||
| 01d9475bcc | |||
| 85984f3b72 | |||
| c782075a13 | |||
| 7f58d9ede0 | |||
| 3531c104b0 | |||
| 67a91cf6f9 | |||
| eeecbaef2c | |||
| 578c078082 | |||
| 0f740527c1 | |||
| 1278459ad5 | |||
| 3d6483873f | |||
| 0939492966 | |||
| a5cbf5fe24 | |||
| 1ab3f88e82 | |||
| bb8cddda23 | |||
| 3bfa56dff2 | |||
| 6959e66b25 | |||
| a6d527e57a | |||
| 1aaefbdd03 | |||
| f316f6a46a | |||
| 3ba858213f | |||
| 0de36d2883 | |||
| d1e9161ca6 | |||
| 37f19a4b43 | |||
| 1ea233ac56 | |||
| d7cab23e6d | |||
| c198138d4e | |||
| 2b4250ec44 | |||
| 9c679fccdf | |||
| ac495d7380 | |||
| c9d08bff41 | |||
| 6920a1f958 | |||
| dcf5c646be | |||
| 1513e7be63 | |||
| 8d3264f680 | |||
| b35274f5a7 | |||
| d5b0df8c3f | |||
| 2be4985b8f | |||
| aa4bcedad3 | |||
| 9801afb85d | |||
| 4db0d999af | |||
| 3d20db1e49 | |||
| 394c30efd0 | |||
| cd8a1bdb8b | |||
| 067ad4c57a | |||
| 52dfc4ebc4 | |||
| 3367df8637 | |||
| 7baf33fea0 | |||
| 1aeae5d40d | |||
| 0ead0503eb | |||
| 6d7573262e | |||
| de7ff556d9 | |||
| 24adc7d3c6 | |||
| 95f7180298 | |||
| 3b810f3544 | |||
| 46cbdff5c3 | |||
| 766e6028d7 | |||
| 7826567df6 | |||
| 99662bc702 | |||
| 45e520ed86 | |||
| 1908080d5c | |||
| 8c37ad7ac5 | |||
| 37609e4ede | |||
| 6bbc5b0f26 | |||
| 30316b16e5 | |||
| 0c78c9c6f7 | |||
| d3cee45f30 | |||
| c11a963b1e | |||
| 02fb5a4121 | |||
| c9aede3727 | |||
| 659f13be1c | |||
| b449928691 | |||
| 0585fb3999 | |||
| 4ee09c89b5 | |||
| 3c631f8ea0 | |||
| a5a069c5b1 | |||
| 73095955bf | |||
| b089ded5b0 | |||
| d5cabca2f7 | |||
| e7076ad35c | |||
| 13f942fab7 | |||
| 8c623c8a42 | |||
| 711b0f50f2 | |||
| 3cbb2b7616 | |||
| d00e1c5e4f | |||
| b5bd977d9a | |||
| 91965500cb | |||
| 55ee250659 | |||
| 0ee505b73e | |||
| 39201adca4 | |||
| 6ea0af3540 | |||
| d3a1d44864 | |||
| 9a6fbf59c5 | |||
| 9bb7fcd997 | |||
| e873b18f43 | |||
| a639535f33 | |||
| c8b860c4b8 | |||
| fc93f99f53 | |||
| 8222698eb2 | |||
| b8c6734580 | |||
| 991eb4858e | |||
| 0d757bf3f7 | |||
| c0b4b5787f | |||
| 909cacec42 | |||
| e381514b07 | |||
| 7da40abba5 | |||
| 4c888d0f32 | |||
| fb61af1882 | |||
| 4318710b9b | |||
| 285b01fc79 | |||
| ac7a699356 | |||
| 5c0ddf3c69 | |||
| 1b98d09855 | |||
| 9551b3a9bb | |||
| efdfe9ad8d | |||
| 1653a32a04 | |||
| 41a4bdea55 | |||
| 5c813a366b | |||
| 0ac117ff27 | |||
| 817a836960 | |||
| 31b25b5808 | |||
| 196f3f8cc1 | |||
| fdde9de005 | |||
| 61117245a6 | |||
| f20eacdb9b | |||
| 0cd427bdd3 | |||
| 609f173ebc | |||
| cfe7ff1c81 | |||
| 4dc964544f | |||
| c5a33d62dd | |||
| 30f6e447d5 | |||
| b3e21ec737 | |||
| 7f96827ade | |||
| 4a1cc9ced7 | |||
| 9c069f6cb1 | |||
| b6ecfcf9ec | |||
| 10caaefd0b | |||
| df3241e072 | |||
| f0dd31a639 | |||
| 8de80ffe9e | |||
| 0ded239453 | |||
| d9a93f44ae | |||
| b6c78452b2 | |||
| b77032c36e | |||
| b2681e1f4a | |||
| c7f60d1799 | |||
| 6d909b013e | |||
| cd57335e46 | |||
| d02e4fb545 | |||
| 857a5b03b7 | |||
| f4de8615aa | |||
| 637e09f995 | |||
| ef2e16912d | |||
| 89d2bd954a | |||
| 4f28c28287 | |||
| 5ff724968d | |||
| 49eec6248d | |||
| e76973c5f0 | |||
| 8d42888476 | |||
| 7772b914c6 | |||
| 32f6ccece8 | |||
| e1fa65a37c | |||
| 4e194c3fbe | |||
| c718ddf7b0 | |||
| 0762131d88 | |||
| 00b95b10a8 | |||
| fbde97f302 | |||
| b612f53e27 | |||
| 0e734d83d5 | |||
| 37ab8a700b | |||
| e49198d49f | |||
| 13c735442c | |||
| ef3f93e84a | |||
| c6b0d85a7c | |||
| a0c9fdba12 | |||
| 165ca12e6d | |||
| 431494096a | |||
| cf100d4d03 | |||
| 8e2be91353 | |||
| 9ef0465c34 | |||
| b948e7cf75 | |||
| 84cc7ffdf6 | |||
| 5d25ca29a6 | |||
| 49f1aa78eb | |||
| 81ca1f7c2b | |||
| cf812ba831 | |||
| 0e6f8df0a8 | |||
| 6db1b692b8 | |||
| 42a2081e8c | |||
| 826db88509 | |||
| 1af052433c | |||
| 97894a1c22 | |||
| 14fa2b18ce | |||
| 4b861aeae6 | |||
| aee8a9c97b | |||
| 91e6274b7d | |||
| 61579ffe7b | |||
| b47491695e | |||
| 9d0e62ef68 | |||
| 3dd6c19c6d | |||
| 0befc60c8f | |||
| 3f3141cdda | |||
| 646fcc5c2f | |||
| b2ce98e881 | |||
| 395c9bd723 | |||
| 142f1ab42f | |||
| 0ca4cd1cf8 | |||
| 36d42bcda4 | |||
| 283811b16b | |||
| aea6bb6357 | |||
| 0fb31c5e36 | |||
| 17f9b61249 | |||
| afd248da8a | |||
| 572c668726 | |||
| 5520e730f1 | |||
| 09f1f727a7 | |||
| 40127bd9ad | |||
| 4c7414833b | |||
| 357fb48d13 | |||
| 513461d4f1 | |||
| c53c8bfc5a | |||
| c211e3998b | |||
| 61d330f805 | |||
| ea5f8f5a7c | |||
| 0c289283ff | |||
| 7ab4d0ca08 | |||
| 214576673a | |||
| 32b4279929 | |||
| 817254f2eb | |||
| fed81c6f83 | |||
| dfe4e01f51 | |||
| df9761cb3f | |||
| 12baafd4f0 | |||
| 1148b61dfa | |||
| bb7152d6e7 | |||
| 61fc321554 | |||
| 4f2e54fc2d | |||
| b97fa4a5ee | |||
| 65a167f7fd | |||
| 0270808b3c | |||
| 823a16ce17 | |||
| 7b4ec72378 | |||
| 437c33ba42 | |||
| 43d3abdfd5 | |||
| 3ae776b1fa | |||
| 61352fe85b | |||
| 6375cc55a3 | |||
| dd09c08cdf | |||
| d6591a6329 | |||
| 42dfa40151 | |||
| 89b81b0080 | |||
| d31767eab8 | |||
| b160f93495 | |||
| 44fd2d96cc | |||
| 9623cdec48 | |||
| 91e39d558f | |||
| c88f11f958 | |||
| 1dbcd66091 | |||
| 4c9ed0d87e | |||
| 06e6386dc9 | |||
| 13a8f90e08 | |||
| a15975d94d | |||
| 93f645800b | |||
| 347c2daa2c | |||
| e39bf87b07 | |||
| 67e7c784e8 | |||
| 384a399fd2 | |||
| c60313de3f | |||
| 84b8ceca0f | |||
| 72e3c43375 | |||
| 8f6d3feaa0 | |||
| 121f9e3734 | |||
| ea73ec5c41 | |||
| cdf2ab9737 | |||
| 19a1477228 | |||
| 5adaa1030c | |||
| f7bf6460aa | |||
| b36af8a11f | |||
| 8a129ef3da | |||
| 69ccba30e9 | |||
| e6893da971 | |||
| 5ed0cf9027 | |||
| 537f79f680 | |||
| 018469286d | |||
| 30e40210a8 | |||
| c8bdb3c602 | |||
| e43439c6c3 | |||
| b2322e58d9 | |||
| d9af4d6599 | |||
| f72318a0ae | |||
| 50b46c9e35 | |||
| 9c7de232b8 | |||
| c326e44488 | |||
| 30c0616384 | |||
| 74b5c371ba | |||
| 846636f2b9 | |||
| cb8ad46564 | |||
| 45828cb934 | |||
| 446e7ed25c | |||
| 73cad470e5 | |||
| 4adc820714 | |||
| 0d151b0212 | |||
| 72590dbb21 | |||
| 7a55d932f9 | |||
| b9e03cb06b | |||
| 4a57e26d76 | |||
| b6191f6057 | |||
| d187cbce73 | |||
| 6a1fe0b1d0 | |||
| 0a06bce3a6 | |||
| 977550f956 | |||
| 18d90ec140 | |||
| d3e0f4dd91 | |||
| 9beb97880f | |||
| 7ad69bfc20 | |||
| 1a154c3e4c | |||
| 37f0e8c6e5 | |||
| 93a522f336 | |||
| 542de82c5f | |||
| 7bf9b767fd | |||
| 0f1f95e090 | |||
| a49123a72b | |||
| dd4f915234 | |||
| d2616b7996 | |||
| deac8e556e | |||
| 8fc16fc937 | |||
| ec6eed6c63 | |||
| 3aee3182ac | |||
| f389f66270 | |||
| 6c3a64578c | |||
| 6e587d5c57 | |||
| 7035ee7ebb | |||
| f23612c3a3 | |||
| 9d27e86951 | |||
| 4577a19190 | |||
| 0075f13126 | |||
| 425a999d5e | |||
| a8cf275aed | |||
| 6df1a7874a | |||
| 99cbfd32c3 | |||
| e3e4f37222 | |||
| 3a51b5a9d2 | |||
| b8201f48fd | |||
| f4d8c7cc2b | |||
| 8e253a316d | |||
| 51aa16f85f | |||
| 8c2e5dcb4a | |||
| 05988193b7 | |||
| 6a7b197af7 | |||
| 73a81f98d4 | |||
| 583201b02c | |||
| f05175586e | |||
| 9d421841d5 | |||
| 260ebeca3a | |||
| f736b665bd | |||
| 76dcde9e31 | |||
| 554662ebab | |||
| ac00d8a215 | |||
| 769ea1b106 | |||
| 206a5e02dd | |||
| 591429e538 | |||
| d198626618 | |||
| 767ea9db83 | |||
| 9f36d170be | |||
| f9689dfe48 | |||
| bf8831157d | |||
| f4e9fb52a8 | |||
| 04ab93ceb4 | |||
| 0ef117ff11 | |||
| fda08852ba | |||
| 203370a810 | |||
| b9a1168580 | |||
| e99b0038a0 | |||
| 91d3e4402f | |||
| 44c95a4736 | |||
| 7368f58518 | |||
| 63c2c08e01 | |||
| dd0d270ba2 | |||
| 873cb4e58b | |||
| b55a2631ba | |||
| 6f73b8b200 | |||
| 2b68212c20 | |||
| 3650ecc3bb | |||
| bec63fbb33 | |||
| 375a63a041 | |||
| 773cd3241b | |||
| f2e8171bfb | |||
| dc3d834026 | |||
| e30f1fbe89 |
+11
-3
@@ -8,6 +8,7 @@ First off, thank you for taking the time to contribute! :+1: :tada:
|
||||
* [How to Contribute](#how-to-contribute)
|
||||
* [Discuss](#discuss)
|
||||
* [Create a Ticket](#create-a-ticket)
|
||||
* [Ticket Lifecycle](#ticket-lifecycle)
|
||||
* [Submit a Pull Request](#submit-a-pull-request)
|
||||
* [Build from Source](#build-from-source)
|
||||
* [Source Code Style](#source-code-style)
|
||||
@@ -35,8 +36,15 @@ it helps us to make a decision.
|
||||
#### Create a Ticket
|
||||
|
||||
Reporting an issue or making a feature request is a great way to contribute. Your feedback
|
||||
and the conversations that result from it provide a continuous flow of ideas. However,
|
||||
before you do that, please take the time to [research first](#Discuss).
|
||||
and the conversations that result from it provide a continuous flow of ideas.
|
||||
|
||||
Before you create a ticket, please take the time to [research first](#discuss).
|
||||
|
||||
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
|
||||
|
||||
When ready create a ticket in the [JIRA issue tracker](https://jira.spring.io/browse/SPR).
|
||||
|
||||
#### Ticket Lifecycle
|
||||
|
||||
When an issue is first created, it may not be assigned and will not have a fix version.
|
||||
Within a day or two, the issue is assigned to a specific committer and the target
|
||||
@@ -56,7 +64,7 @@ You can contribute a source code change by submitting a pull request.
|
||||
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
|
||||
automatically when you submit a pull request.
|
||||
|
||||
1. For all but the most trivial of contributions, please [create a ticket](#Create-a-Ticket).
|
||||
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
|
||||
The purpose of the ticket is to understand and discuss the underlying issue or feature.
|
||||
We use the JIRA issue tracker as the preferred place of record for conversations and
|
||||
conclusions. In that sense discussions directly under a PR are more implementation detail
|
||||
|
||||
@@ -22,8 +22,9 @@ wiki page.
|
||||
|
||||
## Documentation
|
||||
|
||||
The Spring Frameworks maintains
|
||||
[reference documentation](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/),
|
||||
The Spring Frameworks maintains reference documentation
|
||||
([published](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and
|
||||
[source](src/docs/asciidoc)),
|
||||
Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
|
||||
[API reference](http://docs.spring.io/spring-framework/docs/current/javadoc-api/).
|
||||
There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
|
||||
|
||||
+64
-42
@@ -14,8 +14,8 @@ buildscript {
|
||||
plugins {
|
||||
id "com.gradle.build-scan" version "1.8"
|
||||
id "io.spring.dependency-management" version "1.0.3.RELEASE" apply false
|
||||
id "org.jetbrains.kotlin.jvm" version "1.1.61" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.15"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.41" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.17"
|
||||
id "org.asciidoctor.convert" version "1.5.6"
|
||||
}
|
||||
|
||||
@@ -35,54 +35,81 @@ ext {
|
||||
moduleProjects = subprojects.findAll {
|
||||
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
|
||||
}
|
||||
|
||||
aspectjVersion = "1.8.13"
|
||||
freemarkerVersion = "2.3.27-incubating"
|
||||
groovyVersion = "2.4.15"
|
||||
hsqldbVersion = "2.4.1"
|
||||
jackson2Version = "2.9.5"
|
||||
jettyVersion = "9.4.11.v20180605"
|
||||
junitJupiterVersion = "5.0.3"
|
||||
junitPlatformVersion = "1.0.3"
|
||||
junitVintageVersion = "4.12.3"
|
||||
kotlinVersion = "1.2.41"
|
||||
log4jVersion = "2.11.0"
|
||||
nettyVersion = "4.1.25.Final"
|
||||
reactorVersion = "Bismuth-SR10"
|
||||
rxjavaVersion = "1.3.8"
|
||||
rxjavaAdapterVersion = "1.2.1"
|
||||
rxjava2Version = "2.1.14"
|
||||
slf4jVersion = "1.7.25" // spring-jcl + consistent 3rd party deps
|
||||
tiles3Version = "3.0.8"
|
||||
tomcatVersion = "8.5.31"
|
||||
undertowVersion = "1.4.25.Final"
|
||||
|
||||
gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
withoutJclOverSlf4J = {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
}
|
||||
|
||||
configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.13"
|
||||
ext.freemarkerVersion = "2.3.27-incubating"
|
||||
ext.groovyVersion = "2.4.13"
|
||||
ext.hsqldbVersion = "2.4.0"
|
||||
ext.jackson2Version = "2.9.2"
|
||||
ext.jettyVersion = "9.4.7.v20170914"
|
||||
ext.junitJupiterVersion = "5.0.2"
|
||||
ext.junitPlatformVersion = "1.0.2"
|
||||
ext.junitVintageVersion = "4.12.2"
|
||||
ext.kotlinVersion = "1.1.61"
|
||||
ext.log4jVersion = "2.10.0"
|
||||
ext.nettyVersion = "4.1.17.Final"
|
||||
ext.reactorVersion = "Bismuth-SR4"
|
||||
ext.rxjavaVersion = "1.3.4"
|
||||
ext.rxjavaAdapterVersion = "1.2.1"
|
||||
ext.rxjava2Version = "2.1.6"
|
||||
ext.slf4jVersion = "1.7.25"
|
||||
ext.tiles3Version = "3.0.8"
|
||||
ext.tomcatVersion = "8.5.23"
|
||||
ext.undertowVersion = "1.4.21.Final"
|
||||
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "java"
|
||||
apply plugin: "test-source-set-dependencies"
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply from: "${gradleScriptDir}/ide.gradle"
|
||||
|
||||
dependencyManagement {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
generatedPomCustomization {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "kotlin"
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xskip-runtime-version-check", "-Xjsr305=strict"]
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
apiVersion = "1.1"
|
||||
languageVersion = "1.1"
|
||||
}
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xskip-runtime-version-check", "-Xjsr305=strict"]
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
// Check for updates every build
|
||||
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
|
||||
|
||||
// Consistent slf4j version (e.g. clashes between slf4j versions)
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.slf4j') {
|
||||
details.useVersion slf4jVersion
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def commonCompilerArgs =
|
||||
@@ -99,13 +126,13 @@ configure(allprojects) { project ->
|
||||
"-Xlint:-deprecation", "-Xlint:-unchecked"]
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = 1.8
|
||||
sourceCompatibility = 1.8 // can be switched to 10 for testing
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = 1.8
|
||||
sourceCompatibility = 1.8 // can be switched to 10 for testing
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs += "-parameters"
|
||||
@@ -125,7 +152,6 @@ configure(allprojects) { project ->
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-release" }
|
||||
maven { url "https://repo.spring.io/milestone" } // for AspectJ 1.9 beta
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -141,8 +167,9 @@ configure(allprojects) { project ->
|
||||
exclude module:'mockito-core'
|
||||
}
|
||||
testCompile("org.hamcrest:hamcrest-all:1.3")
|
||||
testCompile("org.xmlunit:xmlunit-matchers:2.3.0")
|
||||
testRuntime("org.apache.logging.log4j:log4j-core:${log4jVersion}")
|
||||
testRuntime("org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}")
|
||||
testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
|
||||
// JSR-305 only used for non-required meta-annotations
|
||||
compileOnly("com.google.code.findbugs:jsr305:3.0.2")
|
||||
testCompileOnly("com.google.code.findbugs:jsr305:3.0.2")
|
||||
@@ -178,7 +205,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
manifest.attributes["Created-By"] =
|
||||
"${System.getProperty("java.version")} (${System.getProperty("java.specification.vendor")})"
|
||||
|
||||
from("${rootProject.projectDir}/src/dist") {
|
||||
from("${rootProject.projectDir}/src/docs/dist") {
|
||||
include "license.txt"
|
||||
include "notice.txt"
|
||||
into "META-INF"
|
||||
@@ -224,7 +251,6 @@ configure(rootProject) {
|
||||
description = "Spring Framework"
|
||||
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||
apply from: "${gradleScriptDir}/docs.gradle"
|
||||
|
||||
@@ -232,10 +258,6 @@ configure(rootProject) {
|
||||
imports {
|
||||
mavenBom "io.projectreactor:reactor-bom:${reactorVersion}"
|
||||
}
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
}
|
||||
|
||||
// don't publish the default jar for the root project
|
||||
@@ -257,7 +279,7 @@ configure(rootProject) {
|
||||
testCompile("javax.servlet:javax.servlet-api:3.1.0")
|
||||
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.10.Final")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.14.Final")
|
||||
}
|
||||
|
||||
artifacts {
|
||||
@@ -268,7 +290,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = '4.3.1'
|
||||
gradleVersion = '4.4.1'
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.0.2.RELEASE
|
||||
version=5.0.7.RELEASE
|
||||
|
||||
+10
-7
@@ -49,12 +49,9 @@ task api(type: Javadoc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Need https://github.com/Kotlin/dokka/issues/184 to be fixed to avoid "Can't find node by signature" log spam
|
||||
dokka {
|
||||
dependsOn {
|
||||
subprojects.collect {
|
||||
it.tasks.getByName("jar")
|
||||
}
|
||||
tasks.getByName("api")
|
||||
}
|
||||
doFirst {
|
||||
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
|
||||
@@ -66,10 +63,12 @@ dokka {
|
||||
outputDirectory = "$buildDir/docs/kdoc"
|
||||
|
||||
sourceDirs = files(subprojects.collect { project ->
|
||||
project.sourceSets.main.kotlin.srcDirs
|
||||
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
|
||||
kotlinDirs -= project.sourceSets.main.java.srcDirs
|
||||
})
|
||||
externalDocumentationLink {
|
||||
url = new URL("http://docs.spring.io/spring-framework/docs/${version}/javadoc-api/")
|
||||
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
|
||||
packageListUrl = new File(buildDir, "api/package-list").toURI().toURL()
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("http://projectreactor.io/docs/core/release/api/")
|
||||
@@ -124,10 +123,14 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
|
||||
from (asciidoctor) {
|
||||
from ("$asciidoctor.outputDir/html5") {
|
||||
into "spring-framework-reference"
|
||||
}
|
||||
|
||||
from ("$asciidoctor.outputDir/pdf") {
|
||||
into "spring-framework-reference/pdf"
|
||||
}
|
||||
|
||||
from (dokka) {
|
||||
into "kdoc-api"
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ def customizePom(pom, gradleProject) {
|
||||
"$dep.scope:$dep.groupId:$dep.artifactId"
|
||||
}
|
||||
|
||||
def managedVersions = dependencyManagement.managedVersions
|
||||
generatedPom.dependencies.findAll{dep -> !dep.version }.each { dep ->
|
||||
dep.version = managedVersions["${dep.groupId}:${dep.artifactId}"]
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,5 +1,5 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
/*
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
url "https://dl.bintray.com/kotlin/kotlin-eap-1.1"
|
||||
}
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
include "spring-aop"
|
||||
include "spring-aspects"
|
||||
include "spring-beans"
|
||||
|
||||
@@ -4,6 +4,6 @@ dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(':spring-core'))
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.commons:commons-pool2:2.4.3")
|
||||
optional("org.apache.commons:commons-pool2:2.5.0")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -224,6 +224,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the aspect (bean) in which the advice was declared.
|
||||
*/
|
||||
public void setAspectName(String name) {
|
||||
this.aspectName = name;
|
||||
}
|
||||
@@ -234,7 +237,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <b>declaration order</b> of this advice within the aspect
|
||||
* Set the declaration order of this advice within the aspect.
|
||||
*/
|
||||
public void setDeclarationOrder(int order) {
|
||||
this.declarationOrder = order;
|
||||
@@ -374,7 +377,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* to which argument name. There are multiple strategies for determining
|
||||
* this binding, which are arranged in a ChainOfResponsibility.
|
||||
*/
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
public final synchronized void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
|
||||
return;
|
||||
@@ -382,10 +385,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
int numUnboundArgs = this.parameterTypes.length;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
|
||||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -421,7 +421,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
int firstParenIndex = toMatch.indexOf('(');
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
@@ -582,7 +582,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
if (toMatch.startsWith("!")) {
|
||||
toMatch = toMatch.substring(1);
|
||||
}
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
int firstParenIndex = toMatch.indexOf('(');
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
|
||||
+31
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -289,10 +290,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
|
||||
obtainPointcutExpression();
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
|
||||
// Special handling for this, target, @this, @target, @annotation
|
||||
// in Spring - we can optimize since we know we have exactly this class,
|
||||
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
else {
|
||||
// the maybe case
|
||||
if (beanHasIntroductions) {
|
||||
if (hasIntroductions) {
|
||||
return true;
|
||||
}
|
||||
// A match test returned maybe - if there are any subtype sensitive variables
|
||||
@@ -331,8 +331,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
|
||||
obtainPointcutExpression();
|
||||
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
|
||||
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
|
||||
// consistent with return of MethodInvocationProceedingJoinPoint
|
||||
@@ -367,7 +366,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null && thisObject != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
@@ -427,6 +426,22 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
invocation.setUserAttribute(resolveExpression(), jpm);
|
||||
}
|
||||
|
||||
private ShadowMatch getTargetShadowMatch(Method method, @Nullable Class<?> targetClass) {
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
if (targetClass != null && targetMethod.getDeclaringClass().isInterface()) {
|
||||
// Try to build the most specific interface possible for inherited methods to be
|
||||
// considered for sub-interface matches as well, in particular for proxy classes.
|
||||
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
|
||||
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
|
||||
if (ifcs.size() > 1) {
|
||||
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
|
||||
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
|
||||
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
|
||||
}
|
||||
}
|
||||
return getShadowMatch(targetMethod, method);
|
||||
}
|
||||
|
||||
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
|
||||
// Avoid lock contention for known Methods through concurrent access...
|
||||
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
@@ -434,9 +449,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
synchronized (this.shadowMatchCache) {
|
||||
// Not found - now check again with full lock...
|
||||
PointcutExpression fallbackExpression = null;
|
||||
Method methodToMatch = targetMethod;
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
if (shadowMatch == null) {
|
||||
Method methodToMatch = targetMethod;
|
||||
try {
|
||||
try {
|
||||
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
|
||||
@@ -454,12 +469,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
if (targetMethod != originalMethod && (shadowMatch == null ||
|
||||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
|
||||
// Fall back to the plain original method in case of no resolvable match or a
|
||||
// negative match on a proxy class (which doesn't carry any annotations on its
|
||||
// redeclared methods).
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
@@ -468,7 +487,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-8
@@ -57,6 +57,16 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.order != null) {
|
||||
return this.order;
|
||||
}
|
||||
else {
|
||||
return this.advice.getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
@@ -72,14 +82,13 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.order != null) {
|
||||
return this.order;
|
||||
}
|
||||
else {
|
||||
return this.advice.getOrder();
|
||||
}
|
||||
/**
|
||||
* Return the name of the aspect (bean) in which the advice was declared.
|
||||
* @since 4.3.15
|
||||
* @see AbstractAspectJAdvice#getAspectName()
|
||||
*/
|
||||
public String getAspectName() {
|
||||
return this.advice.getAspectName();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,12 +36,12 @@ public interface AspectJPrecedenceInformation extends Ordered {
|
||||
// its advice for aspects with non-singleton instantiation models.
|
||||
|
||||
/**
|
||||
* The name of the aspect (bean) in which the advice was declared.
|
||||
* Return the name of the aspect (bean) in which the advice was declared.
|
||||
*/
|
||||
String getAspectName();
|
||||
|
||||
/**
|
||||
* The declaration order of the advice member within the aspect.
|
||||
* Return the declaration order of the advice member within the aspect.
|
||||
*/
|
||||
int getDeclarationOrder();
|
||||
|
||||
|
||||
+12
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.IntroductionInterceptor;
|
||||
import org.springframework.aop.support.ClassFilters;
|
||||
import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
@@ -34,12 +35,12 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
*/
|
||||
public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
|
||||
private final Advice advice;
|
||||
|
||||
private final Class<?> introducedInterface;
|
||||
|
||||
private final ClassFilter typePatternClassFilter;
|
||||
|
||||
private final Advice advice;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new advisor for this DeclareParents field.
|
||||
@@ -48,8 +49,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param defaultImpl the default implementation class
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
|
||||
this(interfaceType, typePattern, defaultImpl,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
this(interfaceType, typePattern,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,8 +60,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param delegateRef the delegate implementation object
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
|
||||
this(interfaceType, typePattern, delegateRef.getClass(),
|
||||
new DelegatingIntroductionInterceptor(delegateRef));
|
||||
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(delegateRef));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,18 +68,16 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* (cannot use method such as init() to share common code, due the use of final fields)
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param implementationClass implementation class
|
||||
* @param advice delegation advice
|
||||
* @param interceptor the delegation advice as {@link IntroductionInterceptor}
|
||||
*/
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
|
||||
this.advice = interceptor;
|
||||
this.introducedInterface = interfaceType;
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
|
||||
// Excludes methods implemented.
|
||||
ClassFilter exclusion = clazz -> !(introducedInterface.isAssignableFrom(clazz));
|
||||
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
ClassFilter exclusion = (clazz -> !introducedInterface.isAssignableFrom(clazz));
|
||||
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
|
||||
this.advice = advice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+14
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,17 +33,15 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of AspectJ ProceedingJoinPoint interface
|
||||
* wrapping an AOP Alliance MethodInvocation.
|
||||
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
|
||||
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
|
||||
*
|
||||
* <p><b>Note</b>: the {@code getThis()} method returns the current Spring AOP proxy.
|
||||
* <p><b>Note</b>: The {@code getThis()} method returns the current Spring AOP proxy.
|
||||
* The {@code getTarget()} method returns the current Spring AOP target (which may be
|
||||
* {@code null} if there is no target), and is a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use
|
||||
* {@code getThis()}.</b> A common example is casting the object to an
|
||||
* introduced interface in the implementation of an introduction.
|
||||
*
|
||||
* <p>Of course there is no such distinction between target and proxy in AspectJ.
|
||||
* {@code null} if there is no target instance) as a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use {@code getThis()}.</b>
|
||||
* A common example is casting the object to an introduced interface in the implementation of
|
||||
* an introduction. There is no such distinction between target and proxy in AspectJ itself.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -58,7 +56,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
@Nullable
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
private Object[] args;
|
||||
|
||||
/** Lazily initialized signature object */
|
||||
@Nullable
|
||||
@@ -79,6 +77,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
this.methodInvocation = methodInvocation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void set$AroundClosure(AroundClosure aroundClosure) {
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -120,12 +119,10 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
@Override
|
||||
public Object[] getArgs() {
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
this.defensiveCopyOfArgs = new Object[argsSource.length];
|
||||
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
|
||||
if (this.args == null) {
|
||||
this.args = this.methodInvocation.getArguments().clone();
|
||||
}
|
||||
return this.defensiveCopyOfArgs;
|
||||
return this.args;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +130,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
}
|
||||
return signature;
|
||||
return this.signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -175,7 +175,7 @@ class RuntimeTestWalker {
|
||||
}
|
||||
|
||||
|
||||
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
private abstract static class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private final Class<?> matchClass;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,6 +45,7 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
this.aspectClass = aspectClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the specified aspect class (never {@code null}).
|
||||
*/
|
||||
@@ -52,7 +53,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Object getAspectInstance() {
|
||||
try {
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -170,11 +170,10 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
synchronized (aspectCache) {
|
||||
// To be safe, check within full lock now...
|
||||
instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
if (instance == null) {
|
||||
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
}
|
||||
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
|
||||
+2
-2
@@ -127,7 +127,7 @@ public class AspectMetadata implements Serializable {
|
||||
*/
|
||||
private String findPerClause(Class<?> aspectClass) {
|
||||
String str = aspectClass.getAnnotation(Aspect.class).value();
|
||||
str = str.substring(str.indexOf("(") + 1);
|
||||
str = str.substring(str.indexOf('(') + 1);
|
||||
str = str.substring(0, str.length() - 1);
|
||||
return str;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public class AspectMetadata implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aspect class.
|
||||
* Return the aspect name.
|
||||
*/
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ import org.springframework.lang.Nullable;
|
||||
class InstantiationModelAwarePointcutAdvisorImpl
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
|
||||
|
||||
private static Advice EMPTY_ADVICE = new Advice() {};
|
||||
private static final Advice EMPTY_ADVICE = new Advice() {};
|
||||
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
+6
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -155,7 +154,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
methods.add(method);
|
||||
}
|
||||
});
|
||||
Collections.sort(methods, METHOD_COMPARATOR);
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
return methods;
|
||||
}
|
||||
|
||||
@@ -164,7 +163,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
* for the given introduction field.
|
||||
* <p>Resulting Advisors will need to be evaluated for targets.
|
||||
* @param introductionField the field to introspect
|
||||
* @return {@code null} if not an Advisor
|
||||
* @return the Advisor instance, or {@code null} if not an Advisor
|
||||
*/
|
||||
@Nullable
|
||||
private Advisor getDeclareParentsAdvisor(Field introductionField) {
|
||||
@@ -293,6 +292,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
springAdvice.setArgumentNamesFromStringArray(argNames);
|
||||
}
|
||||
springAdvice.calculateArgumentBindings();
|
||||
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
@@ -306,13 +306,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
|
||||
|
||||
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
|
||||
@Override
|
||||
public void before(Method method, Object[] args, @Nullable Object target) {
|
||||
// Simply instantiate the aspect
|
||||
aif.getAspectInstance();
|
||||
}
|
||||
});
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
|
||||
(method, args, target) -> aif.getAspectInstance());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -67,14 +67,12 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
|
||||
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
|
||||
new ArrayList<>(advisors.size());
|
||||
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
|
||||
for (Advisor element : advisors) {
|
||||
partiallyComparableAdvisors.add(
|
||||
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
|
||||
}
|
||||
List<PartiallyComparableAdvisorHolder> sorted =
|
||||
PartialOrder.sort(partiallyComparableAdvisors);
|
||||
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
|
||||
if (sorted != null) {
|
||||
List<Advisor> result = new ArrayList<>(advisors.size());
|
||||
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
|
||||
@@ -102,10 +100,9 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
// TODO: Consider optimization by caching the list of the aspect names
|
||||
List<Advisor> candidateAdvisors = findCandidateAdvisors();
|
||||
for (Advisor advisor : candidateAdvisors) {
|
||||
if (advisor instanceof AspectJPointcutAdvisor) {
|
||||
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
|
||||
return true;
|
||||
}
|
||||
if (advisor instanceof AspectJPointcutAdvisor &&
|
||||
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.shouldSkip(beanClass, beanName);
|
||||
|
||||
@@ -82,11 +82,11 @@ public abstract class AopNamespaceUtils {
|
||||
|
||||
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
|
||||
if (sourceElement != null) {
|
||||
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
|
||||
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
|
||||
if (proxyTargetClass) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
|
||||
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
|
||||
if (exposeProxy) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -253,8 +253,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
Element aspectElement, String aspectId, List<BeanDefinition> beanDefs,
|
||||
List<BeanReference> beanRefs, ParserContext parserContext) {
|
||||
|
||||
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[beanDefs.size()]);
|
||||
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[beanRefs.size()]);
|
||||
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[0]);
|
||||
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[0]);
|
||||
Object source = parserContext.extractSource(aspectElement);
|
||||
return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -228,7 +228,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
@Override
|
||||
public Class<?>[] getProxiedInterfaces() {
|
||||
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
|
||||
return ClassUtils.toClassArray(this.interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -372,7 +372,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Bring the array up to date with the list.
|
||||
*/
|
||||
protected final void updateAdvisorArray() {
|
||||
this.advisorArray = this.advisors.toArray(new Advisor[this.advisors.size()]);
|
||||
this.advisorArray = this.advisors.toArray(new Advisor[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -205,9 +205,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return createProxyClassAndInstance(enhancer, callbacks);
|
||||
}
|
||||
catch (CodeGenerationException | IllegalArgumentException ex) {
|
||||
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
|
||||
this.advised.getTargetClass() + "]: " +
|
||||
"Common causes of this problem include using a final class or a non-visible class",
|
||||
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
|
||||
": Common causes of this problem include using a final class or a non-visible class",
|
||||
ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,9 +52,9 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
|
||||
|
||||
/**
|
||||
* Set the ordering which will apply to this class's implementation
|
||||
* of Ordered, used when applying multiple processors.
|
||||
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
|
||||
* Set the ordering which will apply to this processor's implementation
|
||||
* of {@link Ordered}, used when applying multiple processors.
|
||||
* <p>The default value is {@code Ordered.LOWEST_PRECEDENCE}, meaning non-ordered.
|
||||
* @param order the ordering value
|
||||
*/
|
||||
public void setOrder(int order) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,7 +90,7 @@ public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Se
|
||||
if (interceptors.isEmpty()) {
|
||||
throw new UnknownAdviceTypeException(advisor.getAdvice());
|
||||
}
|
||||
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
|
||||
return interceptors.toArray(new MethodInterceptor[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Seriali
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
|
||||
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
|
||||
return mi.proceed();
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,7 +70,9 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
|
||||
protected Object[] getAdvicesAndAdvisorsForBean(
|
||||
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
|
||||
|
||||
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
|
||||
if (advisors.isEmpty()) {
|
||||
return DO_NOT_PROXY;
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -544,17 +544,17 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
* @see #setInterceptorNames
|
||||
*/
|
||||
private Advisor[] resolveInterceptorNames() {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory required for resolving interceptor names");
|
||||
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
(ConfigurableBeanFactory) this.beanFactory : null);
|
||||
BeanFactory bf = this.beanFactory;
|
||||
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
for (String beanName : this.interceptorNames) {
|
||||
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
|
||||
Object next = this.beanFactory.getBean(beanName);
|
||||
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
|
||||
Object next = bf.getBean(beanName);
|
||||
advisors.add(this.advisorAdapterRegistry.wrap(next));
|
||||
}
|
||||
}
|
||||
return advisors.toArray(new Advisor[advisors.size()]);
|
||||
return advisors.toArray(new Advisor[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import org.springframework.lang.Nullable;
|
||||
public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator implements BeanNameAware {
|
||||
|
||||
/** Separator between prefix and remainder of bean name */
|
||||
public final static String SEPARATOR = ".";
|
||||
public static final String SEPARATOR = ".";
|
||||
|
||||
|
||||
private boolean usePrefix = false;
|
||||
|
||||
+3
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.aop.framework.autoproxy.target;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -31,7 +30,6 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
@@ -150,11 +148,8 @@ public abstract class AbstractBeanFactoryBasedTargetSourceCreator
|
||||
|
||||
// Filter out BeanPostProcessors that are part of the AOP infrastructure,
|
||||
// since those are only meant to apply to beans defined in the original factory.
|
||||
for (Iterator<BeanPostProcessor> it = internalBeanFactory.getBeanPostProcessors().iterator(); it.hasNext();) {
|
||||
if (it.next() instanceof AopInfrastructureBean) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor ->
|
||||
beanPostProcessor instanceof AopInfrastructureBean);
|
||||
|
||||
return internalBeanFactory;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -192,7 +192,8 @@ public abstract class AopUtils {
|
||||
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
|
||||
*/
|
||||
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
||||
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
|
||||
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
|
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
|
||||
}
|
||||
@@ -236,13 +237,17 @@ public abstract class AopUtils {
|
||||
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
|
||||
}
|
||||
|
||||
Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
|
||||
classes.add(targetClass);
|
||||
Set<Class<?>> classes = new LinkedHashSet<>();
|
||||
if (!Proxy.isProxyClass(targetClass)) {
|
||||
classes.add(ClassUtils.getUserClass(targetClass));
|
||||
}
|
||||
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
|
||||
|
||||
for (Class<?> clazz : classes) {
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
|
||||
for (Method method : methods) {
|
||||
if ((introductionAwareMethodMatcher != null &&
|
||||
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
|
||||
if (introductionAwareMethodMatcher != null ?
|
||||
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
|
||||
methodMatcher.matches(method, targetClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
|
||||
private final Set<Class<?>> interfaces = new LinkedHashSet<>();
|
||||
|
||||
private int order = Integer.MAX_VALUE;
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
||||
/**
|
||||
@@ -105,7 +105,7 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
|
||||
@Override
|
||||
public Class<?>[] getInterfaces() {
|
||||
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
|
||||
return ClassUtils.toClassArray(this.interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,7 +119,6 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
@@ -129,7 +128,6 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,15 +53,15 @@ public class IntroductionInfoSupport implements IntroductionInfo, Serializable {
|
||||
* due to the delegate implementing it. Call this method to exclude
|
||||
* internal interfaces from being visible at the proxy level.
|
||||
* <p>Does nothing if the interface is not implemented by the delegate.
|
||||
* @param intf the interface to suppress
|
||||
* @param ifc the interface to suppress
|
||||
*/
|
||||
public void suppressInterface(Class<?> intf) {
|
||||
this.publishedInterfaces.remove(intf);
|
||||
public void suppressInterface(Class<?> ifc) {
|
||||
this.publishedInterfaces.remove(ifc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getInterfaces() {
|
||||
return this.publishedInterfaces.toArray(new Class<?>[this.publishedInterfaces.size()]);
|
||||
return ClassUtils.toClassArray(this.publishedInterfaces);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,8 +90,8 @@ public abstract class MethodMatchers {
|
||||
*/
|
||||
public static boolean matches(MethodMatcher mm, Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
|
||||
Assert.notNull(mm, "MethodMatcher must not be null");
|
||||
return ((mm instanceof IntroductionAwareMethodMatcher &&
|
||||
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions)) ||
|
||||
return (mm instanceof IntroductionAwareMethodMatcher ?
|
||||
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions) :
|
||||
mm.matches(method, targetClass));
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public abstract class Pointcuts {
|
||||
@SuppressWarnings("serial")
|
||||
private static class SetterPointcut extends StaticMethodMatcherPointcut implements Serializable {
|
||||
|
||||
public static SetterPointcut INSTANCE = new SetterPointcut();
|
||||
public static final SetterPointcut INSTANCE = new SetterPointcut();
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass) {
|
||||
@@ -116,7 +116,7 @@ public abstract class Pointcuts {
|
||||
@SuppressWarnings("serial")
|
||||
private static class GetterPointcut extends StaticMethodMatcherPointcut implements Serializable {
|
||||
|
||||
public static GetterPointcut INSTANCE = new GetterPointcut();
|
||||
public static final GetterPointcut INSTANCE = new GetterPointcut();
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,10 +36,10 @@ import org.springframework.util.Assert;
|
||||
public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut
|
||||
implements PointcutAdvisor, Ordered, Serializable {
|
||||
|
||||
private int order = Integer.MAX_VALUE;
|
||||
|
||||
private Advice advice = EMPTY_ADVICE;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new StaticMethodMatcherPointcutAdvisor,
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.support.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
@@ -71,6 +72,10 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
|
||||
if (matchesMethod(method)) {
|
||||
return true;
|
||||
}
|
||||
// Proxy classes never have annotations on their redeclared methods.
|
||||
if (targetClass != null && Proxy.isProxyClass(targetClass)) {
|
||||
return false;
|
||||
}
|
||||
// The method may be on an interface, so let's check on the target class as well.
|
||||
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
return (specificMethod != method && matchesMethod(specificMethod));
|
||||
|
||||
+23
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,7 +60,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
|
||||
private String targetBeanName;
|
||||
|
||||
/** Class of the target */
|
||||
private Class<?> targetClass;
|
||||
private volatile Class<?> targetClass;
|
||||
|
||||
/**
|
||||
* BeanFactory that owns this TargetSource. We need to hold onto this
|
||||
@@ -120,19 +120,28 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized Class<?> getTargetClass() {
|
||||
if (this.targetClass == null && this.beanFactory != null) {
|
||||
// Determine type of the target bean.
|
||||
this.targetClass = this.beanFactory.getType(this.targetBeanName);
|
||||
if (this.targetClass == null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting bean with name '" + this.targetBeanName + "' in order to determine type");
|
||||
}
|
||||
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
|
||||
this.targetClass = beanInstance.getClass();
|
||||
}
|
||||
public Class<?> getTargetClass() {
|
||||
Class<?> targetClass = this.targetClass;
|
||||
if (targetClass != null) {
|
||||
return targetClass;
|
||||
}
|
||||
synchronized (this) {
|
||||
// Full check within synchronization, entering the BeanFactory interaction algorithm only once...
|
||||
targetClass = this.targetClass;
|
||||
if (targetClass == null && this.beanFactory != null) {
|
||||
// Determine type of the target bean.
|
||||
targetClass = this.beanFactory.getType(this.targetBeanName);
|
||||
if (targetClass == null) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting bean with name '" + this.targetBeanName + "' for type determination");
|
||||
}
|
||||
Object beanInstance = this.beanFactory.getBean(this.targetBeanName);
|
||||
targetClass = beanInstance.getClass();
|
||||
}
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
return targetClass;
|
||||
}
|
||||
return this.targetClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -30,13 +27,7 @@ import org.junit.Test;
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverAnnotationTests
|
||||
extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface MyAnnotation {}
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
public class AspectJAdviceParameterNameDiscoverAnnotationTests extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testAnnotationBinding() {
|
||||
@@ -45,4 +36,9 @@ public class AspectJAdviceParameterNameDiscoverAnnotationTests
|
||||
new String[] {"thisJoinPoint","ann"});
|
||||
}
|
||||
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
|
||||
+58
-52
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -34,47 +35,6 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
// methods to discover parameter names for
|
||||
public void noArgs() {
|
||||
}
|
||||
|
||||
public void tjp(JoinPoint jp) {
|
||||
}
|
||||
|
||||
public void tjpsp(JoinPoint.StaticPart tjpsp) {
|
||||
}
|
||||
|
||||
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
|
||||
}
|
||||
|
||||
public void oneThrowable(Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
|
||||
}
|
||||
|
||||
public void oneObject(Object x) {
|
||||
}
|
||||
|
||||
public void twoObjects(Object x, Object y) {
|
||||
}
|
||||
|
||||
public void onePrimitive(int x) {
|
||||
}
|
||||
|
||||
public void oneObjectOnePrimitive(Object x, int y) {
|
||||
}
|
||||
|
||||
public void oneThrowableOnePrimitive(Throwable x, int y) {
|
||||
}
|
||||
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoArgs() {
|
||||
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
|
||||
@@ -221,22 +181,26 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testThisAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", new String[] {"obj", "count"});
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", new String[] {"obj", "count"});
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowingAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", new String[] {"ex", "count"});
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
|
||||
new String[] {"ex", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllTogetherNow() {
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
|
||||
new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -253,8 +217,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
|
||||
protected Method getMethod(String name) {
|
||||
// assumes no overloading of test methods...
|
||||
Method[] candidates = this.getClass().getMethods();
|
||||
// Assumes no overloading of test methods...
|
||||
Method[] candidates = getClass().getMethods();
|
||||
for (Method candidate : candidates) {
|
||||
if (candidate.getName().equals(name)) {
|
||||
return candidate;
|
||||
@@ -268,8 +232,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
assertParameterNames(method, pointcut, null, null, parameterNames);
|
||||
}
|
||||
|
||||
protected void assertParameterNames(Method method, String pointcut, String returning, String throwing,
|
||||
String[] parameterNames) {
|
||||
protected void assertParameterNames(
|
||||
Method method, String pointcut, String returning, String throwing, String[] parameterNames) {
|
||||
|
||||
assertEquals("bad test specification, must have same number of parameter names as method arguments",
|
||||
method.getParameterCount(), parameterNames.length);
|
||||
@@ -300,8 +264,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
assertException(method, pointcut, null, null, exceptionType, message);
|
||||
}
|
||||
|
||||
protected void assertException(Method method, String pointcut, String returning, String throwing,
|
||||
Class<?> exceptionType, String message) {
|
||||
protected void assertException(
|
||||
Method method, String pointcut, String returning, String throwing, Class<?> exceptionType, String message) {
|
||||
|
||||
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
|
||||
discoverer.setRaiseExceptions(true);
|
||||
@@ -333,4 +297,46 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
// Methods to discover parameter names for
|
||||
|
||||
public void noArgs() {
|
||||
}
|
||||
|
||||
public void tjp(JoinPoint jp) {
|
||||
}
|
||||
|
||||
public void tjpsp(JoinPoint.StaticPart tjpsp) {
|
||||
}
|
||||
|
||||
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
|
||||
}
|
||||
|
||||
public void oneThrowable(Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
|
||||
}
|
||||
|
||||
public void oneObject(Object x) {
|
||||
}
|
||||
|
||||
public void twoObjects(Object x, Object y) {
|
||||
}
|
||||
|
||||
public void onePrimitive(int x) {
|
||||
}
|
||||
|
||||
public void oneObjectOnePrimitive(Object x, int y) {
|
||||
}
|
||||
|
||||
public void oneThrowableOnePrimitive(Throwable x, int y) {
|
||||
}
|
||||
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -218,38 +218,27 @@ public class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testSimpleAdvice() {
|
||||
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.getAge();
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setAge(90);
|
||||
|
||||
assertEquals("Calls should still be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicMatchingProxy() {
|
||||
String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Double(30));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Integer(90));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@@ -291,7 +280,7 @@ public class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUnsupportedPointcutPrimitive() throws Exception {
|
||||
public void testWithUnsupportedPointcutPrimitive() {
|
||||
String expression = "call(int org.springframework.tests.sample.beans.TestBean.getAge())";
|
||||
|
||||
try {
|
||||
@@ -301,7 +290,6 @@ public class AspectJExpressionPointcutTests {
|
||||
catch (UnsupportedPointcutPrimitiveException ex) {
|
||||
assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -332,6 +320,7 @@ public class AspectJExpressionPointcutTests {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,7 @@ public class BeanNamePointcutMatchingTests {
|
||||
assertMisMatch("someName", "!bean(someName) || bean(someOtherName)");
|
||||
}
|
||||
|
||||
|
||||
private void assertMatch(String beanName, String pcExpression) {
|
||||
assertTrue("Unexpected mismatch for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
|
||||
matches(beanName, pcExpression));
|
||||
@@ -98,4 +99,5 @@ public class BeanNamePointcutMatchingTests {
|
||||
pointcut.setExpression(pcExpression);
|
||||
return pointcut.matches(TestBean.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+65
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,30 +26,30 @@ import org.junit.Test;
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Java5-specific {@link AspectJExpressionPointcutTests}.
|
||||
* Java 5 specific {@link AspectJExpressionPointcutTests}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
// TODO factor into static in AspectJExpressionPointcut
|
||||
private Method getAge;
|
||||
|
||||
private Map<String,Method> methodsOnHasGeneric = new HashMap<>();
|
||||
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
public void setup() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
// Assumes no overloading
|
||||
for (Method m : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(m.getName(), m);
|
||||
for (Method method : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchVarargs() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchVarargs() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class MyTemplate {
|
||||
@@ -87,11 +87,6 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
|
||||
jdbcVarArgs.setExpression(expression);
|
||||
|
||||
// TODO: the expression above no longer matches Object[]
|
||||
// assertFalse(jdbcVarArgs.matches(
|
||||
// JdbcTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
// JdbcTemplate.class));
|
||||
|
||||
assertTrue(jdbcVarArgs.matches(
|
||||
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
MyTemplate.class));
|
||||
@@ -105,19 +100,19 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class));
|
||||
@@ -129,12 +124,12 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws SecurityException, NoSuchMethodException {
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws Exception {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
@@ -147,7 +142,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodWithFQN() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -161,28 +156,56 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(true);
|
||||
BeanA proxy = (BeanA) factory.getProxy();
|
||||
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(false);
|
||||
IBeanA proxy = (IBeanA) factory.getProxy();
|
||||
assertTrue(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
|
||||
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
@@ -203,14 +226,16 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
@@ -260,12 +285,21 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class BeanA {
|
||||
interface IBeanA {
|
||||
|
||||
@Tx
|
||||
int getAge();
|
||||
}
|
||||
|
||||
|
||||
static class BeanA implements IBeanA {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
@@ -275,6 +309,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Tx
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
@@ -283,6 +318,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
@Tx
|
||||
static class BeanB {
|
||||
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
|
||||
+77
-96
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,6 @@ import test.aop.PerTargetAspect;
|
||||
import test.aop.TwoAdviceAspect;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
@@ -82,22 +81,24 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testRejectsPerCflowAspect() {
|
||||
try {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(),"someBean"));
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean"));
|
||||
fail("Cannot accept cflow");
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("PERCFLOW") != -1);
|
||||
assertTrue(ex.getMessage().contains("PERCFLOW"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRejectsPerCflowBelowAspect() {
|
||||
try {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(),"someBean"));
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean"));
|
||||
fail("Cannot accept cflowbelow");
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("PERCFLOWBELOW") != -1);
|
||||
assertTrue(ex.getMessage().contains("PERCFLOWBELOW"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +113,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertEquals("Around advice must NOT apply", realAge, itb.getAge());
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[3];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -199,7 +201,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
Advised advised = (Advised) itb;
|
||||
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
|
||||
assertEquals(4, advised.getAdvisors().length);
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -227,16 +230,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
PerTypeWithinAspectInstanceFactory aif = new PerTypeWithinAspectInstanceFactory();
|
||||
TestBean itb = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aif),
|
||||
TestBean.class);
|
||||
TestBean itb = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
assertEquals("No method calls", 0, aif.getInstantiationCount());
|
||||
assertEquals("Around advice must now apply", 0, itb.getAge());
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
|
||||
assertEquals(4, advised.getAdvisors().length);
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -257,9 +259,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertEquals("Around advice must still apply", 1, itb.getAge());
|
||||
assertEquals("Around advice must still apply", 2, itb.getAge());
|
||||
|
||||
TestBean itb2 = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aif),
|
||||
TestBean.class);
|
||||
TestBean itb2 = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
assertEquals(1, aif.getInstantiationCount());
|
||||
assertEquals("Around advice be independent for second instance", 0, itb2.getAge());
|
||||
assertEquals(2, aif.getInstantiationCount());
|
||||
@@ -284,7 +284,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testNamedPointcutFromAspectLibraryWithBinding() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new NamedPointcutAspectFromLibraryWithBinding(),"someBean")),
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NamedPointcutAspectFromLibraryWithBinding(), "someBean")),
|
||||
ITestBean.class);
|
||||
itb.setAge(10);
|
||||
assertEquals("Around advice must apply", 20, itb.getAge());
|
||||
@@ -296,7 +297,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance,"someBean")),
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, "someBean")),
|
||||
ITestBean.class);
|
||||
assertEquals("Around advice must apply", -1, itb.getAge());
|
||||
assertEquals(realAge, target.getAge());
|
||||
@@ -306,7 +307,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testBindingWithSingleArg() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(),"someBean")),
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(), "someBean")),
|
||||
ITestBean.class);
|
||||
itb.setAge(10);
|
||||
assertEquals("Around advice must apply", 20, itb.getAge());
|
||||
@@ -317,7 +319,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testBindingWithMultipleArgsDifferentlyOrdered() {
|
||||
ManyValuedArgs target = new ManyValuedArgs();
|
||||
ManyValuedArgs mva = (ManyValuedArgs) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(),"someBean")),
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(), "someBean")),
|
||||
ManyValuedArgs.class);
|
||||
|
||||
String a = "a";
|
||||
@@ -338,7 +341,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertFalse(notLockableTarget instanceof Lockable);
|
||||
NotLockable notLockable1 = (NotLockable) createProxy(notLockableTarget,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
assertTrue(notLockable1 instanceof Lockable);
|
||||
Lockable lockable = (Lockable) notLockable1;
|
||||
@@ -349,7 +352,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
NotLockable notLockable2Target = new NotLockable();
|
||||
NotLockable notLockable2 = (NotLockable) createProxy(notLockable2Target,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
assertTrue(notLockable2 instanceof Lockable);
|
||||
Lockable lockable2 = (Lockable) notLockable2;
|
||||
@@ -368,11 +371,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testIntroductionAdvisorExcludedFromTargetImplementingInterface() {
|
||||
assertTrue(AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new MakeLockable(),"someBean")),
|
||||
CannotBeUnlocked.class).isEmpty());
|
||||
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
CannotBeUnlocked.class).isEmpty());
|
||||
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -408,42 +411,34 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
List.class
|
||||
),
|
||||
CannotBeUnlocked.class);
|
||||
List.class);
|
||||
assertFalse("Type pattern must have excluded mixin", proxy instanceof Lockable);
|
||||
}
|
||||
|
||||
/* prereq AspectJ 1.6.7
|
||||
@Test
|
||||
public void testIntroductionBasedOnAnnotationMatch_Spr5307() {
|
||||
public void testIntroductionBasedOnAnnotationMatch_SPR5307() {
|
||||
AnnotatedTarget target = new AnnotatedTargetImpl();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(),"someBean"));
|
||||
Object proxy = createProxy(target,
|
||||
advisors,
|
||||
AnnotatedTarget.class);
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
|
||||
Object proxy = createProxy(target, advisors, AnnotatedTarget.class);
|
||||
System.out.println(advisors.get(1));
|
||||
assertTrue(proxy instanceof Lockable);
|
||||
Lockable lockable = (Lockable)proxy;
|
||||
lockable.locked();
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testIntroductionWithArgumentBinding() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(),"someBean"));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(), "someBean"));
|
||||
advisors.addAll(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
|
||||
Modifiable modifiable = (Modifiable) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
Modifiable modifiable = (Modifiable) createProxy(target, advisors, ITestBean.class);
|
||||
assertThat(modifiable, instanceOf(Modifiable.class));
|
||||
Lockable lockable = (Lockable) modifiable;
|
||||
assertFalse(lockable.locked());
|
||||
@@ -477,11 +472,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testAspectMethodThrowsExceptionLegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
UnsupportedOperationException expectedException = new UnsupportedOperationException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertEquals("One advice method was found", 1, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
|
||||
try {
|
||||
itb.getAge();
|
||||
fail();
|
||||
@@ -497,11 +492,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testAspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
RemoteException expectedException = new RemoteException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertEquals("One advice method was found", 1, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
|
||||
try {
|
||||
itb.getAge();
|
||||
fail();
|
||||
@@ -522,10 +517,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
// Required everywhere we use AspectJ proxies
|
||||
pf.addAdvice(ExposeInvocationInterceptor.INSTANCE);
|
||||
|
||||
for (Object a : advisors) {
|
||||
pf.addAdvisor((Advisor) a);
|
||||
}
|
||||
pf.addAdvisors(advisors);
|
||||
|
||||
pf.setExposeProxy(true);
|
||||
return pf.getProxy();
|
||||
@@ -534,13 +526,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testTwoAdvicesOnOneAspect() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
TwoAdviceAspect twoAdviceAspect = new TwoAdviceAspect();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect,"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect, "someBean"));
|
||||
assertEquals("Two advice methods found", 2, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
itb.setName("");
|
||||
assertEquals(0, itb.getAge());
|
||||
int newAge = 32;
|
||||
@@ -551,16 +541,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testAfterAdviceTypes() throws Exception {
|
||||
Echo target = new Echo();
|
||||
|
||||
ExceptionHandling afterReturningAspect = new ExceptionHandling();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect,"someBean"));
|
||||
Echo echo = (Echo) createProxy(target,
|
||||
advisors,
|
||||
Echo.class);
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect, "someBean"));
|
||||
Echo echo = (Echo) createProxy(target, advisors, Echo.class);
|
||||
assertEquals(0, afterReturningAspect.successCount);
|
||||
assertEquals("", echo.echo(""));
|
||||
assertEquals(1, afterReturningAspect.successCount);
|
||||
assertEquals(0, afterReturningAspect.failureCount);
|
||||
|
||||
try {
|
||||
echo.echo(new FileNotFoundException());
|
||||
fail();
|
||||
@@ -580,9 +569,9 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testFailureWithoutExplicitDeclarePrecedence() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
itb.getAge();
|
||||
}
|
||||
|
||||
@@ -590,21 +579,10 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testDeclarePrecedenceNotSupported() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new DeclarePrecedenceShouldSucceed(), "someBean");
|
||||
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory),
|
||||
ITestBean.class);
|
||||
new DeclarePrecedenceShouldSucceed(), "someBean");
|
||||
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
}
|
||||
|
||||
/** Not supported in 2.0!
|
||||
public void testExplicitDeclarePrecedencePreventsFailure() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new DeclarePrecedenceShouldSucceed(), "someBean")),
|
||||
ITestBean.class);
|
||||
assertEquals(666, itb.getAge());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@Aspect("percflow(execution(* *(..)))")
|
||||
public static class PerCflowAspect {
|
||||
@@ -723,6 +701,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class NamedPointcutAspectWithoutFQN {
|
||||
|
||||
@Pointcut("execution(* getAge())")
|
||||
public void getAge() {
|
||||
}
|
||||
@@ -779,7 +758,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around(value="setAge(age)",argNames="age")
|
||||
// @ArgNames({"age"}) // AMC needs more work here? ignoring pjp arg... ok??
|
||||
// argNames should be suported in Around as it is in Pointcut
|
||||
// argNames should be suported in Around as it is in Pointcut
|
||||
public void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
|
||||
pjp.proceed(new Object[] {age*2});
|
||||
}
|
||||
@@ -788,12 +767,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ManyValuedArgs {
|
||||
|
||||
public String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)",
|
||||
argNames="b,c,d,e,a")
|
||||
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)", argNames="b,c,d,e,a")
|
||||
public String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuffer e, String a) throws Throwable {
|
||||
assertEquals(a + b+ c+ d+ e, pjp.proceed());
|
||||
return a + b + c + d + e;
|
||||
@@ -803,6 +782,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ExceptionAspect {
|
||||
|
||||
private final Exception ex;
|
||||
|
||||
public ExceptionAspect(Exception ex) {
|
||||
@@ -829,8 +809,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ExceptionHandling {
|
||||
|
||||
public int successCount;
|
||||
|
||||
public int failureCount;
|
||||
|
||||
public int afterCount;
|
||||
|
||||
@AfterReturning("execution(* echo(*))")
|
||||
@@ -902,10 +885,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
abstract class AbstractMakeModifiable {
|
||||
|
||||
public interface MutableModifable extends Modifiable {
|
||||
|
||||
void markDirty();
|
||||
}
|
||||
|
||||
public static class ModifiableImpl implements MutableModifable {
|
||||
|
||||
private boolean modified;
|
||||
|
||||
@Override
|
||||
@@ -924,10 +909,9 @@ abstract class AbstractMakeModifiable {
|
||||
}
|
||||
}
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)",
|
||||
argNames="modifiable,newValue")
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(JoinPoint jp,
|
||||
MutableModifable mixin, Object newValue) {
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)", argNames="modifiable,newValue")
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(
|
||||
JoinPoint jp, MutableModifable mixin, Object newValue) {
|
||||
|
||||
/*
|
||||
* We use the mixin to check and, if necessary, change,
|
||||
@@ -992,6 +976,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a declare parents pointcut - spr5307
|
||||
* @author Andy Clement
|
||||
@@ -1001,8 +986,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
|
||||
@DeclareParents(value = "(@org.springframework.aop.aspectj.annotation.Measured *)",
|
||||
// @DeclareParents(value = "(@Measured *)", // this would be a nice alternative...
|
||||
defaultImpl=DefaultLockable.class)
|
||||
defaultImpl = DefaultLockable.class)
|
||||
public static Lockable mixin;
|
||||
|
||||
}
|
||||
@@ -1014,14 +998,11 @@ class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
@Aspect
|
||||
class MakeLockable {
|
||||
|
||||
@DeclareParents(value = "org.springframework..*",
|
||||
defaultImpl=DefaultLockable.class)
|
||||
@DeclareParents(value = "org.springframework..*", defaultImpl = DefaultLockable.class)
|
||||
public static Lockable mixin;
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(mixin)", argNames="mixin")
|
||||
public void checkNotLocked(
|
||||
Lockable mixin) // Bind to arg
|
||||
{
|
||||
public void checkNotLocked( Lockable mixin) {
|
||||
// Can also obtain the mixin (this) this way
|
||||
//Lockable mixin = (Lockable) jp.getThis();
|
||||
if (mixin.locked()) {
|
||||
@@ -1069,6 +1050,7 @@ interface Modifiable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used as a target.
|
||||
* @author Andy Clement
|
||||
@@ -1076,11 +1058,12 @@ interface Modifiable {
|
||||
interface AnnotatedTarget {
|
||||
}
|
||||
|
||||
|
||||
@Measured
|
||||
class AnnotatedTargetImpl implements AnnotatedTarget {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Measured {}
|
||||
|
||||
@@ -1104,9 +1087,7 @@ class PerThisAspect {
|
||||
|
||||
public int count;
|
||||
|
||||
/**
|
||||
* Just to check that this doesn't cause problems with introduction processing
|
||||
*/
|
||||
// Just to check that this doesn't cause problems with introduction processing
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
|
||||
+11
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,20 +51,20 @@ public class AopNamespaceHandlerEventTests {
|
||||
|
||||
private CollectingReaderEventListener eventListener = new CollectingReaderEventListener();
|
||||
|
||||
private XmlBeanDefinitionReader reader;
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
private XmlBeanDefinitionReader reader;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setup() {
|
||||
this.reader = new XmlBeanDefinitionReader(this.beanFactory);
|
||||
this.reader.setEventListener(this.eventListener);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPointcutEvents() throws Exception {
|
||||
public void testPointcutEvents() {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 1, componentDefinitions.length);
|
||||
@@ -76,8 +76,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
|
||||
PointcutComponentDefinition pcd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof PointcutComponentDefinition) {
|
||||
pcd = (PointcutComponentDefinition) componentDefinition;
|
||||
break;
|
||||
@@ -88,7 +87,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithPointcutRef() throws Exception {
|
||||
public void testAdvisorEventsWithPointcutRef() {
|
||||
this.reader.loadBeanDefinitions(POINTCUT_REF_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
|
||||
@@ -117,7 +116,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvisorEventsWithDirectPointcut() throws Exception {
|
||||
public void testAdvisorEventsWithDirectPointcut() {
|
||||
this.reader.loadBeanDefinitions(DIRECT_POINTCUT_EVENTS_CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 2, componentDefinitions.length);
|
||||
@@ -146,7 +145,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAspectEvent() throws Exception {
|
||||
public void testAspectEvent() {
|
||||
this.reader.loadBeanDefinitions(CONTEXT);
|
||||
ComponentDefinition[] componentDefinitions = this.eventListener.getComponentDefinitions();
|
||||
assertEquals("Incorrect number of events fired", 5, componentDefinitions.length);
|
||||
@@ -158,8 +157,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
ComponentDefinition[] nestedComponentDefs = compositeDef.getNestedComponents();
|
||||
assertEquals("Incorrect number of inner components", 2, nestedComponentDefs.length);
|
||||
AspectComponentDefinition acd = null;
|
||||
for (int i = 0; i < nestedComponentDefs.length; i++) {
|
||||
ComponentDefinition componentDefinition = nestedComponentDefs[i];
|
||||
for (ComponentDefinition componentDefinition : nestedComponentDefs) {
|
||||
if (componentDefinition instanceof AspectComponentDefinition) {
|
||||
acd = (AspectComponentDefinition) componentDefinition;
|
||||
break;
|
||||
@@ -175,8 +173,7 @@ public class AopNamespaceHandlerEventTests {
|
||||
Set<String> expectedReferences = new HashSet<>();
|
||||
expectedReferences.add("pc");
|
||||
expectedReferences.add("countingAdvice");
|
||||
for (int i = 0; i < beanReferences.length; i++) {
|
||||
BeanReference beanReference = beanReferences[i];
|
||||
for (BeanReference beanReference : beanReferences) {
|
||||
expectedReferences.remove(beanReference.getBeanName());
|
||||
}
|
||||
assertEquals("Incorrect references found", 0, expectedReferences.size());
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,7 +47,7 @@ public class ConcurrencyThrottleInterceptorTests {
|
||||
public void testSerializable() throws Exception {
|
||||
DerivedTestBean tb = new DerivedTestBean();
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
proxyFactory.setInterfaces(ITestBean.class);
|
||||
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
|
||||
proxyFactory.addAdvice(cti);
|
||||
proxyFactory.setTarget(tb);
|
||||
@@ -75,7 +75,7 @@ public class ConcurrencyThrottleInterceptorTests {
|
||||
private void testMultipleThreads(int concurrencyLimit) {
|
||||
TestBean tb = new TestBean();
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.setInterfaces(new Class[] {ITestBean.class});
|
||||
proxyFactory.setInterfaces(ITestBean.class);
|
||||
ConcurrencyThrottleInterceptor cti = new ConcurrencyThrottleInterceptor();
|
||||
cti.setConcurrencyLimit(concurrencyLimit);
|
||||
proxyFactory.addAdvice(cti);
|
||||
@@ -95,7 +95,7 @@ public class ConcurrencyThrottleInterceptorTests {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
threads[i] = new ConcurrencyThread(proxy,
|
||||
i % 2 == 0 ? (Throwable) new OutOfMemoryError() : (Throwable) new IllegalStateException());
|
||||
i % 2 == 0 ? new OutOfMemoryError() : new IllegalStateException());
|
||||
threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < NR_OF_THREADS; i++) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,7 +83,7 @@ public class CustomizableTraceInterceptorTests {
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(methodInvocation.getThis()).willReturn(this);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
@@ -101,7 +101,7 @@ public class CustomizableTraceInterceptorTests {
|
||||
MethodInvocation methodInvocation = mock(MethodInvocation.class);
|
||||
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
|
||||
given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(methodInvocation.getThis()).willReturn(this);
|
||||
given(methodInvocation.proceed()).willThrow(exception);
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ public class SimpleTraceInterceptorTests {
|
||||
@Test
|
||||
public void testSunnyDayPathLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
|
||||
Log log = mock(Log.class);
|
||||
@@ -48,7 +48,7 @@ public class SimpleTraceInterceptorTests {
|
||||
@Test
|
||||
public void testExceptionPathStillLogsCorrectly() throws Throwable {
|
||||
MethodInvocation mi = mock(MethodInvocation.class);
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString", new Class[]{}));
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.getThis()).willReturn(this);
|
||||
IllegalArgumentException exception = new IllegalArgumentException();
|
||||
given(mi.proceed()).willThrow(exception);
|
||||
|
||||
+5
-5
@@ -70,13 +70,13 @@ public class HotSwappableTargetSourceTests {
|
||||
@Test
|
||||
public void testBasicFunctionality() {
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(INITIAL_COUNT, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT, proxied.getCount());
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
|
||||
|
||||
proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 2, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 2, proxied.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,9 +85,9 @@ public class HotSwappableTargetSourceTests {
|
||||
SideEffectBean target2 = (SideEffectBean) beanFactory.getBean("target2");
|
||||
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(target1.getCount(), proxied.getCount() );
|
||||
assertEquals(target1.getCount(), proxied.getCount());
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
|
||||
|
||||
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
|
||||
Object old = swapper.swap(target2);
|
||||
|
||||
+4
-4
@@ -56,14 +56,14 @@ public class PrototypeTargetSourceTests {
|
||||
@Test
|
||||
public void testPrototypeAndSingletonBehaveDifferently() {
|
||||
SideEffectBean singleton = (SideEffectBean) beanFactory.getBean("singleton");
|
||||
assertEquals(INITIAL_COUNT, singleton.getCount() );
|
||||
assertEquals(INITIAL_COUNT, singleton.getCount());
|
||||
singleton.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, singleton.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, singleton.getCount());
|
||||
|
||||
SideEffectBean prototype = (SideEffectBean) beanFactory.getBean("prototype");
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount());
|
||||
prototype.doWork();
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-11
@@ -62,9 +62,9 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testUseDifferentManagedInstancesInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
|
||||
ITestBean test = (ITestBean) beanFactory.getBean("threadLocal2");
|
||||
assertEquals("Rod", test.getName());
|
||||
@@ -74,12 +74,12 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testReuseInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
|
||||
apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,20 +106,20 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testNewThreadHasOwnInstance() throws InterruptedException {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
|
||||
|
||||
class Runner implements Runnable {
|
||||
public SideEffectBean mine;
|
||||
@Override
|
||||
public void run() {
|
||||
this.mine = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT, mine.getCount());
|
||||
mine.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, mine.getCount());
|
||||
}
|
||||
}
|
||||
Runner r = new Runner();
|
||||
@@ -130,11 +130,11 @@ public class ThreadLocalTargetSourceTests {
|
||||
assertNotNull(r);
|
||||
|
||||
// Check it didn't affect the other thread's copy
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
|
||||
|
||||
// When we use other thread's copy in this thread
|
||||
// it should behave like ours
|
||||
assertEquals(INITIAL_COUNT + 3, r.mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, r.mine.getCount());
|
||||
|
||||
// Bound to two threads
|
||||
assertEquals(2, ((ThreadLocalTargetSourceStats) apartment).getObjectCount());
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
description = "Spring Aspects"
|
||||
|
||||
// redefine the compileJava and compileTestJava tasks in order to
|
||||
// compile sources with ajc instead of javac
|
||||
// Redefine the compileJava and compileTestJava tasks in order to compile sources with ajc instead of javac
|
||||
|
||||
configurations {
|
||||
rt
|
||||
@@ -10,21 +9,16 @@ configurations {
|
||||
ajInpath
|
||||
}
|
||||
|
||||
// exclude spring-aspects as a module within IDEA until IDEA-64446 is resolved
|
||||
tasks.getByName("idea").onlyIf { false }
|
||||
tasks.getByName("ideaModule").onlyIf { false }
|
||||
|
||||
compileJava {
|
||||
compileJava {
|
||||
actions = []
|
||||
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileJava")
|
||||
|
||||
def outputDir = project.sourceSets.main.java.outputDir
|
||||
|
||||
inputs.files(project.sourceSets.main.allSource + project.sourceSets.main.compileClasspath)
|
||||
outputs.dir outputDir
|
||||
|
||||
ext.sourceCompatibility = project(":spring-core").compileJava.sourceCompatibility
|
||||
ext.targetCompatibility = project(":spring-core").compileJava.targetCompatibility
|
||||
sourceCompatibility = 1.8 // fixed even when general compatibility level set to e.g. 10
|
||||
targetCompatibility = 1.8
|
||||
|
||||
doLast{
|
||||
// Assemble runtime classpath from folders and JARs that actually exist
|
||||
@@ -49,18 +43,17 @@ compileJava {
|
||||
}
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
compileTestJava {
|
||||
actions = []
|
||||
dependsOn configurations.ajc.getTaskDependencyFromProjectDependency(true, "compileTestJava")
|
||||
dependsOn jar
|
||||
|
||||
def outputDir = project.sourceSets.test.java.outputDir
|
||||
|
||||
inputs.files(project.sourceSets.test.allSource + project.sourceSets.test.compileClasspath)
|
||||
outputs.dir outputDir
|
||||
|
||||
ext.sourceCompatibility = project(":spring-core").compileTestJava.sourceCompatibility
|
||||
ext.targetCompatibility = project(":spring-core").compileTestJava.targetCompatibility
|
||||
sourceCompatibility = 1.8 // fixed even when general compatibility level set to e.g. 10
|
||||
targetCompatibility = 1.8
|
||||
|
||||
doLast{
|
||||
// Assemble runtime classpath from folders and JARs that actually exist
|
||||
@@ -87,8 +80,8 @@ compileTestJava {
|
||||
|
||||
dependencies {
|
||||
aspects(project(":spring-orm"))
|
||||
ajc("org.aspectj:aspectjtools:1.9.0.RC2") // for JDK 9 build compatibility
|
||||
rt("org.aspectj:aspectjrt:1.9.0.RC2") // for JDK 9 build compatibility
|
||||
ajc("org.aspectj:aspectjtools:1.9.1") // for JDK 9+ build compatibility
|
||||
rt("org.aspectj:aspectjrt:1.9.1") // for JDK 9+ build compatibility
|
||||
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // for Maven POM exposure
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
optional(project(":spring-beans")) // for @Configurable support
|
||||
@@ -96,11 +89,11 @@ dependencies {
|
||||
optional(project(":spring-context-support")) // for JavaMail and JSR-107 support
|
||||
optional(project(":spring-orm")) // for JPA exception translation support
|
||||
optional(project(":spring-tx")) // for JPA, @Transactional support
|
||||
optional("javax.cache:cache-api:1.0.0") // for JCache aspect
|
||||
optional("javax.cache:cache-api:1.1.0") // for JCache aspect
|
||||
optional("javax.transaction:javax.transaction-api:1.2") // for @javax.transaction.Transactional support
|
||||
testCompile(project(":spring-core")) // for CodeStyleAspect
|
||||
testCompile(project(":spring-test"))
|
||||
testCompile("javax.mail:javax.mail-api:1.6.0")
|
||||
testCompile("javax.mail:javax.mail-api:1.6.1")
|
||||
}
|
||||
|
||||
eclipse.project {
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see org.springframework.cache.annotation.CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.CACHE_ASPECT_BEAN_NAME)
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see org.springframework.cache.annotation.CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJJCacheConfiguration extends AbstractJCacheConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME)
|
||||
|
||||
@@ -5,7 +5,7 @@ apply plugin: "groovy"
|
||||
dependencies {
|
||||
compile(project(':spring-core'))
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("org.yaml:snakeyaml:1.19")
|
||||
optional("org.yaml:snakeyaml:1.20")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
|
||||
+5
-9
@@ -634,7 +634,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
"property path '" + propertyName + "': returned null");
|
||||
}
|
||||
}
|
||||
String indexedPropertyName = tokens.actualName;
|
||||
StringBuilder indexedPropertyName = new StringBuilder(tokens.actualName);
|
||||
// apply indexes and map keys
|
||||
for (int i = 0; i < tokens.keys.length; i++) {
|
||||
String key = tokens.keys[i];
|
||||
@@ -645,13 +645,13 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
}
|
||||
else if (value.getClass().isArray()) {
|
||||
int index = Integer.parseInt(key);
|
||||
value = growArrayIfNecessary(value, index, indexedPropertyName);
|
||||
value = growArrayIfNecessary(value, index, indexedPropertyName.toString());
|
||||
value = Array.get(value, index);
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
int index = Integer.parseInt(key);
|
||||
List<Object> list = (List<Object>) value;
|
||||
growCollectionIfNecessary(list, index, indexedPropertyName, ph, i + 1);
|
||||
growCollectionIfNecessary(list, index, indexedPropertyName.toString(), ph, i + 1);
|
||||
value = list.get(index);
|
||||
}
|
||||
else if (value instanceof Set) {
|
||||
@@ -686,7 +686,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
"Property referenced in indexed property path '" + propertyName +
|
||||
"' is neither an array nor a List nor a Set nor a Map; returned value was [" + value + "]");
|
||||
}
|
||||
indexedPropertyName += PROPERTY_KEY_PREFIX + key + PROPERTY_KEY_SUFFIX;
|
||||
indexedPropertyName.append(PROPERTY_KEY_PREFIX).append(key).append(PROPERTY_KEY_SUFFIX);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
@@ -695,11 +695,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Index of out of bounds in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Invalid index in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
catch (NumberFormatException | TypeMismatchException ex) {
|
||||
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
|
||||
"Invalid index in property path '" + propertyName + "'", ex);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -118,8 +118,7 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
|
||||
|
||||
// If we encountered individual exceptions, throw the composite exception.
|
||||
if (propertyAccessExceptions != null) {
|
||||
PropertyAccessException[] paeArray =
|
||||
propertyAccessExceptions.toArray(new PropertyAccessException[propertyAccessExceptions.size()]);
|
||||
PropertyAccessException[] paeArray = propertyAccessExceptions.toArray(new PropertyAccessException[0]);
|
||||
throw new PropertyBatchUpdateException(paeArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,12 +98,19 @@ public abstract class BeanUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a class using its no-arg constructor.
|
||||
* Instantiate a class using its 'primary' constructor (for Kotlin classes,
|
||||
* potentially having default arguments declared) or its default constructor
|
||||
* (for regular Java classes, expecting a standard no-arg setup).
|
||||
* <p>Note that this method tries to set the constructor accessible
|
||||
* if given a non-accessible (that is, non-public) constructor.
|
||||
* @param clazz class to instantiate
|
||||
* @param clazz the class to instantiate
|
||||
* @return the new instance
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated
|
||||
* @throws BeanInstantiationException if the bean cannot be instantiated.
|
||||
* The cause may notably indicate a {@link NoSuchMethodException} if no
|
||||
* primary/default constructor was found, a {@link NoClassDefFoundError}
|
||||
* or other {@link LinkageError} in case of an unresolvable class definition
|
||||
* (e.g. due to a missing dependency at runtime), or an exception thrown
|
||||
* from the constructor invocation itself.
|
||||
* @see Constructor#newInstance
|
||||
*/
|
||||
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
|
||||
@@ -113,15 +120,15 @@ public abstract class BeanUtils {
|
||||
}
|
||||
try {
|
||||
Constructor<T> ctor = (KotlinDetector.isKotlinType(clazz) ?
|
||||
KotlinDelegate.findPrimaryConstructor(clazz) : clazz.getDeclaredConstructor());
|
||||
if (ctor == null) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found");
|
||||
}
|
||||
KotlinDelegate.getPrimaryConstructor(clazz) : clazz.getDeclaredConstructor());
|
||||
return instantiateClass(ctor);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
catch (LinkageError err) {
|
||||
throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -360,23 +367,23 @@ public abstract class BeanUtils {
|
||||
public static Method resolveSignature(String signature, Class<?> clazz) {
|
||||
Assert.hasText(signature, "'signature' must not be empty");
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
int firstParen = signature.indexOf("(");
|
||||
int lastParen = signature.indexOf(")");
|
||||
if (firstParen > -1 && lastParen == -1) {
|
||||
int startParen = signature.indexOf('(');
|
||||
int endParen = signature.indexOf(')');
|
||||
if (startParen > -1 && endParen == -1) {
|
||||
throw new IllegalArgumentException("Invalid method signature '" + signature +
|
||||
"': expected closing ')' for args list");
|
||||
}
|
||||
else if (lastParen > -1 && firstParen == -1) {
|
||||
else if (startParen == -1 && endParen > -1) {
|
||||
throw new IllegalArgumentException("Invalid method signature '" + signature +
|
||||
"': expected opening '(' for args list");
|
||||
}
|
||||
else if (firstParen == -1 && lastParen == -1) {
|
||||
else if (startParen == -1) {
|
||||
return findMethodWithMinimalParameters(clazz, signature);
|
||||
}
|
||||
else {
|
||||
String methodName = signature.substring(0, firstParen);
|
||||
String methodName = signature.substring(0, startParen);
|
||||
String[] parameterTypeNames =
|
||||
StringUtils.commaDelimitedListToStringArray(signature.substring(firstParen + 1, lastParen));
|
||||
StringUtils.commaDelimitedListToStringArray(signature.substring(startParen + 1, endParen));
|
||||
Class<?>[] parameterTypes = new Class<?>[parameterTypeNames.length];
|
||||
for (int i = 0; i < parameterTypeNames.length; i++) {
|
||||
String parameterTypeName = parameterTypeNames[i].trim();
|
||||
@@ -561,13 +568,14 @@ public abstract class BeanUtils {
|
||||
|
||||
/**
|
||||
* Check if the given type represents a "simple" value type:
|
||||
* a primitive, a String or other CharSequence, a Number, a Date,
|
||||
* a primitive, an enum, a String or other CharSequence, a Number, a Date,
|
||||
* a URI, a URL, a Locale or a Class.
|
||||
* @param clazz the type to check
|
||||
* @return whether the given type represents a "simple" value type
|
||||
*/
|
||||
public static boolean isSimpleValueType(Class<?> clazz) {
|
||||
return (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.isEnum() ||
|
||||
return (ClassUtils.isPrimitiveOrWrapper(clazz) ||
|
||||
Enum.class.isAssignableFrom(clazz) ||
|
||||
CharSequence.class.isAssignableFrom(clazz) ||
|
||||
Number.class.isAssignableFrom(clazz) ||
|
||||
Date.class.isAssignableFrom(clazz) ||
|
||||
@@ -692,10 +700,26 @@ public abstract class BeanUtils {
|
||||
private static class KotlinDelegate {
|
||||
|
||||
/**
|
||||
* Return the Java constructor corresponding to the Kotlin primary constructor if any.
|
||||
* Determine the Java constructor corresponding to the Kotlin primary constructor.
|
||||
* @param clazz the {@link Class} of the Kotlin class
|
||||
* @throws NoSuchMethodException if no such constructor found
|
||||
* @since 5.0.3
|
||||
* @see #findPrimaryConstructor
|
||||
* @see Class#getDeclaredConstructor
|
||||
*/
|
||||
public static <T> Constructor<T> getPrimaryConstructor(Class<T> clazz) throws NoSuchMethodException {
|
||||
Constructor<T> ctor = findPrimaryConstructor(clazz);
|
||||
if (ctor == null) {
|
||||
throw new NoSuchMethodException();
|
||||
}
|
||||
return ctor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Java constructor corresponding to the Kotlin primary constructor, if any.
|
||||
* @param clazz the {@link Class} of the Kotlin class
|
||||
* @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">
|
||||
* http://kotlinlang.org/docs/reference/classes.html#constructors</a>
|
||||
* http://kotlinlang.org/docs/reference/classes.html#constructors</a>
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> Constructor<T> findPrimaryConstructor(Class<T> clazz) {
|
||||
@@ -705,8 +729,10 @@ public abstract class BeanUtils {
|
||||
return null;
|
||||
}
|
||||
Constructor<T> constructor = ReflectJvmMapping.getJavaConstructor(primaryCtor);
|
||||
Assert.notNull(constructor,
|
||||
() -> "Failed to find Java constructor for Kotlin primary constructor: " + clazz.getName());
|
||||
if (constructor == null) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to find Java constructor for Kotlin primary constructor: " + clazz.getName());
|
||||
}
|
||||
return constructor;
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
@@ -717,7 +743,8 @@ public abstract class BeanUtils {
|
||||
/**
|
||||
* Instantiate a Kotlin class using the provided constructor.
|
||||
* @param ctor the constructor of the Kotlin class to instantiate
|
||||
* @param args the constructor arguments to apply (use null for unspecified parameter if needed)
|
||||
* @param args the constructor arguments to apply
|
||||
* (use {@code null} for unspecified parameter if needed)
|
||||
*/
|
||||
public static <T> T instantiateClass(Constructor<T> ctor, Object... args)
|
||||
throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -228,10 +228,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
@Nullable
|
||||
protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) {
|
||||
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
|
||||
if (pd != null) {
|
||||
return new BeanPropertyHandler(pd);
|
||||
}
|
||||
return null;
|
||||
return (pd != null ? new BeanPropertyHandler(pd) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -242,8 +239,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
@Override
|
||||
protected NotWritablePropertyException createNotWritablePropertyException(String propertyName) {
|
||||
PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());
|
||||
throw new NotWritablePropertyException(
|
||||
getRootClass(), getNestedPath() + propertyName,
|
||||
throw new NotWritablePropertyException(getRootClass(), getNestedPath() + propertyName,
|
||||
matches.buildErrorMessage(), matches.getPossibleMatches());
|
||||
}
|
||||
|
||||
|
||||
+37
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,6 @@ import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -150,24 +149,12 @@ public class CachedIntrospectionResults {
|
||||
* @param classLoader the ClassLoader to clear the cache for
|
||||
*/
|
||||
public static void clearClassLoader(@Nullable ClassLoader classLoader) {
|
||||
for (Iterator<ClassLoader> it = acceptedClassLoaders.iterator(); it.hasNext();) {
|
||||
ClassLoader registeredLoader = it.next();
|
||||
if (isUnderneathClassLoader(registeredLoader, classLoader)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<Class<?>> it = strongClassCache.keySet().iterator(); it.hasNext();) {
|
||||
Class<?> beanClass = it.next();
|
||||
if (isUnderneathClassLoader(beanClass.getClassLoader(), classLoader)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
for (Iterator<Class<?>> it = softClassCache.keySet().iterator(); it.hasNext();) {
|
||||
Class<?> beanClass = it.next();
|
||||
if (isUnderneathClassLoader(beanClass.getClassLoader(), classLoader)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
acceptedClassLoaders.removeIf(registeredLoader ->
|
||||
isUnderneathClassLoader(registeredLoader, classLoader));
|
||||
strongClassCache.keySet().removeIf(beanClass ->
|
||||
isUnderneathClassLoader(beanClass.getClassLoader(), classLoader));
|
||||
softClassCache.keySet().removeIf(beanClass ->
|
||||
isUnderneathClassLoader(beanClass.getClassLoader(), classLoader));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,6 +231,24 @@ public class CachedIntrospectionResults {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a {@link BeanInfo} descriptor for the given target class.
|
||||
* @param beanClass the target class to introspect
|
||||
* @return the resulting {@code BeanInfo} descriptor (never {@code null})
|
||||
* @throws IntrospectionException from the underlying {@link Introspector}
|
||||
*/
|
||||
private static BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
|
||||
for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {
|
||||
BeanInfo beanInfo = beanInfoFactory.getBeanInfo(beanClass);
|
||||
if (beanInfo != null) {
|
||||
return beanInfo;
|
||||
}
|
||||
}
|
||||
return (shouldIntrospectorIgnoreBeaninfoClasses ?
|
||||
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
|
||||
Introspector.getBeanInfo(beanClass));
|
||||
}
|
||||
|
||||
|
||||
/** The BeanInfo object for the introspected bean class */
|
||||
private final BeanInfo beanInfo;
|
||||
@@ -265,21 +270,7 @@ public class CachedIntrospectionResults {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Getting BeanInfo for class [" + beanClass.getName() + "]");
|
||||
}
|
||||
|
||||
BeanInfo beanInfo = null;
|
||||
for (BeanInfoFactory beanInfoFactory : beanInfoFactories) {
|
||||
beanInfo = beanInfoFactory.getBeanInfo(beanClass);
|
||||
if (beanInfo != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (beanInfo == null) {
|
||||
// If none of the factories supported the class, fall back to the default
|
||||
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
|
||||
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
|
||||
Introspector.getBeanInfo(beanClass));
|
||||
}
|
||||
this.beanInfo = beanInfo;
|
||||
this.beanInfo = getBeanInfo(beanClass);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
|
||||
@@ -307,15 +298,15 @@ public class CachedIntrospectionResults {
|
||||
// Explicitly check implemented interfaces for setter/getter methods as well,
|
||||
// in particular for Java 8 default methods...
|
||||
Class<?> clazz = beanClass;
|
||||
while (clazz != null) {
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
Class<?>[] ifcs = clazz.getInterfaces();
|
||||
for (Class<?> ifc : ifcs) {
|
||||
BeanInfo ifcInfo = Introspector.getBeanInfo(ifc, Introspector.IGNORE_ALL_BEANINFO);
|
||||
PropertyDescriptor[] ifcPds = ifcInfo.getPropertyDescriptors();
|
||||
for (PropertyDescriptor pd : ifcPds) {
|
||||
if (!this.propertyDescriptorCache.containsKey(pd.getName())) {
|
||||
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
|
||||
this.propertyDescriptorCache.put(pd.getName(), pd);
|
||||
if (!ClassUtils.isJavaLanguageInterface(ifc)) {
|
||||
for (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {
|
||||
if (!this.propertyDescriptorCache.containsKey(pd.getName())) {
|
||||
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
|
||||
this.propertyDescriptorCache.put(pd.getName(), pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,6 +320,7 @@ public class CachedIntrospectionResults {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BeanInfo getBeanInfo() {
|
||||
return this.beanInfo;
|
||||
}
|
||||
@@ -341,10 +333,10 @@ public class CachedIntrospectionResults {
|
||||
PropertyDescriptor getPropertyDescriptor(String name) {
|
||||
PropertyDescriptor pd = this.propertyDescriptorCache.get(name);
|
||||
if (pd == null && StringUtils.hasLength(name)) {
|
||||
// Same lenient fallback checking as in PropertyTypeDescriptor...
|
||||
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toLowerCase() + name.substring(1));
|
||||
// Same lenient fallback checking as in Property...
|
||||
pd = this.propertyDescriptorCache.get(StringUtils.uncapitalize(name));
|
||||
if (pd == null) {
|
||||
pd = this.propertyDescriptorCache.get(name.substring(0, 1).toUpperCase() + name.substring(1));
|
||||
pd = this.propertyDescriptorCache.get(StringUtils.capitalize(name));
|
||||
}
|
||||
}
|
||||
return (pd == null || pd instanceof GenericTypeAwarePropertyDescriptor ? pd :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,14 +71,15 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected FieldPropertyHandler getLocalPropertyHandler(String propertyName) {
|
||||
FieldPropertyHandler propertyHandler = this.fieldMap.get(propertyName);
|
||||
if (propertyHandler == null) {
|
||||
Field field = ReflectionUtils.findField(getWrappedClass(), propertyName);
|
||||
if (field != null) {
|
||||
propertyHandler = new FieldPropertyHandler(field);
|
||||
this.fieldMap.put(propertyName, propertyHandler);
|
||||
}
|
||||
this.fieldMap.put(propertyName, propertyHandler);
|
||||
}
|
||||
return propertyHandler;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -220,7 +220,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
*/
|
||||
@Override
|
||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||
return this.propertyDescriptors.toArray(new PropertyDescriptor[this.propertyDescriptors.size()]);
|
||||
return this.propertyDescriptors.toArray(new PropertyDescriptor[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,7 +43,7 @@ public interface Mergeable {
|
||||
* @param parent the object to merge with
|
||||
* @return the result of the merge operation
|
||||
* @throws IllegalArgumentException if the supplied parent is {@code null}
|
||||
* @exception IllegalStateException if merging is not enabled for this instance
|
||||
* @throws IllegalStateException if merging is not enabled for this instance
|
||||
* (i.e. {@code mergeEnabled} equals {@code false}).
|
||||
*/
|
||||
Object merge(@Nullable Object parent);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -246,7 +246,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
|
||||
@Override
|
||||
public PropertyValue[] getPropertyValues() {
|
||||
return this.propertyValueList.toArray(new PropertyValue[this.propertyValueList.size()]);
|
||||
return this.propertyValueList.toArray(new PropertyValue[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,11 +285,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
for (PropertyValue newPv : this.propertyValueList) {
|
||||
// if there wasn't an old one, add it
|
||||
PropertyValue pvOld = old.getPropertyValue(newPv.getName());
|
||||
if (pvOld == null) {
|
||||
changes.addPropertyValue(newPv);
|
||||
}
|
||||
else if (!pvOld.equals(newPv)) {
|
||||
// it's changed
|
||||
if (pvOld == null || !pvOld.equals(newPv)) {
|
||||
changes.addPropertyValue(newPv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class PropertyDescriptorUtils {
|
||||
}
|
||||
|
||||
if (writeMethod != null) {
|
||||
Class<?> params[] = writeMethod.getParameterTypes();
|
||||
Class<?>[] params = writeMethod.getParameterTypes();
|
||||
if (params.length != 1) {
|
||||
throw new IntrospectionException("Bad write method arg count: " + writeMethod);
|
||||
}
|
||||
@@ -114,7 +114,7 @@ class PropertyDescriptorUtils {
|
||||
Class<?> indexedPropertyType = null;
|
||||
|
||||
if (indexedReadMethod != null) {
|
||||
Class<?> params[] = indexedReadMethod.getParameterTypes();
|
||||
Class<?>[] params = indexedReadMethod.getParameterTypes();
|
||||
if (params.length != 1) {
|
||||
throw new IntrospectionException("Bad indexed read method arg count: " + indexedReadMethod);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ class PropertyDescriptorUtils {
|
||||
}
|
||||
|
||||
if (indexedWriteMethod != null) {
|
||||
Class<?> params[] = indexedWriteMethod.getParameterTypes();
|
||||
Class<?>[] params = indexedWriteMethod.getParameterTypes();
|
||||
if (params.length != 2) {
|
||||
throw new IntrospectionException("Bad indexed write method arg count: " + indexedWriteMethod);
|
||||
}
|
||||
|
||||
+6
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -349,10 +349,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
public boolean hasCustomEditorForElement(@Nullable Class<?> elementType, @Nullable String propertyPath) {
|
||||
if (propertyPath != null && this.customEditorsForPath != null) {
|
||||
for (Map.Entry<String, CustomEditorHolder> entry : this.customEditorsForPath.entrySet()) {
|
||||
if (PropertyAccessorUtils.matchesProperty(entry.getKey(), propertyPath)) {
|
||||
if (entry.getValue().getPropertyEditor(elementType) != null) {
|
||||
return true;
|
||||
}
|
||||
if (PropertyAccessorUtils.matchesProperty(entry.getKey(), propertyPath) &&
|
||||
entry.getValue().getPropertyEditor(elementType) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,9 +466,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.customEditors.forEach(target::registerCustomEditor);
|
||||
}
|
||||
if (this.customEditorsForPath != null) {
|
||||
for (Map.Entry<String, CustomEditorHolder> entry : this.customEditorsForPath.entrySet()) {
|
||||
String editorPath = entry.getKey();
|
||||
CustomEditorHolder editorHolder = entry.getValue();
|
||||
this.customEditorsForPath.forEach((editorPath, editorHolder) -> {
|
||||
if (nestedProperty != null) {
|
||||
int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(editorPath);
|
||||
if (pos != -1) {
|
||||
@@ -485,7 +482,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
target.registerCustomEditor(
|
||||
editorHolder.getRegisteredType(), editorPath, editorHolder.getPropertyEditor());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,7 +91,7 @@ public abstract class PropertyMatches {
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
private String[] possibleMatches;
|
||||
private final String[] possibleMatches;
|
||||
|
||||
|
||||
/**
|
||||
@@ -155,8 +155,8 @@ public abstract class PropertyMatches {
|
||||
if (s2.isEmpty()) {
|
||||
return s1.length();
|
||||
}
|
||||
int d[][] = new int[s1.length() + 1][s2.length() + 1];
|
||||
|
||||
int[][] d = new int[s1.length() + 1][s2.length() + 1];
|
||||
for (int i = 0; i <= s1.length(); i++) {
|
||||
d[i][0] = i;
|
||||
}
|
||||
@@ -165,18 +165,17 @@ public abstract class PropertyMatches {
|
||||
}
|
||||
|
||||
for (int i = 1; i <= s1.length(); i++) {
|
||||
char s_i = s1.charAt(i - 1);
|
||||
char c1 = s1.charAt(i - 1);
|
||||
for (int j = 1; j <= s2.length(); j++) {
|
||||
int cost;
|
||||
char t_j = s2.charAt(j - 1);
|
||||
if (s_i == t_j) {
|
||||
char c2 = s2.charAt(j - 1);
|
||||
if (c1 == c2) {
|
||||
cost = 0;
|
||||
}
|
||||
else {
|
||||
cost = 1;
|
||||
}
|
||||
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
|
||||
d[i - 1][j - 1] + cost);
|
||||
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1), d[i - 1][j - 1] + cost);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,24 +188,23 @@ public abstract class PropertyMatches {
|
||||
private static class BeanPropertyMatches extends PropertyMatches {
|
||||
|
||||
public BeanPropertyMatches(String propertyName, Class<?> beanClass, int maxDistance) {
|
||||
super(propertyName, calculateMatches(propertyName,
|
||||
BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
|
||||
super(propertyName,
|
||||
calculateMatches(propertyName, BeanUtils.getPropertyDescriptors(beanClass), maxDistance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate possible property alternatives for the given property and
|
||||
* class. Internally uses the {@code getStringDistance} method, which
|
||||
* in turn uses the Levenshtein algorithm to determine the distance between
|
||||
* two Strings.
|
||||
* @param propertyDescriptors the JavaBeans property descriptors to search
|
||||
* Generate possible property alternatives for the given property and class.
|
||||
* Internally uses the {@code getStringDistance} method, which in turn uses
|
||||
* the Levenshtein algorithm to determine the distance between two Strings.
|
||||
* @param descriptors the JavaBeans property descriptors to search
|
||||
* @param maxDistance the maximum distance to accept
|
||||
*/
|
||||
private static String[] calculateMatches(String propertyName, PropertyDescriptor[] propertyDescriptors, int maxDistance) {
|
||||
private static String[] calculateMatches(String name, PropertyDescriptor[] descriptors, int maxDistance) {
|
||||
List<String> candidates = new ArrayList<>();
|
||||
for (PropertyDescriptor pd : propertyDescriptors) {
|
||||
for (PropertyDescriptor pd : descriptors) {
|
||||
if (pd.getWriteMethod() != null) {
|
||||
String possibleAlternative = pd.getName();
|
||||
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
|
||||
if (calculateStringDistance(name, possibleAlternative) <= maxDistance) {
|
||||
candidates.add(possibleAlternative);
|
||||
}
|
||||
}
|
||||
@@ -215,21 +213,16 @@ public abstract class PropertyMatches {
|
||||
return StringUtils.toStringArray(candidates);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String buildErrorMessage() {
|
||||
String propertyName = getPropertyName();
|
||||
String[] possibleMatches = getPossibleMatches();
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Bean property '");
|
||||
msg.append(propertyName);
|
||||
msg.append("' is not writable or has an invalid setter method. ");
|
||||
|
||||
if (ObjectUtils.isEmpty(possibleMatches)) {
|
||||
msg.append("Does the parameter type of the setter match the return type of the getter?");
|
||||
StringBuilder msg = new StringBuilder(160);
|
||||
msg.append("Bean property '").append(getPropertyName()).append(
|
||||
"' is not writable or has an invalid setter method. ");
|
||||
if (!ObjectUtils.isEmpty(getPossibleMatches())) {
|
||||
appendHintMessage(msg);
|
||||
}
|
||||
else {
|
||||
appendHintMessage(msg);
|
||||
msg.append("Does the parameter type of the setter match the return type of the getter?");
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
@@ -242,11 +235,11 @@ public abstract class PropertyMatches {
|
||||
super(propertyName, calculateMatches(propertyName, beanClass, maxDistance));
|
||||
}
|
||||
|
||||
private static String[] calculateMatches(final String propertyName, Class<?> beanClass, final int maxDistance) {
|
||||
private static String[] calculateMatches(final String name, Class<?> clazz, final int maxDistance) {
|
||||
final List<String> candidates = new ArrayList<>();
|
||||
ReflectionUtils.doWithFields(beanClass, field -> {
|
||||
ReflectionUtils.doWithFields(clazz, field -> {
|
||||
String possibleAlternative = field.getName();
|
||||
if (calculateStringDistance(propertyName, possibleAlternative) <= maxDistance) {
|
||||
if (calculateStringDistance(name, possibleAlternative) <= maxDistance) {
|
||||
candidates.add(possibleAlternative);
|
||||
}
|
||||
});
|
||||
@@ -256,14 +249,10 @@ public abstract class PropertyMatches {
|
||||
|
||||
@Override
|
||||
public String buildErrorMessage() {
|
||||
String propertyName = getPropertyName();
|
||||
String[] possibleMatches = getPossibleMatches();
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Bean property '");
|
||||
msg.append(propertyName);
|
||||
msg.append("' has no matching field. ");
|
||||
|
||||
if (!ObjectUtils.isEmpty(possibleMatches)) {
|
||||
StringBuilder msg = new StringBuilder(80);
|
||||
msg.append("Bean property '").append(getPropertyName()).append("' has no matching field.");
|
||||
if (!ObjectUtils.isEmpty(getPossibleMatches())) {
|
||||
msg.append(' ');
|
||||
appendHintMessage(msg);
|
||||
}
|
||||
return msg.toString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -317,7 +317,7 @@ class TypeConverterDelegate {
|
||||
|
||||
if (Enum.class == requiredType && this.targetObject != null) {
|
||||
// target type is declared as raw enum, treat the trimmed value as <enum.fqn>.FIELD_NAME
|
||||
int index = trimmedValue.lastIndexOf(".");
|
||||
int index = trimmedValue.lastIndexOf('.');
|
||||
if (index > - 1) {
|
||||
String enumType = trimmedValue.substring(0, index);
|
||||
String fieldName = trimmedValue.substring(index + 1);
|
||||
@@ -346,6 +346,7 @@ class TypeConverterDelegate {
|
||||
// to be checked, hence we don't return it right away.
|
||||
try {
|
||||
Field enumField = requiredType.getField(trimmedValue);
|
||||
ReflectionUtils.makeAccessible(enumField);
|
||||
convertedValue = enumField.get(null);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.beans;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,9 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
public static final String ERROR_CODE = "typeMismatch";
|
||||
|
||||
|
||||
@Nullable
|
||||
private String propertyName;
|
||||
|
||||
@Nullable
|
||||
private transient Object value;
|
||||
|
||||
@@ -44,7 +48,7 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new TypeMismatchException.
|
||||
* Create a new {@code TypeMismatchException}.
|
||||
* @param propertyChangeEvent the PropertyChangeEvent that resulted in the problem
|
||||
* @param requiredType the required target type
|
||||
*/
|
||||
@@ -53,7 +57,7 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TypeMismatchException.
|
||||
* Create a new {@code TypeMismatchException}.
|
||||
* @param propertyChangeEvent the PropertyChangeEvent that resulted in the problem
|
||||
* @param requiredType the required target type (or {@code null} if not known)
|
||||
* @param cause the root cause (may be {@code null})
|
||||
@@ -69,24 +73,27 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
(propertyChangeEvent.getPropertyName() != null ?
|
||||
" for property '" + propertyChangeEvent.getPropertyName() + "'" : ""),
|
||||
cause);
|
||||
this.propertyName = propertyChangeEvent.getPropertyName();
|
||||
this.value = propertyChangeEvent.getNewValue();
|
||||
this.requiredType = requiredType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TypeMismatchException without PropertyChangeEvent.
|
||||
* Create a new {@code TypeMismatchException} without a {@code PropertyChangeEvent}.
|
||||
* @param value the offending value that couldn't be converted (may be {@code null})
|
||||
* @param requiredType the required target type (or {@code null} if not known)
|
||||
* @see #initPropertyName
|
||||
*/
|
||||
public TypeMismatchException(@Nullable Object value, @Nullable Class<?> requiredType) {
|
||||
this(value, requiredType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TypeMismatchException without PropertyChangeEvent.
|
||||
* Create a new {@code TypeMismatchException} without a {@code PropertyChangeEvent}.
|
||||
* @param value the offending value that couldn't be converted (may be {@code null})
|
||||
* @param requiredType the required target type (or {@code null} if not known)
|
||||
* @param cause the root cause (may be {@code null})
|
||||
* @see #initPropertyName
|
||||
*/
|
||||
public TypeMismatchException(@Nullable Object value, @Nullable Class<?> requiredType, @Nullable Throwable cause) {
|
||||
super("Failed to convert value of type '" + ClassUtils.getDescriptiveType(value) + "'" +
|
||||
@@ -97,6 +104,28 @@ public class TypeMismatchException extends PropertyAccessException {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize this exception's property name for exposure through {@link #getPropertyName()},
|
||||
* as an alternative to having it initialized via a {@link PropertyChangeEvent}.
|
||||
* @param propertyName the property name to expose
|
||||
* @since 5.0.4
|
||||
* @see #TypeMismatchException(Object, Class)
|
||||
* @see #TypeMismatchException(Object, Class, Throwable)
|
||||
*/
|
||||
public void initPropertyName(String propertyName) {
|
||||
Assert.state(this.propertyName == null, "Property name already initialized");
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the affected property, if available.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getPropertyName() {
|
||||
return this.propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the offending value (may be {@code null}).
|
||||
*/
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -149,7 +149,7 @@ public class BeanCreationException extends FatalBeanException {
|
||||
if (this.relatedCauses == null) {
|
||||
return null;
|
||||
}
|
||||
return this.relatedCauses.toArray(new Throwable[this.relatedCauses.size()]);
|
||||
return this.relatedCauses.toArray(new Throwable[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+32
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -149,14 +149,7 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
List<String> resultList = new ArrayList<>();
|
||||
resultList.addAll(Arrays.asList(result));
|
||||
for (String beanName : parentResult) {
|
||||
if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
resultList.add(beanName);
|
||||
}
|
||||
}
|
||||
result = StringUtils.toStringArray(resultList);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -182,14 +175,7 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
List<String> resultList = new ArrayList<>();
|
||||
resultList.addAll(Arrays.asList(result));
|
||||
for (String beanName : parentResult) {
|
||||
if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
resultList.add(beanName);
|
||||
}
|
||||
}
|
||||
result = StringUtils.toStringArray(resultList);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -225,14 +211,7 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
|
||||
List<String> resultList = new ArrayList<>();
|
||||
resultList.addAll(Arrays.asList(result));
|
||||
for (String beanName : parentResult) {
|
||||
if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
resultList.add(beanName);
|
||||
}
|
||||
}
|
||||
result = StringUtils.toStringArray(resultList);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -365,6 +344,7 @@ public abstract class BeanFactoryUtils {
|
||||
*/
|
||||
public static String[] beanNamesForAnnotationIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<? extends Annotation> annotationType) {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForAnnotation(annotationType);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
@@ -372,14 +352,7 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForAnnotationIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), annotationType);
|
||||
List<String> resultList = new ArrayList<>();
|
||||
resultList.addAll(Arrays.asList(result));
|
||||
for (String beanName : parentResult) {
|
||||
if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
resultList.add(beanName);
|
||||
}
|
||||
}
|
||||
result = StringUtils.toStringArray(resultList);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -477,6 +450,29 @@ public abstract class BeanFactoryUtils {
|
||||
return uniqueBean(type, beansOfType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merge the given bean names result with the given parent result.
|
||||
* @param result the local bean name result
|
||||
* @param parentResult the parent bean name result (possibly empty)
|
||||
* @param hbf the local bean factory
|
||||
* @return the merged result (possibly the local result as-is)
|
||||
* @since 4.3.15
|
||||
*/
|
||||
private static String[] mergeNamesWithParent(String[] result, String[] parentResult, HierarchicalBeanFactory hbf) {
|
||||
if (parentResult.length == 0) {
|
||||
return result;
|
||||
}
|
||||
List<String> merged = new ArrayList<>(result.length + parentResult.length);
|
||||
merged.addAll(Arrays.asList(result));
|
||||
for (String beanName : parentResult) {
|
||||
if (!merged.contains(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
merged.add(beanName);
|
||||
}
|
||||
}
|
||||
return StringUtils.toStringArray(merged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a unique bean for the given type from the given Map of matching beans.
|
||||
* @param type type of bean to match
|
||||
@@ -486,11 +482,11 @@ public abstract class BeanFactoryUtils {
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
*/
|
||||
private static <T> T uniqueBean(Class<T> type, Map<String, T> matchingBeans) {
|
||||
int nrFound = matchingBeans.size();
|
||||
if (nrFound == 1) {
|
||||
int count = matchingBeans.size();
|
||||
if (count == 1) {
|
||||
return matchingBeans.values().iterator().next();
|
||||
}
|
||||
else if (nrFound > 1) {
|
||||
else if (count > 1) {
|
||||
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-2
@@ -50,7 +50,7 @@ public class CannotLoadBeanClassException extends FatalBeanException {
|
||||
public CannotLoadBeanClassException(
|
||||
@Nullable String resourceDescription, String beanName, @Nullable String beanClassName, ClassNotFoundException cause) {
|
||||
|
||||
super("Cannot find class [" + String.valueOf(beanClassName) + "] for bean with name '" + beanName + "'" +
|
||||
super("Cannot find class [" + beanClassName + "] for bean with name '" + beanName + "'" +
|
||||
(resourceDescription != null ? " defined in " + resourceDescription : ""), cause);
|
||||
this.resourceDescription = resourceDescription;
|
||||
this.beanName = beanName;
|
||||
@@ -68,7 +68,7 @@ public class CannotLoadBeanClassException extends FatalBeanException {
|
||||
public CannotLoadBeanClassException(
|
||||
@Nullable String resourceDescription, String beanName, @Nullable String beanClassName, LinkageError cause) {
|
||||
|
||||
super("Error loading class [" + String.valueOf(beanClassName) + "] for bean with name '" + beanName + "'" +
|
||||
super("Error loading class [" + beanClassName + "] for bean with name '" + beanName + "'" +
|
||||
(resourceDescription != null ? " defined in " + resourceDescription : "") +
|
||||
": problem with class file or dependent class", cause);
|
||||
this.resourceDescription = resourceDescription;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Defines a factory which can return an Object instance
|
||||
|
||||
+14
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -280,7 +280,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
|
||||
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
|
||||
}
|
||||
List<Constructor<?>> candidates = new ArrayList<Constructor<?>>(rawCandidates.length);
|
||||
List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
|
||||
Constructor<?> requiredConstructor = null;
|
||||
Constructor<?> defaultConstructor = null;
|
||||
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
|
||||
@@ -342,12 +342,13 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
"default constructor to fall back to: " + candidates.get(0));
|
||||
}
|
||||
}
|
||||
candidateConstructors = candidates.toArray(new Constructor<?>[candidates.size()]);
|
||||
candidateConstructors = candidates.toArray(new Constructor<?>[0]);
|
||||
}
|
||||
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
|
||||
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
|
||||
}
|
||||
else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null) {
|
||||
else if (nonSyntheticConstructors == 2 && primaryConstructor != null
|
||||
&& defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
|
||||
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
|
||||
}
|
||||
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
|
||||
@@ -592,11 +593,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
registerDependentBeans(beanName, autowiredBeanNames);
|
||||
if (autowiredBeanNames.size() == 1) {
|
||||
String autowiredBeanName = autowiredBeanNames.iterator().next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
if (beanFactory.containsBean(autowiredBeanName) &&
|
||||
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
|
||||
this.cachedFieldValue = new ShortcutDependencyDescriptor(
|
||||
desc, autowiredBeanName, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -671,19 +671,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
if (!this.cached) {
|
||||
if (arguments != null) {
|
||||
Object[] cachedMethodArguments = new Object[paramTypes.length];
|
||||
for (int i = 0; i < arguments.length; i++) {
|
||||
cachedMethodArguments[i] = descriptors[i];
|
||||
}
|
||||
System.arraycopy(descriptors, 0, cachedMethodArguments, 0, arguments.length);
|
||||
registerDependentBeans(beanName, autowiredBeans);
|
||||
if (autowiredBeans.size() == paramTypes.length) {
|
||||
Iterator<String> it = autowiredBeans.iterator();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
String autowiredBeanName = it.next();
|
||||
if (beanFactory.containsBean(autowiredBeanName)) {
|
||||
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
|
||||
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
|
||||
descriptors[i], autowiredBeanName, paramTypes[i]);
|
||||
}
|
||||
if (beanFactory.containsBean(autowiredBeanName) &&
|
||||
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
|
||||
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
|
||||
descriptors[i], autowiredBeanName, paramTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -87,7 +87,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
@Nullable
|
||||
private transient final Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);
|
||||
private final transient Map<Class<?>, LifecycleMetadata> lifecycleMetadataCache = new ConcurrentHashMap<>(256);
|
||||
|
||||
|
||||
/**
|
||||
@@ -205,21 +205,17 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<>();
|
||||
|
||||
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
|
||||
if (initAnnotationType != null) {
|
||||
if (method.getAnnotation(initAnnotationType) != null) {
|
||||
LifecycleElement element = new LifecycleElement(method);
|
||||
currInitMethods.add(element);
|
||||
if (debug) {
|
||||
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
if (initAnnotationType != null && method.isAnnotationPresent(initAnnotationType)) {
|
||||
LifecycleElement element = new LifecycleElement(method);
|
||||
currInitMethods.add(element);
|
||||
if (debug) {
|
||||
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
}
|
||||
if (destroyAnnotationType != null) {
|
||||
if (method.getAnnotation(destroyAnnotationType) != null) {
|
||||
currDestroyMethods.add(new LifecycleElement(method));
|
||||
if (debug) {
|
||||
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
if (destroyAnnotationType != null && method.isAnnotationPresent(destroyAnnotationType)) {
|
||||
currDestroyMethods.add(new LifecycleElement(method));
|
||||
if (debug) {
|
||||
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ public class InjectionMetadata {
|
||||
}
|
||||
|
||||
|
||||
public static abstract class InjectedElement {
|
||||
public abstract static class InjectedElement {
|
||||
|
||||
protected final Member member;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ import java.lang.annotation.Target;
|
||||
* beans, provide stub implementations of your lookup methods to be able to declare
|
||||
* them as concrete classes. And please remember that lookup methods won't work on
|
||||
* beans returned from {@code @Bean} methods in configuration classes; you'll have
|
||||
* to resort to {@code @Inject Provider<TargetBean>} or the like instead.
|
||||
* to resort to {@code @Inject Provider<TargetBean>} or the like instead.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,8 +56,8 @@ import org.springframework.util.Assert;
|
||||
* and obviates the need (<b>in part</b>) for a developer to code a method that
|
||||
* simply checks that all required properties have actually been set.
|
||||
*
|
||||
* <p>Please note that an 'init' method may still need to implemented (and may
|
||||
* still be desirable), because all that this class does is enforce that a
|
||||
* <p>Please note that an 'init' method may still need to be implemented (and may
|
||||
* still be desirable), because all that this class does is enforcing that a
|
||||
* 'required' property has actually been configured with a value. It does
|
||||
* <b>not</b> check anything else... In particular, it does not check that a
|
||||
* configured value is not {@code null}.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -225,7 +225,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* FactoryBean is supposed to implement, for use with an 'early singleton
|
||||
* proxy' that will be exposed in case of a circular reference.
|
||||
* <p>The default implementation returns this FactoryBean's object type,
|
||||
* provided that it is an interface, or {@code null} else. The latter
|
||||
* provided that it is an interface, or {@code null} otherwise. The latter
|
||||
* indicates that early singleton access is not supported by this FactoryBean.
|
||||
* This will lead to a FactoryBeanNotInitializedException getting thrown.
|
||||
* @return the interfaces to use for 'early singletons',
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,7 +89,9 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);
|
||||
|
||||
/**
|
||||
* Return this factory's class loader for loading bean classes.
|
||||
* Return this factory's class loader for loading bean classes
|
||||
* (only {@code null} if even the system ClassLoader isn't accessible).
|
||||
* @see org.springframework.util.ClassUtils#forName(String, ClassLoader)
|
||||
*/
|
||||
@Nullable
|
||||
ClassLoader getBeanClassLoader();
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,9 +97,7 @@ public class CustomScopeConfigurer implements BeanFactoryPostProcessor, BeanClas
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (this.scopes != null) {
|
||||
for (Map.Entry<String, Object> entry : this.scopes.entrySet()) {
|
||||
String scopeKey = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
this.scopes.forEach((scopeKey, value) -> {
|
||||
if (value instanceof Scope) {
|
||||
beanFactory.registerScope(scopeKey, (Scope) value);
|
||||
}
|
||||
@@ -118,7 +116,7 @@ public class CustomScopeConfigurer implements BeanFactoryPostProcessor, BeanClas
|
||||
scopeKey + "] is not an instance of required type [" + Scope.class.getName() +
|
||||
"] or a corresponding Class or String value indicating a Scope implementation");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,6 +64,8 @@ import org.springframework.lang.Nullable;
|
||||
* Note that the value of "foo" in the first document is not simply replaced
|
||||
* with the value in the second, but its nested values are merged.
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
|
||||
+30
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,12 +25,12 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.yaml.snakeyaml.LoaderOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
@@ -46,6 +46,8 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* Base class for YAML factories.
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
@@ -78,15 +80,16 @@ public abstract class YamlProcessor {
|
||||
* name: My Cool App
|
||||
* </pre>
|
||||
* when mapped with
|
||||
* <code>documentMatchers = YamlProcessor.mapMatcher({"environment": "prod"})</code>
|
||||
* <pre class="code">
|
||||
* setDocumentMatchers(properties ->
|
||||
* ("prod".equals(properties.getProperty("environment")) ? MatchStatus.FOUND : MatchStatus.NOT_FOUND));
|
||||
* </pre>
|
||||
* would end up as
|
||||
* <pre class="code">
|
||||
* environment=prod
|
||||
* url=http://foo.bar.com
|
||||
* name=My Cool App
|
||||
* url=http://dev.bar.com
|
||||
* </pre>
|
||||
* @param matchers a map of keys to value patterns (regular expressions)
|
||||
*/
|
||||
public void setDocumentMatchers(DocumentMatcher... matchers) {
|
||||
this.documentMatchers = Arrays.asList(matchers);
|
||||
@@ -95,8 +98,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Flag indicating that a document for which all the
|
||||
* {@link #setDocumentMatchers(DocumentMatcher...) document matchers} abstain will
|
||||
* nevertheless match.
|
||||
* @param matchDefault the flag to set (default true)
|
||||
* nevertheless match. Default is {@code true}.
|
||||
*/
|
||||
public void setMatchDefault(boolean matchDefault) {
|
||||
this.matchDefault = matchDefault;
|
||||
@@ -105,9 +107,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Method to use for resolving resources. Each resource will be converted to a Map,
|
||||
* so this property is used to decide which map entries to keep in the final output
|
||||
* from this factory.
|
||||
* @param resolutionMethod the resolution method to set (defaults to
|
||||
* {@link ResolutionMethod#OVERRIDE}).
|
||||
* from this factory. Default is {@link ResolutionMethod#OVERRIDE}.
|
||||
*/
|
||||
public void setResolutionMethod(ResolutionMethod resolutionMethod) {
|
||||
Assert.notNull(resolutionMethod, "ResolutionMethod must not be null");
|
||||
@@ -145,9 +145,14 @@ public abstract class YamlProcessor {
|
||||
|
||||
/**
|
||||
* Create the {@link Yaml} instance to use.
|
||||
* <p>The default implementation sets the "allowDuplicateKeys" flag to {@code false},
|
||||
* enabling built-in duplicate key handling in SnakeYAML 1.18+.
|
||||
* @see LoaderOptions#setAllowDuplicateKeys(boolean)
|
||||
*/
|
||||
protected Yaml createYaml() {
|
||||
return new Yaml(new StrictMapAppenderConstructor());
|
||||
LoaderOptions options = new LoaderOptions();
|
||||
options.setAllowDuplicateKeys(false);
|
||||
return new Yaml(options);
|
||||
}
|
||||
|
||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||
@@ -272,8 +277,7 @@ public abstract class YamlProcessor {
|
||||
}
|
||||
|
||||
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path) {
|
||||
for (Entry<String, Object> entry : source.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
source.forEach((key, value) -> {
|
||||
if (StringUtils.hasText(path)) {
|
||||
if (key.startsWith("[")) {
|
||||
key = path + key;
|
||||
@@ -282,7 +286,6 @@ public abstract class YamlProcessor {
|
||||
key = path + '.' + key;
|
||||
}
|
||||
}
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof String) {
|
||||
result.put(key, value);
|
||||
}
|
||||
@@ -296,16 +299,21 @@ public abstract class YamlProcessor {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
int count = 0;
|
||||
for (Object object : collection) {
|
||||
buildFlattenedMap(result,
|
||||
Collections.singletonMap("[" + (count++) + "]", object), key);
|
||||
if (collection.isEmpty()) {
|
||||
result.put(key, "");
|
||||
}
|
||||
else {
|
||||
int count = 0;
|
||||
for (Object object : collection) {
|
||||
buildFlattenedMap(result, Collections.singletonMap(
|
||||
"[" + (count++) + "]", object), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.put(key, (value != null ? value : ""));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +400,10 @@ public abstract class YamlProcessor {
|
||||
|
||||
/**
|
||||
* A specialized {@link Constructor} that checks for duplicate keys.
|
||||
* @deprecated as of Spring Framework 5.0.6 (not used anymore here),
|
||||
* superseded by SnakeYAML's own duplicate key handling
|
||||
*/
|
||||
@Deprecated
|
||||
protected static class StrictMapAppenderConstructor extends Constructor {
|
||||
|
||||
// Declared as public for use in subclasses
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,6 +74,8 @@ import org.springframework.lang.Nullable;
|
||||
* servers[1]=foo.bar.com
|
||||
* </pre>
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+10
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -237,6 +237,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
Closure beans = new Closure(this) {
|
||||
@Override
|
||||
public Object call(Object[] args) {
|
||||
invokeBeanDefiningClosure((Closure) args[0]);
|
||||
return null;
|
||||
@@ -380,10 +381,8 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
refName = args[0].toString();
|
||||
}
|
||||
boolean parentRef = false;
|
||||
if (args.length > 1) {
|
||||
if (args[1] instanceof Boolean) {
|
||||
parentRef = (Boolean) args[1];
|
||||
}
|
||||
if (args.length > 1 && args[1] instanceof Boolean) {
|
||||
parentRef = (Boolean) args[1];
|
||||
}
|
||||
return new RuntimeBeanReference(refName, parentRef);
|
||||
}
|
||||
@@ -410,12 +409,7 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
}
|
||||
|
||||
private boolean addDeferredProperty(String property, Object newValue) {
|
||||
if (newValue instanceof List) {
|
||||
this.deferredProperties.put(this.currentBeanDefinition.getBeanName() + '.' + property,
|
||||
new DeferredProperty(this.currentBeanDefinition, property, newValue));
|
||||
return true;
|
||||
}
|
||||
else if (newValue instanceof Map) {
|
||||
if (newValue instanceof List || newValue instanceof Map) {
|
||||
this.deferredProperties.put(this.currentBeanDefinition.getBeanName() + '.' + property,
|
||||
new DeferredProperty(this.currentBeanDefinition, property, newValue));
|
||||
return true;
|
||||
@@ -524,10 +518,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
Closure callable = (Closure) args[args.length - 1];
|
||||
callable.setDelegate(this);
|
||||
callable.setResolveStrategy(Closure.DELEGATE_FIRST);
|
||||
callable.call(new Object[]{currentBeanDefinition});
|
||||
callable.call(this.currentBeanDefinition);
|
||||
}
|
||||
|
||||
GroovyBeanDefinitionWrapper beanDefinition = currentBeanDefinition;
|
||||
GroovyBeanDefinitionWrapper beanDefinition = this.currentBeanDefinition;
|
||||
this.currentBeanDefinition = null;
|
||||
beanDefinition.getBeanDefinition().setAttribute(GroovyBeanDefinitionWrapper.class.getName(), beanDefinition);
|
||||
getRegistry().registerBeanDefinition(beanName, beanDefinition.getBeanDefinition());
|
||||
@@ -815,14 +809,17 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invokeMethod(String name, Object args) {
|
||||
return InvokerHelper.invokeMethod(this.propertyValue, name, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
return InvokerHelper.getProperty(this.propertyValue, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String name, Object value) {
|
||||
InvokerHelper.setProperty(this.propertyValue, name, value);
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -162,6 +162,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getProperty(String property) {
|
||||
if (this.definitionWrapper.isReadableProperty(property)) {
|
||||
return this.definitionWrapper.getPropertyValue(property);
|
||||
@@ -172,6 +173,7 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
|
||||
return super.getProperty(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String property, Object newValue) {
|
||||
if (PARENT.equals(property)) {
|
||||
setParent(newValue);
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,8 +83,8 @@ public class BeanComponentDefinition extends BeanDefinitionHolder implements Com
|
||||
references.add((BeanReference) value);
|
||||
}
|
||||
}
|
||||
this.innerBeanDefinitions = innerBeans.toArray(new BeanDefinition[innerBeans.size()]);
|
||||
this.beanReferences = references.toArray(new BeanReference[references.size()]);
|
||||
this.innerBeanDefinitions = innerBeans.toArray(new BeanDefinition[0]);
|
||||
this.beanReferences = references.toArray(new BeanReference[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,7 +79,7 @@ public class CompositeComponentDefinition extends AbstractComponentDefinition {
|
||||
* @return the array of nested components, or an empty array if none
|
||||
*/
|
||||
public ComponentDefinition[] getNestedComponents() {
|
||||
return this.nestedComponents.toArray(new ComponentDefinition[this.nestedComponents.size()]);
|
||||
return this.nestedComponents.toArray(new ComponentDefinition[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-14
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.springframework.beans.factory.parsing;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Simple {@link Stack}-based structure for tracking the logical position during
|
||||
* a parsing process. {@link Entry entries} are added to the stack at
|
||||
* Simple {@link LinkedList}-based structure for tracking the logical position during
|
||||
* a parsing process. {@link Entry entries} are added to the LinkedList at
|
||||
* each point during the parse phase in a reader-specific manner.
|
||||
*
|
||||
* <p>Calling {@link #toString()} will render a tree-style view of the current logical
|
||||
@@ -40,49 +40,49 @@ public final class ParseState {
|
||||
private static final char TAB = '\t';
|
||||
|
||||
/**
|
||||
* Internal {@link Stack} storage.
|
||||
* Internal {@link LinkedList} storage.
|
||||
*/
|
||||
private final Stack<Entry> state;
|
||||
private final LinkedList<Entry> state;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code ParseState} with an empty {@link Stack}.
|
||||
* Create a new {@code ParseState} with an empty {@link LinkedList}.
|
||||
*/
|
||||
public ParseState() {
|
||||
this.state = new Stack<>();
|
||||
this.state = new LinkedList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ParseState} whose {@link Stack} is a {@link Object#clone clone}
|
||||
* Create a new {@code ParseState} whose {@link LinkedList} is a {@link Object#clone clone}
|
||||
* of that of the passed in {@code ParseState}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private ParseState(ParseState other) {
|
||||
this.state = (Stack<Entry>) other.state.clone();
|
||||
this.state = (LinkedList<Entry>) other.state.clone();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new {@link Entry} to the {@link Stack}.
|
||||
* Add a new {@link Entry} to the {@link LinkedList}.
|
||||
*/
|
||||
public void push(Entry entry) {
|
||||
this.state.push(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an {@link Entry} from the {@link Stack}.
|
||||
* Remove an {@link Entry} from the {@link LinkedList}.
|
||||
*/
|
||||
public void pop() {
|
||||
this.state.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link Entry} currently at the top of the {@link Stack} or
|
||||
* {@code null} if the {@link Stack} is empty.
|
||||
* Return the {@link Entry} currently at the top of the {@link LinkedList} or
|
||||
* {@code null} if the {@link LinkedList} is empty.
|
||||
*/
|
||||
@Nullable
|
||||
public Entry peek() {
|
||||
return this.state.empty() ? null : this.state.peek();
|
||||
return this.state.isEmpty() ? null : this.state.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+51
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -40,6 +39,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
@@ -505,12 +506,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
return beanInstance;
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
// A previously detected exception with proper bean creation context already...
|
||||
throw ex;
|
||||
}
|
||||
catch (ImplicitlyAppearedSingletonException ex) {
|
||||
// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
|
||||
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
|
||||
// A previously detected exception with proper bean creation context already,
|
||||
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
@@ -756,7 +754,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
|
||||
factoryMethod, args, getBeanClassLoader());
|
||||
uniqueCandidate = (commonType == null ? factoryMethod : null);
|
||||
uniqueCandidate = (commonType == null && returnType == factoryMethod.getReturnType() ?
|
||||
factoryMethod : null);
|
||||
commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
|
||||
if (commonType == null) {
|
||||
// Ambiguous return types found: return null to indicate "not determinable".
|
||||
@@ -780,12 +779,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
if (commonType != null) {
|
||||
// Clear return type found: all factory methods return same type.
|
||||
mbd.factoryMethodReturnType = (uniqueCandidate != null ?
|
||||
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
|
||||
if (commonType == null) {
|
||||
return null;
|
||||
}
|
||||
return commonType;
|
||||
// Common return type found: all factory methods return same type. For a non-parameterized
|
||||
// unique candidate, cache the full type declaration context of the target factory method.
|
||||
cachedReturnType = (uniqueCandidate != null ?
|
||||
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
|
||||
mbd.factoryMethodReturnType = cachedReturnType;
|
||||
return cachedReturnType.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,12 +933,16 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (bw != null) {
|
||||
return (FactoryBean<?>) bw.getWrappedInstance();
|
||||
}
|
||||
Object beanInstance = getSingleton(beanName, false);
|
||||
if (beanInstance instanceof FactoryBean) {
|
||||
return (FactoryBean<?>) beanInstance;
|
||||
}
|
||||
if (isSingletonCurrentlyInCreation(beanName) ||
|
||||
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object instance = null;
|
||||
Object instance;
|
||||
try {
|
||||
// Mark this bean as currently in creation, even if just partially.
|
||||
beforeSingletonCreation(beanName);
|
||||
@@ -1496,15 +1502,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @see #isExcludedFromDependencyCheck
|
||||
*/
|
||||
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
|
||||
List<PropertyDescriptor> pds =
|
||||
new LinkedList<>(Arrays.asList(bw.getPropertyDescriptors()));
|
||||
for (Iterator<PropertyDescriptor> it = pds.iterator(); it.hasNext();) {
|
||||
PropertyDescriptor pd = it.next();
|
||||
if (isExcludedFromDependencyCheck(pd)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return pds.toArray(new PropertyDescriptor[pds.size()]);
|
||||
List<PropertyDescriptor> pds = new LinkedList<>(Arrays.asList(bw.getPropertyDescriptors()));
|
||||
pds.removeIf(this::isExcludedFromDependencyCheck);
|
||||
return pds.toArray(new PropertyDescriptor[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1566,15 +1566,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
return;
|
||||
}
|
||||
|
||||
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
|
||||
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
|
||||
}
|
||||
|
||||
MutablePropertyValues mpvs = null;
|
||||
List<PropertyValue> original;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
if (bw instanceof BeanWrapperImpl) {
|
||||
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
|
||||
}
|
||||
}
|
||||
|
||||
if (pvs instanceof MutablePropertyValues) {
|
||||
mpvs = (MutablePropertyValues) pvs;
|
||||
if (mpvs.isConverted()) {
|
||||
@@ -1857,8 +1855,29 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
*/
|
||||
@Override
|
||||
protected void removeSingleton(String beanName) {
|
||||
super.removeSingleton(beanName);
|
||||
this.factoryBeanInstanceCache.remove(beanName);
|
||||
synchronized (getSingletonMutex()) {
|
||||
super.removeSingleton(beanName);
|
||||
this.factoryBeanInstanceCache.remove(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to clear FactoryBean instance cache as well.
|
||||
*/
|
||||
@Override
|
||||
protected void clearSingletonCache() {
|
||||
synchronized (getSingletonMutex()) {
|
||||
super.clearSingletonCache();
|
||||
this.factoryBeanInstanceCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the logger to collaborating delegates.
|
||||
* @since 5.0.7
|
||||
*/
|
||||
Log getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -301,7 +300,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
|
||||
}
|
||||
registerDependentBean(dep, beanName);
|
||||
getBean(dep);
|
||||
try {
|
||||
getBean(dep);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,7 +557,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
|
||||
// Check bean class whether we're dealing with a FactoryBean.
|
||||
if (FactoryBean.class.isAssignableFrom(beanType)) {
|
||||
if (!BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
if (!BeanFactoryUtils.isFactoryDereference(name) && beanInstance == null) {
|
||||
// If it's a FactoryBean, we want to look at what it creates, not the factory class.
|
||||
beanType = getTypeForFactoryBean(beanName, mbd);
|
||||
if (beanType == null) {
|
||||
@@ -1338,12 +1343,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* @since 4.2
|
||||
*/
|
||||
public void clearMetadataCache() {
|
||||
Iterator<String> mergedBeans = this.mergedBeanDefinitions.keySet().iterator();
|
||||
while (mergedBeans.hasNext()) {
|
||||
if (!isBeanEligibleForMetadataCaching(mergedBeans.next())) {
|
||||
mergedBeans.remove();
|
||||
}
|
||||
}
|
||||
this.mergedBeanDefinitions.keySet().removeIf(bean -> !isBeanEligibleForMetadataCaching(bean));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1379,8 +1379,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||
}
|
||||
catch (LinkageError ex) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
|
||||
catch (LinkageError err) {
|
||||
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1501,7 +1501,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* should be used as fallback.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the merged bean definition for the bean
|
||||
* @return the type for the bean if determinable, or {@code null} else
|
||||
* @return the type for the bean if determinable, or {@code null} otherwise
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
* @see #getBean(String)
|
||||
*/
|
||||
@@ -1515,7 +1515,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return getTypeForFactoryBean(factoryBean);
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
if (ex instanceof BeanCurrentlyInCreationException) {
|
||||
if (ex.contains(BeanCurrentlyInCreationException.class)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
|
||||
}
|
||||
@@ -1614,8 +1614,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
|
||||
|
||||
// Don't let calling code try to dereference the factory if the bean isn't a factory.
|
||||
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
|
||||
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
|
||||
if (BeanFactoryUtils.isFactoryDereference(name)) {
|
||||
if (beanInstance instanceof NullBean) {
|
||||
return beanInstance;
|
||||
}
|
||||
if (!(beanInstance instanceof FactoryBean)) {
|
||||
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("serial")
|
||||
public class AutowireCandidateQualifier extends BeanMetadataAttributeAccessor {
|
||||
|
||||
public static String VALUE_KEY = "value";
|
||||
public static final String VALUE_KEY = "value";
|
||||
|
||||
private final String typeName;
|
||||
|
||||
|
||||
+20
-27
@@ -28,7 +28,6 @@ import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
@@ -58,19 +57,16 @@ abstract class AutowireUtils {
|
||||
* @param constructors the constructor array to sort
|
||||
*/
|
||||
public static void sortConstructors(Constructor<?>[] constructors) {
|
||||
Arrays.sort(constructors, new Comparator<Constructor<?>>() {
|
||||
@Override
|
||||
public int compare(Constructor<?> c1, Constructor<?> c2) {
|
||||
boolean p1 = Modifier.isPublic(c1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(c2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = c1.getParameterCount();
|
||||
int c2pl = c2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
}
|
||||
});
|
||||
Arrays.sort(constructors, (c1, c2) -> {
|
||||
boolean p1 = Modifier.isPublic(c1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(c2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = c1.getParameterCount();
|
||||
int c2pl = c2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,19 +77,16 @@ abstract class AutowireUtils {
|
||||
* @param factoryMethods the factory method array to sort
|
||||
*/
|
||||
public static void sortFactoryMethods(Method[] factoryMethods) {
|
||||
Arrays.sort(factoryMethods, new Comparator<Method>() {
|
||||
@Override
|
||||
public int compare(Method fm1, Method fm2) {
|
||||
boolean p1 = Modifier.isPublic(fm1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(fm2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = fm1.getParameterCount();
|
||||
int c2pl = fm2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
}
|
||||
});
|
||||
Arrays.sort(factoryMethods, (fm1, fm2) -> {
|
||||
boolean p1 = Modifier.isPublic(fm1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(fm2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = fm1.getParameterCount();
|
||||
int c2pl = fm2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -421,12 +421,11 @@ class BeanDefinitionValueResolver {
|
||||
*/
|
||||
private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) {
|
||||
Map<Object, Object> resolved = new LinkedHashMap<>(mm.size());
|
||||
for (Map.Entry<?, ?> entry : mm.entrySet()) {
|
||||
Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
|
||||
Object resolvedValue = resolveValueIfNecessary(
|
||||
new KeyedArgName(argName, entry.getKey()), entry.getValue());
|
||||
mm.forEach((key, value) -> {
|
||||
Object resolvedKey = resolveValueIfNecessary(argName, key);
|
||||
Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, key), value);
|
||||
resolved.put(resolvedKey, resolvedValue);
|
||||
}
|
||||
});
|
||||
return resolved;
|
||||
}
|
||||
|
||||
|
||||
+16
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,6 +32,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
@@ -78,6 +80,8 @@ class ConstructorResolver {
|
||||
|
||||
private final AbstractAutowireCapableBeanFactory beanFactory;
|
||||
|
||||
private final Log logger;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConstructorResolver for the given factory and instantiation strategy.
|
||||
@@ -85,6 +89,7 @@ class ConstructorResolver {
|
||||
*/
|
||||
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.logger = beanFactory.getLogger();
|
||||
}
|
||||
|
||||
|
||||
@@ -193,9 +198,8 @@ class ConstructorResolver {
|
||||
getUserDeclaredConstructor(candidate), autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
if (this.beanFactory.logger.isTraceEnabled()) {
|
||||
this.beanFactory.logger.trace(
|
||||
"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
}
|
||||
// Swallow and try next constructor.
|
||||
if (causes == null) {
|
||||
@@ -419,7 +423,7 @@ class ConstructorResolver {
|
||||
candidateSet.add(candidate);
|
||||
}
|
||||
}
|
||||
Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
|
||||
Method[] candidates = candidateSet.toArray(new Method[0]);
|
||||
AutowireUtils.sortFactoryMethods(candidates);
|
||||
|
||||
ConstructorArgumentValues resolvedValues = null;
|
||||
@@ -471,9 +475,8 @@ class ConstructorResolver {
|
||||
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
if (this.beanFactory.logger.isTraceEnabled()) {
|
||||
this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
|
||||
"] of bean '" + beanName + "': " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
}
|
||||
// Swallow and try next overloaded factory method.
|
||||
if (causes == null) {
|
||||
@@ -733,8 +736,8 @@ class ConstructorResolver {
|
||||
|
||||
for (String autowiredBeanName : autowiredBeanNames) {
|
||||
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
|
||||
if (this.beanFactory.logger.isDebugEnabled()) {
|
||||
this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
|
||||
" to bean named '" + autowiredBeanName + "'");
|
||||
}
|
||||
@@ -833,11 +836,11 @@ class ConstructorResolver {
|
||||
*/
|
||||
private static class ArgumentsHolder {
|
||||
|
||||
public final Object rawArguments[];
|
||||
public final Object[] rawArguments;
|
||||
|
||||
public final Object arguments[];
|
||||
public final Object[] arguments;
|
||||
|
||||
public final Object preparedArguments[];
|
||||
public final Object[] preparedArguments;
|
||||
|
||||
public boolean resolveNecessary = false;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user