mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
668 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dcd2a0395e | |||
| c0ee1ff896 | |||
| f944815d92 | |||
| 0d0399ac02 | |||
| d1f42ac729 | |||
| 17f42fc97a | |||
| fa2c377405 | |||
| 9dcdfec2e2 | |||
| 07a0a31565 | |||
| f3a2f57696 | |||
| 80bf394fdc | |||
| f948742781 | |||
| 0088922dfd | |||
| 57fbdc0ad5 | |||
| f5d689e764 | |||
| 681ced8fd3 | |||
| 8b64ad3192 | |||
| 35248498ae | |||
| 5f07434360 | |||
| cd602e5904 | |||
| 0e8bd71d53 | |||
| c752ba5b38 | |||
| 12978b8185 | |||
| 40b4276475 | |||
| 4160ced64c | |||
| a032e86355 | |||
| 4b2bad96ce | |||
| 1513c4a952 | |||
| bb6d9fabee | |||
| bffcd33ea3 | |||
| c9ffa64140 | |||
| aa0d7a61b6 | |||
| e138d7d29f | |||
| 50f8b6b3ab | |||
| 121a3bf670 | |||
| e4031f290e | |||
| 55fa5f2b65 | |||
| 3802aca474 | |||
| a9a4d7cf78 | |||
| 17382aec6d | |||
| 8ad3c958e1 | |||
| 8d743181da | |||
| f92ab75bc9 | |||
| 092b5f7556 | |||
| d4d609318d | |||
| 501891c749 | |||
| 2b0dc8d7ff | |||
| 674e2320a8 | |||
| fee259a3c5 | |||
| 016b7d753c | |||
| a17255a2e3 | |||
| 35efdf6b51 | |||
| b35c238d27 | |||
| db1fd516ea | |||
| b7337b304e | |||
| 7cac1f1e6e | |||
| fa09cd3737 | |||
| be93ee77e4 | |||
| 8330134757 | |||
| 9cb9884533 | |||
| ac25db6d2b | |||
| 22bf9febcc | |||
| c6deeb31ec | |||
| f80b2d9a94 | |||
| 8c206bf477 | |||
| 6aeb8ef56d | |||
| 04a96ffa27 | |||
| 2677584658 | |||
| 99236759ec | |||
| e2aa117ff9 | |||
| 8deec9569c | |||
| 0f8bf10aa8 | |||
| e0a7b074ed | |||
| 4fc41eeeb9 | |||
| 81143a80c4 | |||
| 9572859a35 | |||
| 78931ee3ea | |||
| e522fec611 | |||
| a12bbde87e | |||
| 50235be746 | |||
| 1332482c40 | |||
| 799589ec1c | |||
| 16fdda00c1 | |||
| d2985613d1 | |||
| beac891ff0 | |||
| 2d1b551248 | |||
| aa8cf190d3 | |||
| d643e57318 | |||
| 84d2e5a3c8 | |||
| dab56dbb05 | |||
| 9b647021f7 | |||
| 38089d8e66 | |||
| 554c3f3d7e | |||
| ee40310c92 | |||
| 226cddadef | |||
| 5a80f4f16e | |||
| bb63ce9935 | |||
| 1b4289803b | |||
| 3d7576df7f | |||
| 8b9e9202f1 | |||
| afe11e7919 | |||
| 665e6cf6ca | |||
| fd1d8aeeb4 | |||
| 9b2f9e655e | |||
| 6c370ed28d | |||
| a2b356162e | |||
| 71f7fdd632 | |||
| c35ddf905a | |||
| d866715556 | |||
| a9a1f783c5 | |||
| 65d52a4b97 | |||
| 3c8fc46568 | |||
| 421fabb2c4 | |||
| 811d523211 | |||
| 40232f4e22 | |||
| 80fa3ac907 | |||
| 54180f90e2 | |||
| 865953f145 | |||
| 93fac8882f | |||
| a3d199f4dd | |||
| 597fe0720f | |||
| 8321f01bf8 | |||
| 7e736b69b7 | |||
| 8b054840fc | |||
| 7f3d0b3e6e | |||
| 546d7ddd07 | |||
| 95099fd709 | |||
| f65e1edd58 | |||
| 0a9f98f0df | |||
| 46cf4f9ba1 | |||
| 2b930e3858 | |||
| bde2ddbeb1 | |||
| 4eb929c105 | |||
| d0d7a88233 | |||
| f7548a87ed | |||
| e0fe7cdc44 | |||
| 8289bf0aff | |||
| 79d747410d | |||
| 70bca99da8 | |||
| 83617f382c | |||
| 21ac764e5c | |||
| c4fda0e811 | |||
| 66670cfd56 | |||
| c31bfe65aa | |||
| 22ddb35258 | |||
| d0177b0f55 | |||
| 2233ec04ff | |||
| e9ff3bb4e3 | |||
| 57c8c759ae | |||
| cfd9b3461f | |||
| d3324c8d4f | |||
| ffe9bae138 | |||
| 020e51cb96 | |||
| a78066830b | |||
| 77c771e874 | |||
| 227ac3faa4 | |||
| 98dbc17591 | |||
| e58b17a3a1 | |||
| 9de97614a0 | |||
| 015e00b5dd | |||
| 0bc59225d8 | |||
| d8acc27afb | |||
| a1e4afe338 | |||
| 3b9faee335 | |||
| 0048ff84ea | |||
| c3f131325d | |||
| b945e0f202 | |||
| ce3cf3251d | |||
| d69fb06852 | |||
| e9de3bb85b | |||
| e6a51e3d29 | |||
| c734c3a3fe | |||
| a48a956c0c | |||
| e5010a823b | |||
| 1db42081e5 | |||
| 34a0857628 | |||
| ba0484fcac | |||
| f1133a8e56 | |||
| 35e37f6b60 | |||
| f117b804a8 | |||
| 278199d467 | |||
| fd568f3e96 | |||
| 45b27a85f4 | |||
| 0f71f58616 | |||
| 9834c42b5c | |||
| 7879bdfc1d | |||
| dfa8a7c358 | |||
| 427fd9b19a | |||
| 6417ed47ab | |||
| b0ef80c3ff | |||
| 7ed4884eaa | |||
| c3cc42d4d3 | |||
| 860e2bcc2d | |||
| 06231721c3 | |||
| 4d2360e5b5 | |||
| 4f52174674 | |||
| 7d7c5c9d9c | |||
| 08b9e7b83e | |||
| e24c530705 | |||
| 5017c05c23 | |||
| 6e93834e27 | |||
| 5f90a7eee9 | |||
| eff285eb3b | |||
| da7d79b3a1 | |||
| d6216fb74a | |||
| 941f3e7166 | |||
| e80c251c7a | |||
| 56abc4a429 | |||
| dde9e27630 | |||
| 15b174a522 | |||
| 1fcb2608fb | |||
| c15d687bf0 | |||
| e038631a6d | |||
| d5daa8e3a7 | |||
| 6014ca9140 | |||
| d4010573af | |||
| e3cd5c8ef0 | |||
| dec1c93b24 | |||
| 3ef6697536 | |||
| 8207c53b9a | |||
| e3be94c961 | |||
| b40f016de2 | |||
| 28849e0987 | |||
| b386be1529 | |||
| a98a61852f | |||
| 3304efd64d | |||
| b97e7d53bc | |||
| 4af6d58d8d | |||
| e2d06eaae5 | |||
| fcfacd9f83 | |||
| bddcc669b3 | |||
| 2024b37e65 | |||
| fb3191904a | |||
| 9e4d74c502 | |||
| 9b221f58b9 | |||
| f7c3b814e3 | |||
| 155bbb8466 | |||
| 4f690eea2a | |||
| 70a1ecba7f | |||
| c8b0ff2fca | |||
| f9a4856c3b | |||
| 35b67a54d2 | |||
| 78a23be9bc | |||
| 09c5958608 | |||
| ffb295971a | |||
| 77bb7e6030 | |||
| 75daf781c2 | |||
| fcead670f0 | |||
| 801b93a078 | |||
| 4beeeb8118 | |||
| 64d4afad9f | |||
| 48f57e3bb2 | |||
| d92f69747b | |||
| 315698b50e | |||
| 6deccf123d | |||
| 391ebc8eda | |||
| 28c7f65a25 | |||
| caebe72083 | |||
| f79baec5ff | |||
| d1c0ea7d74 | |||
| 53e2d7d160 | |||
| 8c62a2f11a | |||
| 8656e30550 | |||
| 0655d73f8e | |||
| 24ebd15f9c | |||
| cce84711c6 | |||
| 7f127300f9 | |||
| 1521094c5b | |||
| 0b8134049c | |||
| 70a980db58 | |||
| 8b960099f1 | |||
| cc53d597c0 | |||
| 5982f732b4 | |||
| c5500b2332 | |||
| de611cb3a9 | |||
| 72a76367f2 | |||
| 5afc3a3a50 | |||
| 2f2ef00d1f | |||
| de7eea4498 | |||
| e9a87de965 | |||
| db7b74feac | |||
| f7d126043b | |||
| 55b44b4f86 | |||
| 523370b6f2 | |||
| 131d2c2051 | |||
| 7f05c2a18c | |||
| 8fc65ab0a5 | |||
| b6108e3b2d | |||
| 26a4aef417 | |||
| 050f2c746d | |||
| fd21e0e69a | |||
| 794580ffcd | |||
| d44bc27c9a | |||
| 243e21a3ea | |||
| 20aaa8841c | |||
| d77ab67c56 | |||
| dd2b6a0fc5 | |||
| f949461297 | |||
| 9a39a25bb5 | |||
| 4b018407c1 | |||
| 28e114b569 | |||
| 99226e0fa6 | |||
| 4a84ee07be | |||
| 505480cf63 | |||
| fa2bfdd326 | |||
| afe022853c | |||
| 41b834f76e | |||
| a88436c806 | |||
| e2d6e709c3 | |||
| bd7fee5a77 | |||
| 709d4ba6e7 | |||
| 8d55c7d60a | |||
| 9cb4de8b5e | |||
| 8662c61a17 | |||
| 935671ae32 | |||
| a5ce965d22 | |||
| 1e58c80fe7 | |||
| a92ae4ba30 | |||
| b5f2e56e38 | |||
| 594f4d56b8 | |||
| 2d83ca61e7 | |||
| 307e37a69f | |||
| 8310eb3b1f | |||
| b9c4f1fa95 | |||
| faab4f9e28 | |||
| 271b0abc45 | |||
| f0c3d50408 | |||
| f0fdff1f07 | |||
| d15df3489e | |||
| f3cc4ab09d | |||
| 442d8a68a6 | |||
| 934fffec68 | |||
| 8190e7838f | |||
| 4571975414 | |||
| 5115c61b03 | |||
| 54c7a9ee95 | |||
| 0296c7c5b6 | |||
| 84d8135cbb | |||
| dd3c370bca | |||
| 4e41f74925 | |||
| c6663f59b8 | |||
| ced7503d95 | |||
| 04af30daed | |||
| 5ccc8e341c | |||
| 71977e8f9d | |||
| 5e774e0b44 | |||
| e16d753439 | |||
| b14d189db9 | |||
| 14de29c031 | |||
| b59455b63c | |||
| 1a6dc86fed | |||
| 35b0c8b577 | |||
| 75034c3710 | |||
| 305cea28c5 | |||
| 69ba85b051 | |||
| 5700d65a53 | |||
| e707c40e0b | |||
| 9d37472f23 | |||
| eb97335c6f | |||
| 0028b29760 | |||
| 1ded1e38e8 | |||
| 149acdae7d | |||
| 5fee5f39ea | |||
| f16d453805 | |||
| 2b0293578f | |||
| 66aeeedaef | |||
| af41dd1ed6 | |||
| 17f7f1fc15 | |||
| cbc512f3be | |||
| 7ac9f92bc2 | |||
| a7ba63d425 | |||
| 5ca10b1d67 | |||
| f22a4a4e80 | |||
| b53ee13662 | |||
| 8de100b116 | |||
| ac30bcb0eb | |||
| 872d6ef55a | |||
| dd3b9c7c35 | |||
| 9755ae3cbe | |||
| bc29fb5a09 | |||
| 646a574b9c | |||
| 8f19650fd7 | |||
| f08980967b | |||
| 5285f5300a | |||
| 1608d0596d | |||
| 62631bfe33 | |||
| 7ffed858f0 | |||
| 3a1334e0d4 | |||
| 37f4f43726 | |||
| db1a84ede1 | |||
| 3d2e4c338c | |||
| b42d731fc8 | |||
| fd7045adac | |||
| e26d3505f7 | |||
| fe0249bf8f | |||
| 2ac682e125 | |||
| 9be1710dca | |||
| 7e7504f5ea | |||
| e83c11667f | |||
| 05547979de | |||
| 9e67ba83a5 | |||
| 2bb3522bbb | |||
| 8f4ec35697 | |||
| 17863dfbda | |||
| 56bb20d489 | |||
| 5baf32cd81 | |||
| 38cd1ecff4 | |||
| 77e00f1926 | |||
| ade139f2d0 | |||
| 653f35a3d8 | |||
| baa7aecf60 | |||
| d859826be6 | |||
| d759c96a98 | |||
| 7cbab0efe3 | |||
| b6b536682e | |||
| edf1df33cc | |||
| bf0df54136 | |||
| 7e80d2de79 | |||
| 144f687ee9 | |||
| 0ee8322947 | |||
| 997fb5fb48 | |||
| 2b459881bd | |||
| e18e7eca47 | |||
| 1c80d2ac2f | |||
| 62918ca779 | |||
| 3cca57a801 | |||
| 5578a2e46d | |||
| fe19cfde28 | |||
| fbad637235 | |||
| 01e9307fb7 | |||
| 5697cb6c95 | |||
| 05ff83f95a | |||
| 1e3012cb49 | |||
| 45b8cf350e | |||
| 2c2c6f8e02 | |||
| 4e3a6b9404 | |||
| 76bbccb4dc | |||
| 1c4433555a | |||
| faaced1d86 | |||
| 1a1d17e13a | |||
| 4254b6d0e2 | |||
| a211c2a955 | |||
| 196200bcc0 | |||
| c062835702 | |||
| 664ef756c2 | |||
| 9de28d640e | |||
| adb9dc7ede | |||
| f9fcd24315 | |||
| 6d95b999ad | |||
| 6731e52280 | |||
| 970358b2af | |||
| 3d68950037 | |||
| d50b2a4804 | |||
| 29a946163b | |||
| 9472025da7 | |||
| f5cd5387da | |||
| 7a8bf8e9a5 | |||
| f5ecdda400 | |||
| c2031aa651 | |||
| 8751c9931e | |||
| adbf9922f4 | |||
| b3a1e5f9e9 | |||
| 22f70f9ac9 | |||
| d2079f32d8 | |||
| f2ac416f66 | |||
| 642fbfba9f | |||
| c98cdd4f4c | |||
| d04567b99c | |||
| f2e1e1b890 | |||
| 6c764f6b8a | |||
| 49929f1e56 | |||
| acdf139137 | |||
| 3346c594e4 | |||
| 0bb2cfe440 | |||
| 11573b4ea4 | |||
| 5934959b62 | |||
| 81f6c22e51 | |||
| 78a8245f4a | |||
| 049861afb4 | |||
| 3df7083f69 | |||
| ca17edd5ac | |||
| c26bf871b7 | |||
| 15d3e8c3e1 | |||
| 66b370e103 | |||
| 2bbfbb1d50 | |||
| ace25d4987 | |||
| 59cb9a4e60 | |||
| 0dce570157 | |||
| 7ddaf49eb2 | |||
| e947363a11 | |||
| 5dbfe48d24 | |||
| 07d5f8b123 | |||
| be99603f1b | |||
| 54db496815 | |||
| fbe7ddb640 | |||
| 55c37d2a57 | |||
| 4b445531f5 | |||
| 12afc263a4 | |||
| 040d131284 | |||
| 73bbe0849a | |||
| 09a0615df0 | |||
| 669d5815c9 | |||
| bd24b97bd3 | |||
| db196ce5d8 | |||
| 4396b211ce | |||
| 367949e914 | |||
| ae2bbe7f19 | |||
| 819e14f91b | |||
| fcf3ccba98 | |||
| 558a10b54f | |||
| 43c60a02f7 | |||
| 6501bc5d32 | |||
| f3dae0c9ad | |||
| dc2cafc888 | |||
| 49fc4923be | |||
| efb5f17a60 | |||
| 086e764845 | |||
| c30290b43c | |||
| d26421fe3b | |||
| 37670924f6 | |||
| ee5143b54b | |||
| acbb2544bf | |||
| d8f7347000 | |||
| 3b91dec462 | |||
| 05f74b4218 | |||
| 8e98177fb3 | |||
| 815a3ad0de | |||
| 5075dd4dfa | |||
| ca09dcbe89 | |||
| 198a74d793 | |||
| fe404628e9 | |||
| 5a004c3b2a | |||
| 430180aa96 | |||
| e828be96f0 | |||
| 52447efb97 | |||
| d09b0fe83a | |||
| 798d8668a4 | |||
| 2a82b8fed9 | |||
| 696f687419 | |||
| 9b91b9db8c | |||
| 026473280b | |||
| a7849b2861 | |||
| 74bf659c56 | |||
| c2feedb7a2 | |||
| 0735e9ba98 | |||
| ab686732d0 | |||
| 6d86437369 | |||
| 184285ab27 | |||
| 1e8065d040 | |||
| f735d12247 | |||
| 7135bc2dc2 | |||
| 9044706796 | |||
| 5f68da3153 | |||
| 5222489a01 | |||
| 27f830f345 | |||
| 8d7db8e450 | |||
| da56758054 | |||
| 66dcc4b6db | |||
| 6eab5622c7 | |||
| af53f3d6cf | |||
| 188e5327ee | |||
| 1932a9d729 | |||
| c926ec477a | |||
| 7b11fa18a1 | |||
| e6cefdca25 | |||
| fbeff475b3 | |||
| d057099c17 | |||
| 411700d7e6 | |||
| b4e9d918f2 | |||
| 2756c364d2 | |||
| 43faabd4cc | |||
| a4a71a8904 | |||
| e23ac031ff | |||
| 79a56967a1 | |||
| 0bc0453700 | |||
| 35e247aa26 | |||
| 67ba187b6f | |||
| 67f0b1986c | |||
| 60e0177d00 | |||
| 4543a28e51 | |||
| aade2d1ec9 | |||
| 4627545a3b | |||
| e2ba7c9b8c | |||
| 6f5596ac5c | |||
| 7d1c2f191a | |||
| 4ada571384 | |||
| ad8ebbaa05 | |||
| 4854989db4 | |||
| 7c5050cf80 | |||
| 14ae8be547 | |||
| ff878ea9dc | |||
| 7021a4be44 | |||
| 5c4737c3d0 | |||
| fbf3807af1 | |||
| 703c37ec88 | |||
| 96440878bb | |||
| b5c11ffb1c | |||
| 7f5b323d50 | |||
| 67176e2b75 | |||
| 79f3cf3263 | |||
| 9ee1dc79fd | |||
| 9e2c34dfa6 | |||
| cc93c2a559 | |||
| 15c7044c4d | |||
| 0ef80d3579 | |||
| 95c2e0a996 | |||
| da3e8611e1 | |||
| 64595597f3 | |||
| 82f2983cd4 | |||
| 9451177c35 | |||
| 9ed087d5da | |||
| 77f22e9674 | |||
| 8ccfdbbcf9 | |||
| 5a92aa4e06 | |||
| 7b1010cf61 | |||
| 45b2f5bac4 | |||
| 36e1c82ef5 | |||
| 503d65d570 | |||
| fe17f8da41 | |||
| b583aa1579 | |||
| e0d81b97bb | |||
| 90752f9d87 | |||
| 3663aa675a | |||
| 1ca4b81856 | |||
| 4e7e06f549 | |||
| b2f0bdb0f4 | |||
| d98bd34200 | |||
| 940bdd878e | |||
| df556333a8 | |||
| 116f05eda6 | |||
| b187bbeca3 | |||
| 479a83b628 | |||
| 1c18100143 | |||
| 5d3c0f33f6 | |||
| afe106e254 | |||
| 69dd40ec89 | |||
| dee50d5e28 | |||
| 9e93403857 | |||
| 12bff6b3a0 | |||
| 70e666b4a3 | |||
| 29f980ec72 | |||
| 1d39d762f0 | |||
| 4d6d5e0ddd | |||
| 4ea5f070a4 | |||
| da59b4da9b | |||
| 0065a160cc | |||
| 52f46c7fea | |||
| f0a826ec0c | |||
| 5c3c0f73c1 | |||
| be0b71ce31 | |||
| f85d48dd31 | |||
| a1b58ee601 | |||
| e30429051d | |||
| 942ead75e2 | |||
| 453688f6df | |||
| 7d7a161102 | |||
| aaa223ae66 | |||
| d11c624fb0 | |||
| 275e51b19d | |||
| ab62edeeaa | |||
| 813108a928 | |||
| 3c14911401 | |||
| 4337f14627 | |||
| 92d78c10a2 | |||
| 16d5ba9b3a | |||
| 52065a736b | |||
| 11cb109114 | |||
| d7eadd41d6 |
@@ -1,10 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*.{adoc,bat,groovy,html,java,js,jsp,kt,kts,md,properties,py,rb,sh,sql,svg,txt,xml,xsd}]
|
||||
charset = utf-8
|
||||
|
||||
[*.{groovy,java,kt,kts,xml,xsd}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
continuation_indent_size = 8
|
||||
end_of_line = lf
|
||||
@@ -17,7 +17,6 @@ argfile*
|
||||
pom.xml
|
||||
activemq-data/
|
||||
|
||||
classes/
|
||||
/build
|
||||
buildSrc/build
|
||||
/spring-*/build
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#com.springsource.sts.gradle.core.preferences.GradleImportPreferences
|
||||
#Thu Aug 9 11:34:43 CEST 2012
|
||||
enableAfterTasks=true
|
||||
afterTasks=afterEclipseImport;
|
||||
enableDependendencyManagement=false
|
||||
enableBeforeTasks=true
|
||||
projects=;spring-aop;spring-aspects;spring-beans;spring-context;spring-context-support;spring-core;spring-expression;spring-instrument;spring-instrument-tomcat;spring-jdbc;spring-jms;spring-orm;spring-oxm;spring-struts;spring-test;spring-tx;spring-web;spring-webmvc;spring-webmvc-portlet;
|
||||
enableDSLD=false
|
||||
beforeTasks=cleanEclipse;eclipse;\:spring-oxm\:compileTestJava;
|
||||
@@ -0,0 +1,5 @@
|
||||
#com.springsource.sts.gradle.core.preferences.GradleProjectPreferences
|
||||
#Tue Feb 21 14:38:31 CET 2012
|
||||
com.springsource.sts.gradle.classpath.enableSorting=false
|
||||
com.springsource.sts.gradle.rootprojectloc=
|
||||
com.springsource.sts.gradle.linkedresources=
|
||||
@@ -0,0 +1,9 @@
|
||||
#com.springsource.sts.gradle.core.actions.GradleRefreshPreferences
|
||||
#Thu Aug 9 11:34:43 CEST 2012
|
||||
enableAfterTasks=true
|
||||
afterTasks=afterEclipseImport;
|
||||
useHierarchicalNames=false
|
||||
enableBeforeTasks=true
|
||||
addResourceFilters=false
|
||||
enableDSLD=false
|
||||
beforeTasks=cleanEclipse;eclipse;\:spring-oxm\:compileTestJava;
|
||||
@@ -0,0 +1,51 @@
|
||||
= How to contribute to the reference
|
||||
|
||||
The Spring Framework reference now uses http://asciidoctor.org/[asciidoctor]. This
|
||||
document describes how to contribute documentation updates.
|
||||
|
||||
== Building with Gradle
|
||||
|
||||
You can build the documentation using gradle using the `reference` task. For example, from
|
||||
the project root execute the following command:
|
||||
|
||||
./gradlew reference
|
||||
|
||||
the output will be available at `spring-framework/build/reference/htmlsingle/index.html`
|
||||
|
||||
== Live editing
|
||||
|
||||
One of the nice features about using asciidoctor is the support for live editing.
|
||||
|
||||
You will find a Guardfile already present at `spring-framework/src/asciidoc/Guardfile`.
|
||||
Make sure first to follow the setup instructions within the
|
||||
http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/[Editing AsciiDoc with Live Preview]
|
||||
document. Once you have done that, there are additional gems to install to make it work
|
||||
(assuming that you are using http://livereload.com/[LiveReload]):
|
||||
|
||||
gem install guard-rspec guard-livereload
|
||||
|
||||
When running `guard start` within the `src/asciidoc/` folder, any changes to the
|
||||
`src/asciidoc/index.adoc` file will automatically be written at
|
||||
`src/asciidoc/build/index.html`.
|
||||
|
||||
== Troubleshooting
|
||||
|
||||
* If you are using LiveReload, make sure to select _Allow access to file URLs_ in the
|
||||
LiveEdit plugin options of your browser.
|
||||
* The icon used to enable _LiveReload_ can be a bit confusing. The dot is empty when it is
|
||||
disabled and full when the plugin is active. Make sure to enable it on the tab
|
||||
displaying the `index.html` file.
|
||||
* Ensure you are _not_ running guard start at all as two instances could not run at the
|
||||
same time. To exit a current session in a clean way, just type e in the shell.
|
||||
|
||||
== Documentation notes
|
||||
|
||||
Some notes on documentation
|
||||
|
||||
* Documentation is wrapped at 90 chars, ensure that you manually wrap your edits
|
||||
* Tabs are used for indentation, do not use spaces
|
||||
* Follow the existing style when inserting `source` blocks
|
||||
* http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[Asciidoctor Quick Reference]
|
||||
* http://asciidoctor.org/docs/user-manual/[Asciidoctor Manual]
|
||||
* http://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoctor Writers Guide]
|
||||
|
||||
+283
-92
@@ -1,128 +1,319 @@
|
||||
# Contributing to the Spring Framework
|
||||
_Have something you'd like to contribute to the framework? We welcome pull
|
||||
requests but ask that you carefully read this document first to understand how
|
||||
best to submit them; what kind of changes are likely to be accepted; and what
|
||||
to expect from the Spring team when evaluating your submission._
|
||||
|
||||
First off, thank you for taking the time to contribute! :+1: :tada:
|
||||
_Please refer back to this document as a checklist before issuing any pull
|
||||
request; this will save time for everyone!_
|
||||
|
||||
### Table of Contents
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
* [Code of Conduct](#code-of-conduct)
|
||||
* [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)
|
||||
* [Reference Docs](#reference-docs)
|
||||
## Take Your First Steps
|
||||
|
||||
### Code of Conduct
|
||||
### Understand the basics
|
||||
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating you are expected to uphold this code.
|
||||
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
excellent [help documentation][] first.
|
||||
|
||||
### How to Contribute
|
||||
### Search Stack Overflow first; discuss if necessary
|
||||
|
||||
#### Discuss
|
||||
If you're unsure why something isn't working or wondering if there is a better
|
||||
way of doing it please check on Stack Overflow first and if necessary start
|
||||
a discussion. This is the official list of
|
||||
[Spring project tags](https://spring.io/questions). In short the issue tracker
|
||||
should be used to report issues and make feature requests.
|
||||
|
||||
If you have a question, check StackOverflow using
|
||||
[this list of tags](https://spring.io/questions), organized by Spring project.
|
||||
Find an existing discussion or start a new one if necessary.
|
||||
### Search JIRA; create an issue if necessary
|
||||
|
||||
If you suspect an issue, perform a search in the
|
||||
[JIRA issue tracker](https://jira.spring.io/browse/SPR), using a few different keywords.
|
||||
When you find related issues and discussions, prior or current, it helps you to learn and
|
||||
it helps us to make a decision.
|
||||
Is there already an issue that addresses your concern? Do a bit of searching
|
||||
in our [JIRA issue tracker][] to see if you can find something similar. If you
|
||||
do not find something similar, please create a new JIRA issue before submitting
|
||||
a pull request unless the change is truly trivial -- for example: typo fixes,
|
||||
removing compiler warnings, etc.
|
||||
|
||||
#### Create a Ticket
|
||||
### Sign the Individual Contributor License Agreement (ICLA)
|
||||
|
||||
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.
|
||||
If you have not previously done so, please fill out and submit the
|
||||
[Spring ICLA form][]. You'll receive a token when this process is complete.
|
||||
Keep track of this; you may be asked for it later!
|
||||
|
||||
Before you create a ticket, please take the time to [research first](#discuss).
|
||||
Note that emailing/postal mailing a signed copy is _not_ necessary. Submission
|
||||
of the web form is all that is required.
|
||||
|
||||
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.
|
||||
Once you've completed the web form, simply add the following in a comment on
|
||||
your pull request:
|
||||
|
||||
When ready create a ticket in the [JIRA issue tracker](https://jira.spring.io/browse/SPR).
|
||||
I have signed and agree to the terms of the Spring Individual Contributor
|
||||
License Agreement.
|
||||
|
||||
#### Ticket Lifecycle
|
||||
You do not need to include your token/id. Please add the above statement to all
|
||||
future pull requests as well, simply so that the Spring Framework team knows
|
||||
immediately that this process is complete.
|
||||
|
||||
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
|
||||
version is set to "Waiting for Triage". The committer will then review the issue, ask for
|
||||
further information if needed, and based on the findings, the issue is either assigned a fix
|
||||
version or rejected.
|
||||
## Create a Branch
|
||||
|
||||
When a fix is ready, the issue is marked "Resolved" and may still be re-opened. Once a fix
|
||||
is released, the issue is permanently "Closed". If necessary, you will need to create a new,
|
||||
related ticket with a fresh description.
|
||||
### Branch from `master`
|
||||
|
||||
#### Submit a Pull Request
|
||||
Master currently represents work toward Spring Framework 4.0. Please submit
|
||||
all pull requests there, even bug fixes and minor improvements. Backports to
|
||||
`3.2.x` will be considered on a case-by-case basis.
|
||||
|
||||
You can contribute a source code change by submitting a pull request.
|
||||
|
||||
1. If you have not previously done so, please sign the
|
||||
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
|
||||
automatically when you submit a pull request.
|
||||
### Use short branch names
|
||||
|
||||
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
|
||||
oriented and transient in nature.
|
||||
Branches used when submitting pull requests should preferably be named
|
||||
according to JIRA issues, e.g. 'SPR-1234'. Otherwise, use succinct, lower-case,
|
||||
dash (-) delimited names, such as 'fix-warnings', 'fix-typo', etc. In
|
||||
[fork-and-edit][] cases, the GitHub default 'patch-1' is fine as well. This is
|
||||
important, because branch names show up in the merge commits that result from
|
||||
accepting pull requests and should be as expressive and concise as possible.
|
||||
|
||||
1. Always check out the `master` branch and submit pull requests against it
|
||||
(for target version see [settings.gradle](settings.gradle)).
|
||||
Backports to prior versions will be considered on a case-by-case basis and reflected as
|
||||
the fix version in the issue tracker.
|
||||
## Use Spring Framework Code Style
|
||||
|
||||
1. Use short branch names, preferably based on the JIRA issue (e.g. `SPR-1234`), or
|
||||
otherwise using succinct, lower-case, dash (-) delimited names, such as `fix-warnings'.
|
||||
The complete [Spring Framework Code Style][] reference is available on the wiki, but
|
||||
here's a quick summary:
|
||||
|
||||
1. Choose the granularity of your commits consciously and squash commits that represent
|
||||
multiple edits or corrections of the same logical change. See
|
||||
[Rewriting History section of Pro Git](http://git-scm.com/book/en/Git-Tools-Rewriting-History)
|
||||
for an overview of streamlining commit history.
|
||||
### Mind the whitespace
|
||||
|
||||
1. Format commit messages using 55 characters for the subject line, 72 lines for the
|
||||
description, followed by related issues, e.g. `Issues: SPR-1234, SPR-1235`.
|
||||
See the
|
||||
[Commit Guidelines section of Pro Git](http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
|
||||
for best practices around commit messages and use `git log` to see some examples.
|
||||
Please carefully follow the whitespace and formatting conventions already
|
||||
present in the framework.
|
||||
|
||||
1. List the JIRA issue number in the PR description.
|
||||
1. Tabs, not spaces
|
||||
1. Unix (LF), not DOS (CRLF) line endings
|
||||
1. Eliminate all trailing whitespace
|
||||
1. Wrap Javadoc at 90 characters
|
||||
1. Aim to wrap code at 90 characters, but favor readability over wrapping
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. UTF-8 encoding for Java sources
|
||||
|
||||
If accepted, your contribution may be heavily modified as needed prior to merging.
|
||||
You will likely retain author attribution for your Git commits granted that the bulk of
|
||||
your changes remain intact. You may also be asked to rework the submission.
|
||||
|
||||
If asked to make corrections, simply push the changes against the same branch, and your
|
||||
pull request will be updated. In other words, you do not need to create a new pull request
|
||||
when asked to make changes.
|
||||
### Add Apache license header to all new classes
|
||||
|
||||
### Build from Source
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
|
||||
wiki page for instructions on how to check out, build, and import the Spring Framework
|
||||
source code into your IDE.
|
||||
package ...;
|
||||
```
|
||||
|
||||
### Source Code Style
|
||||
### Update Apache license header in modified files as necessary
|
||||
|
||||
The wiki pages
|
||||
[Code Style](https://github.com/spring-projects/spring-framework/wiki/Code-Style) and
|
||||
[IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings)
|
||||
defines the source file coding standards we use along with some IDEA editor settings we customize.
|
||||
Always check the date range in the license header. For example, if you've
|
||||
modified a file in 2015 whose header still reads:
|
||||
|
||||
### Reference Docs
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
The reference documentation is in the [src/docs/asciidoc](src/docs/asciidoc) directory and, in
|
||||
[Asciidoctor](http://asciidoctor.org/) format. For trivial changes, you may be able to browse,
|
||||
edit source files, and submit directly from Github.
|
||||
Then be sure to update it to 2016 accordingly:
|
||||
|
||||
When making changes locally, use `./gradlew asciidoctor` and then browse the result under
|
||||
`build/asciidoc/html5/index.html`.
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
```
|
||||
|
||||
Asciidoctor also supports live editing. For more details read
|
||||
[Editing AsciiDoc with Live Preview](http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/).
|
||||
Note that if you choose the
|
||||
[System Monitor](http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/#using-a-system-monitor)
|
||||
option, you can find a Guardfile under `src/docs/asciidoc`.
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
|
||||
For example:
|
||||
|
||||
```java
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @author First Last
|
||||
* @since 4.2.3
|
||||
* @see ...
|
||||
*/
|
||||
```
|
||||
|
||||
## Prepare Your Commit
|
||||
|
||||
### Submit JUnit test cases for all behavior changes
|
||||
|
||||
Search the codebase to find related tests and add additional `@Test` methods
|
||||
as appropriate. It is also acceptable to submit test cases on a per JIRA issue
|
||||
basis, for example:
|
||||
|
||||
```java
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
/**
|
||||
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
|
||||
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
|
||||
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
|
||||
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
|
||||
* that not only the predicted bean type is considered, but also the original bean
|
||||
* definition's beanClass.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class Spr8954Tests {
|
||||
|
||||
@Test
|
||||
public void cornerSpr8954() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Squash commits
|
||||
|
||||
Use `git rebase --interactive --autosquash`, `git add --patch`, and other tools
|
||||
to "squash" multiple commits into a single atomic commit. In addition to the man
|
||||
pages for git, there are many resources online to help you understand how these
|
||||
tools work. The [Rewriting History section of Pro Git][] provides a good overview.
|
||||
|
||||
|
||||
### Use real name in git commits
|
||||
|
||||
Please configure git to use your real first and last name for any commits you
|
||||
intend to submit as pull requests. For example, this is not acceptable:
|
||||
|
||||
Author: Nickname <user@mail.com>
|
||||
|
||||
Rather, please include your first and last name, properly capitalized, as
|
||||
submitted against the Spring Individual Contributor License Agreement (ICLA):
|
||||
|
||||
Author: First Last <user@mail.com>
|
||||
|
||||
This helps ensure traceability against the ICLA and also goes a long way to
|
||||
ensuring useful output from tools like `git shortlog` and others.
|
||||
|
||||
You can configure this via the account admin area in GitHub (useful for
|
||||
fork-and-edit cases); _globally_ on your machine with
|
||||
|
||||
git config --global user.name "First Last"
|
||||
git config --global user.email user@mail.com
|
||||
|
||||
or _locally_ for the `spring-framework` repository only by omitting the
|
||||
'--global' flag:
|
||||
|
||||
cd spring-framework
|
||||
git config user.name "First Last"
|
||||
git config user.email user@mail.com
|
||||
|
||||
|
||||
### Format commit messages
|
||||
|
||||
Please read and follow the [Commit Guidelines section of Pro Git][].
|
||||
|
||||
Most importantly, please format your commit messages in the following way
|
||||
(adapted from the commit template in the link above):
|
||||
|
||||
Short (50 chars or less) summary of changes
|
||||
|
||||
More detailed explanatory text, if necessary. Wrap it to about 72
|
||||
characters or so. In some contexts, the first line is treated as the
|
||||
subject of an email and the rest of the text as the body. The blank
|
||||
line separating the summary from the body is critical (unless you omit
|
||||
the body entirely); tools like rebase can get confused if you run the
|
||||
two together.
|
||||
|
||||
Further paragraphs come after blank lines.
|
||||
|
||||
- Bullet points are okay, too
|
||||
|
||||
- Typically a hyphen or asterisk is used for the bullet, preceded by a
|
||||
single space, with blank lines in between, but conventions vary here
|
||||
|
||||
Issue: SPR-1234, SPR-1235
|
||||
|
||||
|
||||
1. Use imperative statements in the subject line, e.g. "Fix broken Javadoc link".
|
||||
1. Begin the subject line with a capitalized verb, e.g. "Add, Prune, Fix,
|
||||
Introduce, Avoid, etc."
|
||||
1. Do not end the subject line with a period.
|
||||
1. Restrict the subject line to 50 characters or less if possible.
|
||||
1. Wrap lines in the body at 72 characters or less.
|
||||
1. Mention associated JIRA issue(s) at the end of the commit comment, prefixed
|
||||
with "Issue: " as above.
|
||||
1. In the body of the commit message, explain how things worked before this
|
||||
commit, what has changed, and how things work now.
|
||||
|
||||
For examples of this style, issue a `git log --author=cbeams` in the
|
||||
`spring-framework` git repository. For convenience, here are several such commits:
|
||||
|
||||
- https://github.com/spring-projects/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
|
||||
- https://github.com/spring-projects/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
|
||||
- https://github.com/spring-projects/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
|
||||
- https://github.com/spring-projects/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
|
||||
|
||||
## Run the Final Checklist
|
||||
|
||||
### Run all tests prior to submission
|
||||
|
||||
See the [building from source][] section of the `README` for instructions. Make
|
||||
sure that all tests pass prior to submitting your pull request.
|
||||
|
||||
|
||||
### Submit your pull request
|
||||
|
||||
Subject line:
|
||||
|
||||
Follow the same conventions for pull request subject lines as mentioned above
|
||||
for commit message subject lines.
|
||||
|
||||
In the body:
|
||||
|
||||
1. Explain your use case. What led you to submit this change? Why were existing
|
||||
mechanisms in the framework insufficient? Make a case that this is a
|
||||
general-purpose problem and that yours is a general-purpose solution, etc.
|
||||
1. Add any additional information and ask questions; start a conversation or
|
||||
continue one from JIRA.
|
||||
1. Mention the JIRA issue ID.
|
||||
1. Also mention that you have submitted the ICLA as described above.
|
||||
|
||||
Note that for pull requests containing a single commit, GitHub will default the
|
||||
subject line and body of the pull request to match the subject line and body of
|
||||
the commit message. This is fine, but please also include the items above in the
|
||||
body of the request.
|
||||
|
||||
|
||||
### Mention your pull request on the associated JIRA issue
|
||||
|
||||
Add a comment to the associated JIRA issue(s) linking to your new pull request.
|
||||
|
||||
|
||||
### Expect discussion and rework
|
||||
|
||||
The Spring team takes a very conservative approach to accepting contributions to
|
||||
the framework. This is to keep code quality and stability as high as possible,
|
||||
and to keep complexity at a minimum. Your changes, if accepted, may be heavily
|
||||
modified prior to merging. You will retain "Author:" attribution for your Git
|
||||
commits granted that the bulk of your changes remain intact. You may be asked to
|
||||
rework the submission for style (as explained above) and/or substance. Again, we
|
||||
strongly recommend discussing any serious submissions with the Spring Framework
|
||||
team _prior_ to engaging in serious development work.
|
||||
|
||||
Note that you can always force push (`git push -f`) reworked / rebased commits
|
||||
against the branch used to submit your pull request. In other words, you do not
|
||||
need to issue a new pull request when asked to make changes.
|
||||
|
||||
[help documentation]: http://help.github.com/send-pull-requests
|
||||
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
|
||||
[spring-framework-contrib]: https://groups.google.com/forum/#!forum/spring-framework-contrib
|
||||
[Spring ICLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
|
||||
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
|
||||
[Rewriting History section of Pro Git]: http://git-scm.com/book/en/Git-Tools-Rewriting-History
|
||||
[Commit Guidelines section of Pro Git]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines
|
||||
[building from source]: https://github.com/spring-projects/spring-framework#building-from-source
|
||||
|
||||
@@ -1,48 +1,102 @@
|
||||
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework
|
||||
## Spring Framework
|
||||
The Spring Framework provides a comprehensive programming and configuration
|
||||
model for modern Java-based enterprise applications -- on any kind of deployment
|
||||
platform. A key element of Spring is infrastructural support at the application
|
||||
level: Spring focuses on the "plumbing" of enterprise applications so that teams
|
||||
can focus on application-level business logic, without unnecessary ties to
|
||||
specific deployment environments.
|
||||
|
||||
This is the home of the Spring Framework, the foundation for all
|
||||
[Spring projects](https://spring.io/projects). Together the Spring Framework and the family of Spring projects make up what we call "Spring".
|
||||
|
||||
Spring provides everything you need beyond the Java language to create enterprise
|
||||
applications in a wide range of scenarios and architectures. Please read the
|
||||
[Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction)
|
||||
section in the reference for a more complete introduction.
|
||||
The framework also serves as the foundation for [Spring Integration][], [Spring Batch][]
|
||||
and the rest of the Spring [family of projects][]. Browse the repositories under
|
||||
the [Spring organization][] on GitHub for a full list.
|
||||
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating you are expected to uphold this code.
|
||||
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Access to Binaries
|
||||
|
||||
For access to artifacts or a distribution zip, see the
|
||||
[Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts)
|
||||
wiki page.
|
||||
## Downloading Artifacts
|
||||
See [downloading Spring artifacts][] for Maven repository information. Unable to
|
||||
use Maven or other transitive dependency management tools?
|
||||
See [building a distribution with dependencies][].
|
||||
|
||||
## Documentation
|
||||
See the current [Javadoc][] and [reference docs][].
|
||||
|
||||
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.
|
||||
## Getting Support
|
||||
Check out the [spring][spring tags] tags on [Stack Overflow][]. [Commercial support][]
|
||||
is available too.
|
||||
|
||||
## Build from Source
|
||||
## Issue Tracking
|
||||
Report issues via the [Spring Framework JIRA][]. Understand our issue management
|
||||
process by reading about [the lifecycle of an issue][]. Think you've found a
|
||||
bug? Please consider submitting a reproduction project via the
|
||||
[spring-framework-issues][] GitHub repository. The [readme][] there provides
|
||||
simple step-by-step instructions.
|
||||
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
|
||||
wiki page and also [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
## Building from Source
|
||||
The Spring Framework uses a [Gradle][]-based build system. In the instructions
|
||||
below, [`./gradlew`][] is invoked from the root of the source tree and serves as
|
||||
a cross-platform, self-contained bootstrap mechanism for the build.
|
||||
|
||||
## Stay in Touch
|
||||
### Prerequisites
|
||||
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral),
|
||||
[@SpringFramework](https://twitter.com/springframework), and its
|
||||
[team members](https://twitter.com/springframework/lists/team/members) on Twitter.
|
||||
In-depth articles can be found at [The Spring Blog](http://spring.io/blog/),
|
||||
and releases are announced via our [news feed](http://spring.io/blog/category/news).
|
||||
[Git][] and [JDK 8 update 20 or later][JDK8 build]
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder
|
||||
extracted from the JDK download.
|
||||
|
||||
### Check out sources
|
||||
`git clone git@github.com:spring-projects/spring-framework.git`
|
||||
|
||||
### Import sources into your IDE
|
||||
Run `./import-into-eclipse.sh` or read `import-into-idea.md` as appropriate.
|
||||
> **Note:** Per the prerequisites above, ensure that you have JDK 8 configured properly in your IDE.
|
||||
|
||||
### Install all spring-\* jars into your local Maven cache
|
||||
`./gradlew install`
|
||||
|
||||
### Compile and test; build all jars, distribution zips, and docs
|
||||
`./gradlew build`
|
||||
|
||||
... and discover more commands with `./gradlew tasks`. See also the [Gradle
|
||||
build and release FAQ][].
|
||||
|
||||
## Contributing
|
||||
[Pull requests][] are welcome; see the [contributor guidelines][] for details.
|
||||
|
||||
## Staying in Touch
|
||||
Follow [@SpringCentral][] as well as [@SpringFramework][] and its [team members][]
|
||||
on Twitter. In-depth articles can be found at [The Spring Blog][], and releases
|
||||
are announced via our [news feed][].
|
||||
|
||||
## License
|
||||
The Spring Framework is released under version 2.0 of the [Apache License][].
|
||||
|
||||
The Spring Framework is released under version 2.0 of the
|
||||
[Apache License](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
[Spring Integration]: https://github.com/spring-projects/spring-integration
|
||||
[Spring Batch]: https://github.com/spring-projects/spring-batch
|
||||
[family of projects]: http://spring.io/projects
|
||||
[Spring organization]: https://github.com/spring-projects
|
||||
[downloading Spring artifacts]: https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts
|
||||
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
|
||||
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
|
||||
[spring tags]: http://spring.io/questions
|
||||
[Stack Overflow]: http://stackoverflow.com/faq
|
||||
[Commercial support]: http://spring.io/services
|
||||
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
|
||||
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[Gradle]: http://gradle.org
|
||||
[`./gradlew`]: http://vimeo.com/34436402
|
||||
[Git]: http://help.github.com/set-up-git-redirect
|
||||
[JDK8 build]: http://www.oracle.com/technetwork/java/javase/downloads
|
||||
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Pull requests]: http://help.github.com/send-pull-requests
|
||||
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@SpringFramework]: https://twitter.com/springframework
|
||||
[@SpringCentral]: https://twitter.com/springcentral
|
||||
[team members]: https://twitter.com/springframework/lists/team/members
|
||||
[The Spring Blog]: http://spring.io/blog/
|
||||
[news feed]: http://spring.io/blog/category/news
|
||||
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
+1238
-141
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
description = "Exposes gradle buildSrc for IDE support"
|
||||
|
||||
apply plugin: "groovy"
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
}
|
||||
|
||||
configurations.archives.artifacts.clear()
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.gradle
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that detects identically named, non-empty packages split across multiple
|
||||
* subprojects, e.g. "org.springframework.context.annotation" existing in both spring-core
|
||||
* and spring-aspects. Adds a 'detectSplitPackages' task to the current project's task
|
||||
* collection. If the project already contains a 'check' task (i.e. is a typical Gradle
|
||||
* project with the "java" plugin applied), the 'check' task will be updated to depend on
|
||||
* the execution of 'detectSplitPackages'.
|
||||
*
|
||||
* By default, all subprojects will be scanned. Use the 'projectsToScan' task property to
|
||||
* modify this value. Example usage:
|
||||
*
|
||||
* apply plugin: 'detect-split-packages // typically applied to root project
|
||||
*
|
||||
* detectSplitPackages {
|
||||
* packagesToScan -= project(":spring-xyz") // scan every project but spring-xyz
|
||||
* }
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Glyn Normington
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class DetectSplitPackagesPlugin implements Plugin<Project> {
|
||||
public void apply(Project project) {
|
||||
def tasks = project.tasks
|
||||
Task detectSplitPackages = tasks.create("detectSplitPackages", DetectSplitPackagesTask.class)
|
||||
if (tasks.asMap.containsKey("check")) {
|
||||
tasks.getByName("check").dependsOn detectSplitPackages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DetectSplitPackagesTask extends DefaultTask {
|
||||
|
||||
private static final String JAVA_FILE_SUFFIX = ".java"
|
||||
private static final String PACKAGE_SEPARATOR = "."
|
||||
private static final String HIDDEN_DIRECTORY_PREFIX = "."
|
||||
|
||||
@Input
|
||||
Set<Project> projectsToScan = project.subprojects
|
||||
|
||||
public DetectSplitPackagesTask() {
|
||||
this.group = "Verification"
|
||||
this.description = "Detects packages split across two or more subprojects."
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void detectSplitPackages() {
|
||||
def splitPackages = doDetectSplitPackages()
|
||||
if (!splitPackages.isEmpty()) {
|
||||
def message = "The following split package(s) have been detected:\n"
|
||||
splitPackages.each { pkg, mod ->
|
||||
message += " - ${pkg} (split across ${mod[0].name} and ${mod[1].name})\n"
|
||||
}
|
||||
throw new GradleException(message)
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<Project>> doDetectSplitPackages() {
|
||||
def splitPackages = [:]
|
||||
def mergedProjects = findMergedProjects()
|
||||
def packagesByProject = mapPackagesByProject()
|
||||
|
||||
def projects = packagesByProject.keySet().toArray()
|
||||
def nProjects = projects.length
|
||||
|
||||
for (int i = 0; i < nProjects - 1; i++) {
|
||||
for (int j = i + 1; j < nProjects - 1; j++) {
|
||||
def prj_i = projects[i]
|
||||
def prj_j = projects[j]
|
||||
|
||||
def pkgs_i = new HashSet(packagesByProject.get(prj_i))
|
||||
def pkgs_j = packagesByProject.get(prj_j)
|
||||
pkgs_i.retainAll(pkgs_j)
|
||||
|
||||
if (!pkgs_i.isEmpty()
|
||||
&& mergedProjects.get(prj_i) != prj_j
|
||||
&& mergedProjects.get(prj_j) != prj_i) {
|
||||
pkgs_i.each { pkg ->
|
||||
def readablePkg = pkg.substring(1).replaceAll(File.separator, PACKAGE_SEPARATOR)
|
||||
splitPackages[readablePkg] = [prj_i, prj_j]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return splitPackages;
|
||||
}
|
||||
|
||||
private Map<Project, Set<String>> mapPackagesByProject() {
|
||||
def packagesByProject = [:]
|
||||
this.projectsToScan.each { Project p ->
|
||||
def packages = new HashSet<String>()
|
||||
p.sourceSets.main.java.srcDirs.each { File dir ->
|
||||
findPackages(packages, dir, "")
|
||||
}
|
||||
if (!packages.isEmpty()) {
|
||||
packagesByProject.put(p, packages)
|
||||
}
|
||||
}
|
||||
return packagesByProject;
|
||||
}
|
||||
|
||||
private Map<Project, Project> findMergedProjects() {
|
||||
def mergedProjects = [:]
|
||||
this.projectsToScan.findAll { p ->
|
||||
p.plugins.findPlugin(MergePlugin)
|
||||
}.findAll { p ->
|
||||
p.merge.into
|
||||
}.each { p ->
|
||||
mergedProjects.put(p, p.merge.into)
|
||||
}
|
||||
return mergedProjects
|
||||
}
|
||||
|
||||
private static void findPackages(Set<String> packages, File dir, String packagePath) {
|
||||
def scanDir = new File(dir, packagePath)
|
||||
def File[] javaFiles = scanDir.listFiles({ file ->
|
||||
!file.isDirectory() && file.name.endsWith(JAVA_FILE_SUFFIX)
|
||||
} as FileFilter)
|
||||
|
||||
if (javaFiles != null && javaFiles.length != 0) {
|
||||
packages.add(packagePath)
|
||||
}
|
||||
|
||||
scanDir.listFiles({ File file ->
|
||||
file.isDirectory() && !file.name.startsWith(HIDDEN_DIRECTORY_PREFIX)
|
||||
} as FileFilter).each { File subDir ->
|
||||
findPackages(packages, dir, packagePath + File.separator + subDir.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.gradle
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
|
||||
import org.gradle.api.plugins.MavenPlugin
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
import org.gradle.api.invocation.*
|
||||
|
||||
/**
|
||||
* Gradle plugin that allows projects to merged together. Primarily developed to
|
||||
* allow Spring to support multiple incompatible versions of third-party
|
||||
* dependencies (for example Hibernate v3 and v4).
|
||||
* <p>
|
||||
* The 'merge' extension should be used to define how projects are merged, for example:
|
||||
* <pre class="code">
|
||||
* configure(subprojects) {
|
||||
* apply plugin: MergePlugin
|
||||
* }
|
||||
*
|
||||
* project("myproject") {
|
||||
* }
|
||||
*
|
||||
* project("myproject-extra") {
|
||||
* merge.into = project("myproject")
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* This plugin adds two new configurations:
|
||||
* <ul>
|
||||
* <li>merging - Contains the projects being merged into this project<li>
|
||||
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
|
||||
* to allow an IDE to reference merge projects.</li>
|
||||
* <ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MergePlugin implements Plugin<Project> {
|
||||
|
||||
private static boolean attachedProjectsEvaluated;
|
||||
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(MavenPlugin)
|
||||
project.plugins.apply(EclipsePlugin)
|
||||
project.plugins.apply(IdeaPlugin)
|
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel)
|
||||
project.configurations.create("merging")
|
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
|
||||
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
if (it.merge.into != null) {
|
||||
setup(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to build runtimeMerge dependencies
|
||||
if (!attachedProjectsEvaluated) {
|
||||
project.gradle.projectsEvaluated{
|
||||
postProcessProjects(it)
|
||||
}
|
||||
attachedProjectsEvaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(Project project) {
|
||||
project.merge.into.dependencies.add("merging", project)
|
||||
project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
|
||||
project.dependencies.add("runtimeMerge", project.merge.into)
|
||||
setupTaskDependencies(project)
|
||||
setupMaven(project)
|
||||
}
|
||||
|
||||
private void setupTaskDependencies(Project project) {
|
||||
// invoking a task will invoke the task with the same name on 'into' project
|
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
|
||||
def task = project.tasks.findByPath(it)
|
||||
if (task) {
|
||||
task.enabled = false
|
||||
task.dependsOn(project.merge.into.tasks.findByPath(it))
|
||||
}
|
||||
}
|
||||
|
||||
// update 'into' project artifacts to contain the source artifact contents
|
||||
project.merge.into.sourcesJar.from(project.sourcesJar.source)
|
||||
project.merge.into.jar.from(project.sourceSets.main.output)
|
||||
project.merge.into.javadoc {
|
||||
source += project.javadoc.source
|
||||
classpath += project.javadoc.classpath
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMaven(Project project) {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if (mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.create(
|
||||
project.name + "-" + configuration.name)
|
||||
configuration.excludeRules.each {
|
||||
configuration.exclude([
|
||||
(ExcludeRule.GROUP_KEY) : it.group,
|
||||
(ExcludeRule.MODULE_KEY) : it.module])
|
||||
}
|
||||
configuration.dependencies.each {
|
||||
def intoCompile = project.merge.into.configurations.getByName("compile")
|
||||
// Protect against changing a compile scope dependency (SPR-10218)
|
||||
if (!intoCompile.dependencies.contains(it)) {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100 + index, intoConfiguration, mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private postProcessProjects(Gradle gradle) {
|
||||
gradle.allprojects(new Action<Project>() {
|
||||
public void execute(Project project) {
|
||||
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
|
||||
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
|
||||
dependsOnMergedFrom.dependencies.each{ dep ->
|
||||
project.dependencies.add("runtimeMerge", dep.dependencyProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MergeModel {
|
||||
Project into;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin
|
||||
@@ -0,0 +1 @@
|
||||
implementation-class=org.springframework.build.gradle.MergePlugin
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.1.0.RC2
|
||||
version=4.3.11.RELEASE
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
task api(type: Javadoc) {
|
||||
group = "Documentation"
|
||||
description = "Generates aggregated Javadoc API documentation."
|
||||
title = "${rootProject.description} ${version} API"
|
||||
|
||||
dependsOn {
|
||||
subprojects.collect {
|
||||
it.tasks.getByName("jar")
|
||||
}
|
||||
}
|
||||
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
|
||||
options.author = true
|
||||
options.header = rootProject.description
|
||||
options.use = true
|
||||
options.overview = "src/docs/api/overview.html"
|
||||
options.stylesheetFile = file("src/docs/api/stylesheet.css")
|
||||
options.splitIndex = true
|
||||
options.links(project.ext.javadocLinks)
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
|
||||
source subprojects.collect { project ->
|
||||
project.sourceSets.main.allJava
|
||||
}
|
||||
|
||||
maxMemory = "1024m"
|
||||
destinationDir = new File(buildDir, "api")
|
||||
|
||||
doFirst {
|
||||
classpath = files(
|
||||
// ensure the javadoc process can resolve types compiled from .aj sources
|
||||
project(":spring-aspects").sourceSets.main.output
|
||||
)
|
||||
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
|
||||
}
|
||||
}
|
||||
|
||||
dokka {
|
||||
dependsOn {
|
||||
tasks.getByName("api")
|
||||
}
|
||||
doFirst {
|
||||
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
|
||||
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
|
||||
|
||||
}
|
||||
moduleName = "spring-framework"
|
||||
outputFormat = "html"
|
||||
outputDirectory = "$buildDir/docs/kdoc"
|
||||
|
||||
sourceDirs = files(subprojects.collect { project ->
|
||||
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
|
||||
kotlinDirs -= project.sourceSets.main.java.srcDirs
|
||||
})
|
||||
externalDocumentationLink {
|
||||
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/")
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("http://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
|
||||
}
|
||||
}
|
||||
|
||||
asciidoctor {
|
||||
sources {
|
||||
include '*.adoc'
|
||||
}
|
||||
resources {
|
||||
from(sourceDir) {
|
||||
include 'images/*', 'stylesheets/*', 'tocbot-3.0.2/*'
|
||||
}
|
||||
}
|
||||
logDocuments = true
|
||||
backends = ["html5"]
|
||||
// only ouput PDF documentation for non-SNAPSHOT builds
|
||||
if(!project.getVersion().toString().contains("BUILD-SNAPSHOT")) {
|
||||
backends += "pdf"
|
||||
}
|
||||
options doctype: 'book', eruby: 'erubis'
|
||||
attributes 'icons': 'font',
|
||||
'idprefix': '',
|
||||
'idseparator': '-',
|
||||
docinfo: '',
|
||||
revnumber: project.version,
|
||||
sectanchors: '',
|
||||
sectnums: '',
|
||||
'source-highlighter': 'coderay@', // TODO switch to 'rouge' once supported by the html5 backend
|
||||
stylesdir: 'stylesheets/',
|
||||
stylesheet: 'main.css',
|
||||
'spring-version': project.version
|
||||
|
||||
}
|
||||
|
||||
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
|
||||
group = "Distribution"
|
||||
baseName = "spring-framework"
|
||||
classifier = "docs"
|
||||
description = "Builds -${classifier} archive containing api and reference " +
|
||||
"for deployment at http://docs.spring.io/spring-framework/docs."
|
||||
|
||||
from("src/dist") {
|
||||
include "changelog.txt"
|
||||
}
|
||||
|
||||
from (api) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
|
||||
from ("$asciidoctor.outputDir/html5") {
|
||||
into "spring-framework-reference"
|
||||
}
|
||||
|
||||
from ("$asciidoctor.outputDir/pdf") {
|
||||
into "spring-framework-reference/pdf"
|
||||
}
|
||||
|
||||
from (dokka) {
|
||||
into "kdoc-api"
|
||||
}
|
||||
}
|
||||
|
||||
task schemaZip(type: Zip) {
|
||||
group = "Distribution"
|
||||
baseName = "spring-framework"
|
||||
classifier = "schema"
|
||||
description = "Builds -${classifier} archive containing all " +
|
||||
"XSDs for deployment at http://springframework.org/schema."
|
||||
duplicatesStrategy 'exclude'
|
||||
moduleProjects.each { subproject ->
|
||||
def Properties schemas = new Properties();
|
||||
|
||||
subproject.sourceSets.main.resources.find {
|
||||
it.path.endsWith("META-INF/spring.schemas")
|
||||
}?.withInputStream { schemas.load(it) }
|
||||
|
||||
for (def key : schemas.keySet()) {
|
||||
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
|
||||
assert shortName != key
|
||||
File xsdFile = subproject.sourceSets.main.resources.find {
|
||||
it.path.endsWith(schemas.get(key))
|
||||
}
|
||||
assert xsdFile != null
|
||||
into (shortName) {
|
||||
from xsdFile.path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
|
||||
|
||||
group = "Distribution"
|
||||
baseName = "spring-framework"
|
||||
classifier = "dist"
|
||||
description = "Builds -${classifier} archive, containing all jars and docs, " +
|
||||
"suitable for community download page."
|
||||
|
||||
ext.baseDir = "${baseName}-${project.version}";
|
||||
|
||||
from("src/docs/dist") {
|
||||
include "readme.txt"
|
||||
include "license.txt"
|
||||
include "notice.txt"
|
||||
into "${baseDir}"
|
||||
expand(copyright: new Date().format("yyyy"), version: project.version)
|
||||
}
|
||||
|
||||
from(zipTree(docsZip.archivePath)) {
|
||||
into "${baseDir}/docs"
|
||||
}
|
||||
|
||||
from(zipTree(schemaZip.archivePath)) {
|
||||
into "${baseDir}/schema"
|
||||
}
|
||||
|
||||
moduleProjects.each { subproject ->
|
||||
into ("${baseDir}/libs") {
|
||||
from subproject.jar
|
||||
if (subproject.tasks.findByPath("sourcesJar")) {
|
||||
from subproject.sourcesJar
|
||||
}
|
||||
if (subproject.tasks.findByPath("javadocJar")) {
|
||||
from subproject.javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
distZip.mustRunAfter subprojects.test
|
||||
|
||||
// Create a distribution that contains all dependencies (required and optional).
|
||||
// Not published by default; only for use when building from source.
|
||||
task depsZip(type: Zip, dependsOn: distZip) { zipTask ->
|
||||
group = "Distribution"
|
||||
baseName = "spring-framework"
|
||||
classifier = "dist-with-deps"
|
||||
description = "Builds -${classifier} archive, containing everything " +
|
||||
"in the -${distZip.classifier} archive plus all runtime dependencies."
|
||||
|
||||
from zipTree(distZip.archivePath)
|
||||
|
||||
gradle.taskGraph.whenReady { taskGraph ->
|
||||
if (taskGraph.hasTask(":${zipTask.name}")) {
|
||||
def projectNames = rootProject.subprojects*.name
|
||||
def artifacts = new HashSet()
|
||||
subprojects.each { subproject ->
|
||||
(subproject.configurations.runtime.resolvedConfiguration.resolvedArtifacts +
|
||||
subproject.configurations.optional.resolvedConfiguration.resolvedArtifacts).each { artifact ->
|
||||
def dependency = artifact.moduleVersion.id
|
||||
if (!projectNames.contains(dependency.name)) {
|
||||
artifacts << artifact.file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zipTask.from(artifacts) {
|
||||
into "${distZip.baseDir}/deps"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-10
@@ -13,7 +13,7 @@ eclipse.jdt {
|
||||
// Replace classpath entries with project dependencies (GRADLE-1116)
|
||||
// http://issues.gradle.org/browse/GRADLE-1116
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
def regexp = /.*?\/([^\/]+)\/build\/([^\/]+\/)+(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
||||
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
||||
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
||||
projectOutputDependencies.each { entry ->
|
||||
def matcher = (entry.path =~ regexp)
|
||||
@@ -21,7 +21,7 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||
def projectName = matcher[0][1]
|
||||
def path = "/${projectName}"
|
||||
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
||||
def dependency = new ProjectDependency(path)
|
||||
def dependency = new ProjectDependency(path, project(":${projectName}").path)
|
||||
dependency.exported = true
|
||||
classpath.entries.add(dependency)
|
||||
}
|
||||
@@ -91,14 +91,6 @@ task cleanEclipseJdtUi(type: Delete) {
|
||||
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
|
||||
}
|
||||
|
||||
task eclipseBuildship(type: Copy) {
|
||||
from rootProject.files(
|
||||
"src/eclipse/org.eclipse.jdt.ui.prefs",
|
||||
"src/eclipse/org.eclipse.jdt.core.prefs")
|
||||
into project.file('.settings/')
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
|
||||
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
|
||||
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||
|
||||
@@ -43,7 +43,6 @@ task jdiff {
|
||||
ant.mkdir(dir: outputDir)
|
||||
ant.jdiff(
|
||||
destdir: outputDir,
|
||||
source: "1.8",
|
||||
verbose: "off",
|
||||
stats: "on",
|
||||
docchanges: "off") {
|
||||
|
||||
@@ -18,11 +18,6 @@ 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
-1
@@ -1,5 +1,6 @@
|
||||
#Wed Aug 17 21:21:18 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -34,11 +34,11 @@ DEFAULT_JVM_OPTS=""
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
@@ -155,19 +155,11 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
|
||||
Vendored
+6
@@ -50,6 +50,7 @@ goto fail
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@@ -60,6 +61,11 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
@echo off
|
||||
set STS_TEST_VERSION='2.9.2.RELEASE'
|
||||
|
||||
set CURRENT_DIR=%~dp0
|
||||
cd %CURRENT_DIR%
|
||||
|
||||
cls
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo Spring Framework Eclipse/STS project import guide
|
||||
echo.
|
||||
echo This script will guide you through the process of importing the
|
||||
echo Spring Framework sources into Eclipse/STS. It is recommended that you
|
||||
echo have a recent version of the SpringSource Tool Suite (this script has
|
||||
echo been tested against STS %STS_TEST_VERSION%), but at the minimum you will
|
||||
echo need Eclipse + AJDT.
|
||||
echo.
|
||||
echo If you need to download and install STS, please do that now by
|
||||
echo visiting http://spring.io/tools/sts/all
|
||||
echo.
|
||||
echo Otherwise, press enter and we'll begin.
|
||||
|
||||
pause
|
||||
|
||||
REM this command:
|
||||
REM - wipes out any existing Eclipse metadata
|
||||
REM - generates OXM test classes to avoid errors on import into Eclipse
|
||||
REM - generates metadata for all subprojects
|
||||
REM - skips metadata gen for the root project (-x :eclipse) to work
|
||||
REM around Eclipse's inability to import hierarchical project structures
|
||||
REM SET COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
SET COMMAND=gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo STEP 1: Generate subproject Eclipse metadata
|
||||
echo.
|
||||
echo The first step will be to generate Eclipse project metadata for each
|
||||
echo of the spring-* subprojects. This happens via the built-in
|
||||
echo "Gradle wrapper" script (./gradlew in this directory). If this is your
|
||||
echo first time using the Gradle wrapper, this step may take a few minutes
|
||||
echo while a Gradle distribution is downloaded for you.
|
||||
echo.
|
||||
echo The command run will be:
|
||||
echo.
|
||||
echo %COMMAND%
|
||||
echo.
|
||||
echo Press enter when ready.
|
||||
|
||||
pause
|
||||
|
||||
call %COMMAND%
|
||||
if not "%ERRORLEVEL%" == "0" exit /B %ERRORLEVEL%
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo STEP 2: Import subprojects into Eclipse/STS
|
||||
echo.
|
||||
echo Within Eclipse/STS, do the following:
|
||||
echo.
|
||||
echo File ^> Import... ^> Existing Projects into Workspace
|
||||
echo ^> When prompted for the 'root directory', provide %CURRENT_DIR%
|
||||
echo ^> Press enter. You will see the modules show up under "Projects"
|
||||
echo ^> All projects should be selected/checked. Click Finish.
|
||||
echo ^> When the project import is complete, you should have no errors.
|
||||
echo.
|
||||
echo When the above is complete, return here and press the enter key.
|
||||
|
||||
pause
|
||||
|
||||
set COMMAND=gradlew --no-daemon :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo STEP 3: generate root project Eclipse metadata
|
||||
echo.
|
||||
echo Unfortunately, Eclipse does not allow for importing project
|
||||
echo hierarchies, so we had to skip root project metadata generation in the
|
||||
echo during step 1. In this step we simply generate root project metadata
|
||||
echo so you can import it in the next step.
|
||||
echo.
|
||||
echo The command run will be:
|
||||
echo.
|
||||
echo %COMMAND%
|
||||
echo.
|
||||
echo Press the enter key when ready.
|
||||
pause
|
||||
|
||||
call %COMMAND%
|
||||
if not "%ERRORLEVEL%" == "0" exit /B %ERRORLEVEL%
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo STEP 4: Import root project into Eclipse/STS
|
||||
echo.
|
||||
echo Follow the project import steps listed in step 2 above to import the
|
||||
echo root project.
|
||||
echo.
|
||||
echo Press enter when complete, and move on to the final step.
|
||||
|
||||
pause
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
echo STEP 5: Enable Git support for all projects
|
||||
echo.
|
||||
echo - In the Eclipse/STS Package Explorer, select all spring* projects.
|
||||
echo - Right-click to open the context menu and select Team ^> Share Project...
|
||||
echo - In the Share Project dialog that appears, select Git and press Next
|
||||
echo - Check "Use or create repository in parent folder of project"
|
||||
echo - Click Finish
|
||||
echo.
|
||||
echo When complete, you'll have Git support enabled for all projects.
|
||||
echo.
|
||||
echo You're ready to code! Goodbye!
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# Spring Framework - Eclipse/STS Project Import Guide
|
||||
|
||||
This document will guide you through the process of importing the Spring Framework
|
||||
projects into Eclipse or the Spring Tool Suite (STS). It is recommended that you have a
|
||||
recent version of Eclipse or STS. As a bare minimum you will need Eclipse with full Java
|
||||
8 support, the AspectJ Development Tools (AJDT), and the Groovy Compiler.
|
||||
|
||||
The following instructions have been tested against
|
||||
[Spring Tool Suite](https://spring.io/tools) (_STS_) 3.9.4 and 4.0.0.M11 with
|
||||
[Eclipse Buildship](http://projects.eclipse.org/projects/tools.buildship) (Eclipse
|
||||
Plug-ins for Gradle). The instructions should work with the latest Eclipse distribution
|
||||
as long as you install
|
||||
[Buildship](https://marketplace.eclipse.org/content/buildship-gradle-integration). Note
|
||||
that STS 4 comes with Buildship preinstalled.
|
||||
|
||||
## Steps
|
||||
|
||||
_Within your locally cloned `spring-framework` working directory:_
|
||||
|
||||
1. Precompile `spring-oxm` with `./gradlew :spring-oxm:compileTestJava`
|
||||
2. Import into Eclipse (File -> Import -> Gradle -> Existing Gradle Project -> Navigate
|
||||
to directory -> Select Finish)
|
||||
3. If prompted, exclude the `spring-aspects` module (or after the import by closing or
|
||||
deleting the project)
|
||||
4. In the `spring-oxm` project, add the two folders (`castor` and `jaxb`) in
|
||||
`build/generated-sources` to the build path (right click on them and select
|
||||
`Build Path -> Use as Source Folder`)
|
||||
5. To apply project specific settings run `./gradlew eclipseBuildship`
|
||||
7. Code away
|
||||
|
||||
## Known Issues
|
||||
|
||||
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
|
||||
- See `*RepackJar` tasks in the build.
|
||||
2. `spring-aspects` does not compile due to references to aspect types unknown to Eclipse.
|
||||
- If you install [AJDT](https://www.eclipse.org/ajdt/downloads/) into Eclipse it should
|
||||
work.
|
||||
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
|
||||
the IDE.
|
||||
- Resolving this is a work in progress.
|
||||
- If attempting to run all JUnit tests from within the IDE, you will likely need to set
|
||||
the following VM options to avoid out of memory errors:
|
||||
`-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m`
|
||||
|
||||
## Tips
|
||||
|
||||
In any case, please do not check in your own generated `.classpath` file, `.project`
|
||||
file, or `.settings` folder. You'll notice these files are already intentionally in
|
||||
`.gitignore`. The same policy holds for IDEA metadata.
|
||||
Executable
+135
@@ -0,0 +1,135 @@
|
||||
cd `dirname $0`
|
||||
clear
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Spring Framework - Eclipse/STS Project Import Guide
|
||||
|
||||
This script will guide you through the process of importing the Spring
|
||||
Framework projects into Eclipse or the Spring Tool Suite (STS). It is
|
||||
recommended that you have a recent version of Eclipse or STS. As a bare
|
||||
minimum you will need Eclipse with full Java 8 support, the AspectJ
|
||||
Development Tools (AJDT), and the Groovy Compiler.
|
||||
|
||||
This script has been tested against:
|
||||
|
||||
- STS: 3.6.3.RELEASE (Eclipse Luna SR1 4.4.1)
|
||||
- AJDT: 2.2.4.e44x-20141118-0700 (Luna 4.4)
|
||||
|
||||
If you need to download and install Eclipse or STS, please do that now
|
||||
by visiting one of the following sites:
|
||||
|
||||
- Eclipse downloads: http://download.eclipse.org/eclipse/downloads
|
||||
- STS downloads: http://spring.io/tools/sts/all
|
||||
- STS nightly builds: http://dist.springsource.com/snapshot/STS/nightly-distributions.html
|
||||
|
||||
If you need to install a recent CI build for AJDT (i.e., so that the
|
||||
spring-aspects module properly compiles in Eclipse/STS), click on the
|
||||
"Artifacts" tab of a successful CI build and copy the link to the
|
||||
"update site" which you can then use to install or update AJDT within
|
||||
Eclipse/STS.
|
||||
|
||||
- AJDT CI builds: https://build.spring.io/browse/AJDT-AE44
|
||||
|
||||
Once Eclipse/STS is installed, press enter, and we'll begin.
|
||||
EOM
|
||||
|
||||
read
|
||||
|
||||
# this command:
|
||||
# - wipes out any existing Eclipse metadata
|
||||
# - generates OXM test classes to avoid errors on import into Eclipse
|
||||
# - generates metadata for all subprojects
|
||||
# - skips metadata gen for the root project (-x :eclipse) to work
|
||||
# around Eclipse's inability to import hierarchical project structures
|
||||
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
STEP 1: Generate subproject Eclipse metadata
|
||||
|
||||
The first step will be to generate Eclipse project metadata for each of
|
||||
the spring-* subprojects. This happens via the built-in "Gradle wrapper"
|
||||
script (./gradlew in this directory). If this is your first time using
|
||||
the Gradle wrapper, this step may take a few minutes while a Gradle
|
||||
distribution is downloaded for you.
|
||||
|
||||
The command run will be:
|
||||
|
||||
$COMMAND
|
||||
|
||||
Press enter when ready.
|
||||
EOM
|
||||
|
||||
read
|
||||
|
||||
$COMMAND || exit
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
STEP 2: Import subprojects into Eclipse/STS
|
||||
|
||||
Within Eclipse/STS, do the following:
|
||||
|
||||
- File > Import... > Existing Projects into Workspace
|
||||
- When prompted for the 'root directory', provide $PWD.
|
||||
- Press enter. You will see the modules show up under "Projects".
|
||||
- All projects should be selected/checked. Click Finish.
|
||||
- When the project import is complete, you should have no errors.
|
||||
|
||||
When the above is complete, return here and press the enter key.
|
||||
EOM
|
||||
|
||||
read
|
||||
|
||||
COMMAND="./gradlew --no-daemon :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
STEP 3: Generate root project Eclipse metadata
|
||||
|
||||
Unfortunately, Eclipse does not support importing project hierarchies,
|
||||
so we had to skip root project metadata generation during step 1. In
|
||||
this step we simply generate root project metadata so that you can
|
||||
import it in the next step.
|
||||
|
||||
The command run will be:
|
||||
|
||||
$COMMAND
|
||||
|
||||
Press the enter key when ready.
|
||||
EOM
|
||||
|
||||
read
|
||||
|
||||
$COMMAND || exit
|
||||
|
||||
cat <<EOM
|
||||
------------------------------------------------------------------------
|
||||
STEP 4: Import root project into Eclipse/STS
|
||||
|
||||
Follow the project import steps listed in step 2 above to import the
|
||||
root "spring" project.
|
||||
|
||||
Press enter when complete, and move on to the final step.
|
||||
EOM
|
||||
|
||||
read
|
||||
|
||||
cat <<EOM
|
||||
------------------------------------------------------------------------
|
||||
STEP 5: Enable Git support for all projects
|
||||
|
||||
- In the Eclipse/STS Package Explorer, select all spring* projects.
|
||||
- Right-click to open the context menu and select Team > Share Project...
|
||||
- In the Share Project dialog that appears, select Git and press Next.
|
||||
- Check "Use or create repository in parent folder of project".
|
||||
- Click Finish.
|
||||
|
||||
When complete, you'll have Git support enabled for all projects.
|
||||
|
||||
You're ready to code! Goodbye!
|
||||
EOM
|
||||
+14
-17
@@ -1,28 +1,25 @@
|
||||
The following has been tested against IntelliJ IDEA 2016.2.2
|
||||
The following has been tested against Intellij IDEA 13.1
|
||||
|
||||
## Steps
|
||||
|
||||
_Within your locally cloned spring-framework working directory:_
|
||||
|
||||
1. Precompile `spring-oxm` with `./gradlew :spring-oxm:compileTestJava`
|
||||
2. Import into IntelliJ (File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)
|
||||
3. When prompted exclude the `spring-aspects` module (or after the import via File-> Project Structure -> Modules)
|
||||
4. Code away
|
||||
1. Pre-compile `spring-oxm` with `./gradlew cleanIdea :spring-oxm:compileTestJava`
|
||||
2. Import into IDEA (File->import project->import from external model->Gradle)
|
||||
3. Set the Project JDK as appropriate (1.8+)
|
||||
4. Exclude the `spring-aspects` module (Go to File->Project Structure->Modules)
|
||||
5. Code away
|
||||
|
||||
## Known issues
|
||||
|
||||
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
|
||||
See `*RepackJar` tasks in the build and https://youtrack.jetbrains.com/issue/IDEA-160605).
|
||||
2. `spring-aspects` does not compile due to references to aspect types unknown to
|
||||
IntelliJ IDEA. See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the
|
||||
'spring-aspects' can be excluded from the project to avoid compilation errors.
|
||||
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
|
||||
IntelliJ IDEA. Resolving this is a work in progress. If attempting to run all JUnit tests from within
|
||||
IntelliJ IDEA, you will likely need to set the following VM options to avoid out of memory errors:
|
||||
1. `spring-oxm` should be pre-compiled since it's using repackaged dependencies (see *RepackJar tasks)
|
||||
2. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
|
||||
See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the 'spring-aspects'
|
||||
should be excluded from the overall project to avoid compilation errors.
|
||||
3. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
|
||||
likely need to set the following VM options to avoid out of memory errors:
|
||||
-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
|
||||
4. If you invoke "Rebuild Project" in the IDE, you'll have to generate some test
|
||||
resources of the `spring-oxm` module again (`./gradlew :spring-oxm:compileTestJava`)
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
@@ -31,6 +28,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
|
||||
|
||||
## FAQ
|
||||
|
||||
Q. What about IntelliJ IDEA's own [Gradle support](http://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
|
||||
Q. What about IDEA's own [Gradle support](http://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
|
||||
|
||||
A. Keep an eye on http://youtrack.jetbrains.com/issue/IDEA-53476
|
||||
|
||||
+8
-8
@@ -1,31 +1,31 @@
|
||||
rootProject.name = "spring"
|
||||
|
||||
include "spring-aop"
|
||||
include "spring-aspects"
|
||||
include "spring-beans"
|
||||
include "spring-beans-groovy"
|
||||
include "spring-context"
|
||||
include "spring-context-support"
|
||||
include "spring-context-indexer"
|
||||
include "spring-core"
|
||||
include "spring-expression"
|
||||
include "spring-instrument"
|
||||
include "spring-jcl"
|
||||
include "spring-instrument-tomcat"
|
||||
include "spring-jdbc"
|
||||
include "spring-jms"
|
||||
include "spring-messaging"
|
||||
include "spring-orm"
|
||||
include "spring-orm-hibernate4"
|
||||
include "spring-orm-hibernate5"
|
||||
include "spring-oxm"
|
||||
include "spring-test"
|
||||
include "spring-tx"
|
||||
include "spring-web"
|
||||
include "spring-webmvc"
|
||||
include "spring-webflux"
|
||||
include "spring-webmvc-portlet"
|
||||
include "spring-webmvc-tiles2"
|
||||
include "spring-websocket"
|
||||
include "spring-framework-bom"
|
||||
|
||||
// Exposes gradle buildSrc for IDE support
|
||||
include "buildSrc"
|
||||
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
|
||||
|
||||
rootProject.name = "spring"
|
||||
rootProject.children.each {project ->
|
||||
project.buildFileName = "${project.name}.gradle"
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
description = "Spring AOP"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.commons:commons-pool2:2.6.0")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,7 @@ package org.aopalliance.aop;
|
||||
* Superclass for all AOP infrastructure exceptions.
|
||||
* Unchecked, as such exceptions are fatal and end user
|
||||
* code shouldn't be forced to catch them.
|
||||
*
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Bob Lee
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* The core AOP Alliance advice marker.
|
||||
*/
|
||||
package org.aopalliance.aop;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -30,12 +30,12 @@ import java.lang.reflect.Constructor;
|
||||
*/
|
||||
public interface ConstructorInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the constructor being called.
|
||||
* <p>This method is a friendly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the constructor being called
|
||||
*/
|
||||
Constructor<?> getConstructor();
|
||||
/**
|
||||
* Get the constructor being called.
|
||||
* <p>This method is a friendly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the constructor being called
|
||||
*/
|
||||
Constructor<?> getConstructor();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -24,7 +24,7 @@ import org.aopalliance.aop.Advice;
|
||||
* <p>A generic interceptor can intercept runtime events that occur
|
||||
* within a base program. Those events are materialized by (reified
|
||||
* in) joinpoints. Runtime joinpoints can be invocations, field
|
||||
* access, exceptions...
|
||||
* access, exceptions...
|
||||
*
|
||||
* <p>This interface is not used directly. Use the sub-interfaces
|
||||
* to intercept specific events. For instance, the following class
|
||||
@@ -32,7 +32,7 @@ import org.aopalliance.aop.Advice;
|
||||
* debugger:
|
||||
*
|
||||
* <pre class=code>
|
||||
* class DebuggingInterceptor implements MethodInterceptor,
|
||||
* class DebuggingInterceptor implements MethodInterceptor,
|
||||
* ConstructorInterceptor, FieldInterceptor {
|
||||
*
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
@@ -44,7 +44,7 @@ import org.aopalliance.aop.Advice;
|
||||
* debug(i.getConstructor(), i.getThis(), i.getArgs());
|
||||
* return i.proceed();
|
||||
* }
|
||||
*
|
||||
*
|
||||
* Object get(FieldAccess fa) throws Throwable {
|
||||
* debug(fa.getField(), fa.getThis(), null);
|
||||
* return fa.proceed();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -39,9 +39,8 @@ package org.aopalliance.intercept;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface MethodInterceptor extends Interceptor {
|
||||
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the invocation. Polite implementations would certainly
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* The AOP Alliance reflective interception abstraction.
|
||||
*/
|
||||
package org.aopalliance.intercept;
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Spring's variant of the AOP Alliance interfaces.
|
||||
*/
|
||||
package org.aopalliance;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -31,18 +31,9 @@ import org.aopalliance.aop.Advice;
|
||||
* implemented using interception.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface Advisor {
|
||||
|
||||
/**
|
||||
* Common placeholder for an empty {@code Advice} to be returned from
|
||||
* {@link #getAdvice()} if no proper advice has been configured (yet).
|
||||
* @since 5.0
|
||||
*/
|
||||
Advice EMPTY_ADVICE = new Advice() {};
|
||||
|
||||
|
||||
/**
|
||||
* Return the advice part of this aspect. An advice may be an
|
||||
* interceptor, a before advice, a throws advice, etc.
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* After returning advice is invoked only on normal method return, not if an
|
||||
* exception is thrown. Such advice can see the return value, but cannot change it.
|
||||
@@ -41,6 +39,6 @@ public interface AfterReturningAdvice extends AfterAdvice {
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
* will be wrapped as a runtime exception.
|
||||
*/
|
||||
void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;
|
||||
void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2007 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 @@ package org.springframework.aop;
|
||||
* @see Pointcut
|
||||
* @see MethodMatcher
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClassFilter {
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2013 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,7 +33,8 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
|
||||
* instead of the 2-arg {@link #matches(java.lang.reflect.Method, Class)} method
|
||||
* if the caller supports the extended IntroductionAwareMethodMatcher interface.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param hasIntroductions {@code true} if the object on whose behalf we are
|
||||
* asking is the subject on one or more introductions; {@code false} otherwise
|
||||
* @return whether or not this method matches statically
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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,15 +18,14 @@ package org.springframework.aop;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Advice invoked before a method is invoked. Such advices cannot
|
||||
* prevent the method call proceeding, unless they throw a Throwable.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see AfterReturningAdvice
|
||||
* @see ThrowsAdvice
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
|
||||
@@ -40,6 +39,6 @@ public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
* will be wrapped as a runtime exception.
|
||||
*/
|
||||
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
|
||||
void before(Method method, Object[] args, Object target) throws Throwable;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -48,13 +48,13 @@ import java.lang.reflect.Method;
|
||||
public interface MethodMatcher {
|
||||
|
||||
/**
|
||||
* Perform static checking whether the given method matches.
|
||||
* <p>If this returns {@code false} or if the {@link #isRuntime()}
|
||||
* method returns {@code false}, no runtime check (i.e. no
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
|
||||
* will be made.
|
||||
* Perform static checking whether the given method matches. If this
|
||||
* returns {@code false} or if the {@link #isRuntime()} method
|
||||
* returns {@code false}, no runtime check (i.e. no.
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @return whether or not this method matches statically
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass);
|
||||
@@ -80,7 +80,8 @@ public interface MethodMatcher {
|
||||
* immediately before potential running of the advice, after any
|
||||
* advice earlier in the advice chain has run.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param args arguments to the method
|
||||
* @return whether there's a runtime match
|
||||
* @see MethodMatcher#matches(Method, Class)
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Extension of the AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}
|
||||
* interface, allowing access to the proxy that the method invocation was made through.
|
||||
@@ -75,7 +73,7 @@ public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
* @param key the name of the attribute
|
||||
* @param value the value of the attribute, or {@code null} to reset it
|
||||
*/
|
||||
void setUserAttribute(String key, @Nullable Object value);
|
||||
void setUserAttribute(String key, Object value);
|
||||
|
||||
/**
|
||||
* Return the value of the specified user attribute.
|
||||
@@ -83,7 +81,6 @@ public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
* @return the value of the attribute, or {@code null} if not set
|
||||
* @see #setUserAttribute
|
||||
*/
|
||||
@Nullable
|
||||
Object getUserAttribute(String key);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Minimal interface for exposing the target class behind a proxy.
|
||||
*
|
||||
@@ -36,7 +34,6 @@ public interface TargetClassAware {
|
||||
* (typically a proxy configuration or an actual proxy).
|
||||
* @return the target Class, or {@code null} if not known
|
||||
*/
|
||||
@Nullable
|
||||
Class<?> getTargetClass();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
/*<
|
||||
* Copyright 2002-2012 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,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A {@code TargetSource} is used to obtain the current "target" of
|
||||
* an AOP invocation, which will be invoked via reflection if no around
|
||||
@@ -31,24 +29,24 @@ import org.springframework.lang.Nullable;
|
||||
* {@code TargetSources} directly: this is an AOP framework interface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface TargetSource extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Return the type of targets returned by this {@link TargetSource}.
|
||||
* <p>Can return {@code null}, although certain usages of a {@code TargetSource}
|
||||
* might just work with a predetermined target class.
|
||||
* <p>Can return {@code null}, although certain usages of a
|
||||
* {@code TargetSource} might just work with a predetermined
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
Class<?> getTargetClass();
|
||||
|
||||
/**
|
||||
* Will all calls to {@link #getTarget()} return the same object?
|
||||
* <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
|
||||
* and the AOP framework can cache the return value of {@link #getTarget()}.
|
||||
* <p>In that case, there will be no need to invoke
|
||||
* {@link #releaseTarget(Object)}, and the AOP framework can cache
|
||||
* the return value of {@link #getTarget()}.
|
||||
* @return {@code true} if the target is immutable
|
||||
* @see #getTarget
|
||||
*/
|
||||
@@ -57,16 +55,14 @@ public interface TargetSource extends TargetClassAware {
|
||||
/**
|
||||
* Return a target instance. Invoked immediately before the
|
||||
* AOP framework calls the "target" of an AOP method invocation.
|
||||
* @return the target object which contains the joinpoint,
|
||||
* or {@code null} if there is no actual target instance
|
||||
* @return the target object, which contains the joinpoint
|
||||
* @throws Exception if the target object can't be resolved
|
||||
*/
|
||||
@Nullable
|
||||
Object getTarget() throws Exception;
|
||||
|
||||
/**
|
||||
* Release the given target object obtained from the
|
||||
* {@link #getTarget()} method, if any.
|
||||
* {@link #getTarget()} method.
|
||||
* @param target object obtained from a call to {@link #getTarget()}
|
||||
* @throws Exception if the object can't be released
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -24,7 +24,7 @@ import java.io.Serializable;
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
final class TrueClassFilter implements ClassFilter, Serializable {
|
||||
class TrueClassFilter implements ClassFilter, Serializable {
|
||||
|
||||
public static final TrueClassFilter INSTANCE = new TrueClassFilter();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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,7 +25,7 @@ import java.lang.reflect.Method;
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
final class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -24,7 +24,7 @@ import java.io.Serializable;
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
final class TruePointcut implements Pointcut, Serializable {
|
||||
class TruePointcut implements Pointcut, Serializable {
|
||||
|
||||
public static final TruePointcut INSTANCE = new TruePointcut();
|
||||
|
||||
|
||||
+39
-57
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -42,7 +42,6 @@ import org.springframework.aop.support.MethodMatchers;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -104,11 +103,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
private final AspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
/**
|
||||
* The name of the aspect (ref bean) in which this advice was defined
|
||||
* (used when determining advice precedence so that we can determine
|
||||
* The name of the aspect (ref bean) in which this advice was defined (used
|
||||
* when determining advice precedence so that we can determine
|
||||
* whether two pieces of advice come from the same aspect).
|
||||
*/
|
||||
private String aspectName = "";
|
||||
private String aspectName;
|
||||
|
||||
/**
|
||||
* The order of declaration of this advice within the aspect.
|
||||
@@ -117,18 +116,15 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
/**
|
||||
* This will be non-null if the creator of this advice object knows the argument names
|
||||
* and sets them explicitly.
|
||||
* and sets them explicitly
|
||||
*/
|
||||
@Nullable
|
||||
private String[] argumentNames;
|
||||
private String[] argumentNames = null;
|
||||
|
||||
/** Non-null if after throwing advice binds the thrown value. */
|
||||
@Nullable
|
||||
private String throwingName;
|
||||
/** Non-null if after throwing advice binds the thrown value */
|
||||
private String throwingName = null;
|
||||
|
||||
/** Non-null if after returning advice binds the return value. */
|
||||
@Nullable
|
||||
private String returningName;
|
||||
/** Non-null if after returning advice binds the return value */
|
||||
private String returningName = null;
|
||||
|
||||
private Class<?> discoveredReturningType = Object.class;
|
||||
|
||||
@@ -136,22 +132,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
/**
|
||||
* Index for thisJoinPoint argument (currently only
|
||||
* supported at index 0 if present at all).
|
||||
* supported at index 0 if present at all)
|
||||
*/
|
||||
private int joinPointArgumentIndex = -1;
|
||||
|
||||
/**
|
||||
* Index for thisJoinPointStaticPart argument (currently only
|
||||
* supported at index 0 if present at all).
|
||||
* supported at index 0 if present at all)
|
||||
*/
|
||||
private int joinPointStaticPartArgumentIndex = -1;
|
||||
|
||||
@Nullable
|
||||
private Map<String, Integer> argumentBindings;
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
@Nullable
|
||||
private Type discoveredReturningGenericType;
|
||||
// Note: Unlike return type, no such generic information is needed for the throwing type,
|
||||
// since Java doesn't allow exception types to be parameterized.
|
||||
@@ -213,7 +207,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
/**
|
||||
* Return the ClassLoader for aspect instances.
|
||||
*/
|
||||
@Nullable
|
||||
public final ClassLoader getAspectClassLoader() {
|
||||
return this.aspectInstanceFactory.getAspectClassLoader();
|
||||
}
|
||||
@@ -224,9 +217,6 @@ 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;
|
||||
}
|
||||
@@ -237,7 +227,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the declaration order of this advice within the aspect.
|
||||
* Sets the <b>declaration order</b> of this advice within the aspect
|
||||
*/
|
||||
public void setDeclarationOrder(int order) {
|
||||
this.declarationOrder = order;
|
||||
@@ -270,7 +260,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
if (this.argumentNames != null) {
|
||||
if (this.aspectJAdviceMethod.getParameterCount() == this.argumentNames.length + 1) {
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
@@ -305,8 +295,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Returning name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,7 +305,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Type getDiscoveredReturningGenericType() {
|
||||
return this.discoveredReturningGenericType;
|
||||
}
|
||||
@@ -340,8 +329,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Throwing name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,7 +366,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 final synchronized void calculateArgumentBindings() {
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
|
||||
return;
|
||||
@@ -385,8 +374,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
int numUnboundArgs = this.parameterTypes.length;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
|
||||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
|
||||
@@ -470,10 +461,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
private void bindExplicitArguments(int numArgumentsLeftToBind) {
|
||||
Assert.state(this.argumentNames != null, "No argument names available");
|
||||
this.argumentBindings = new HashMap<>();
|
||||
this.argumentBindings = new HashMap<String, Integer>();
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
|
||||
" arguments to bind by name in advice, but actually found " +
|
||||
@@ -511,7 +501,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
// configure the pointcut expression accordingly.
|
||||
configurePointcutParameters(this.argumentNames, argumentIndexOffset);
|
||||
configurePointcutParameters(argumentIndexOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -519,7 +509,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* pointcut parameters - but returning and throwing vars are handled differently
|
||||
* and must be removed from the list if present.
|
||||
*/
|
||||
private void configurePointcutParameters(String[] argumentNames, int argumentIndexOffset) {
|
||||
private void configurePointcutParameters(int argumentIndexOffset) {
|
||||
int numParametersToRemove = argumentIndexOffset;
|
||||
if (this.returningName != null) {
|
||||
numParametersToRemove++;
|
||||
@@ -527,20 +517,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
if (this.throwingName != null) {
|
||||
numParametersToRemove++;
|
||||
}
|
||||
String[] pointcutParameterNames = new String[argumentNames.length - numParametersToRemove];
|
||||
String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
|
||||
Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
|
||||
Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < argumentNames.length; i++) {
|
||||
for (int i = 0; i < this.argumentNames.length; i++) {
|
||||
if (i < argumentIndexOffset) {
|
||||
continue;
|
||||
}
|
||||
if (argumentNames[i].equals(this.returningName) ||
|
||||
argumentNames[i].equals(this.throwingName)) {
|
||||
if (this.argumentNames[i].equals(this.returningName) ||
|
||||
this.argumentNames[i].equals(this.throwingName)) {
|
||||
continue;
|
||||
}
|
||||
pointcutParameterNames[index] = argumentNames[i];
|
||||
pointcutParameterNames[index] = this.argumentNames[i];
|
||||
pointcutParameterTypes[index] = methodParameterTypes[i];
|
||||
index++;
|
||||
}
|
||||
@@ -551,16 +541,14 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
/**
|
||||
* Take the arguments at the method execution join point and output a set of arguments
|
||||
* to the advice method.
|
||||
* to the advice method
|
||||
* @param jp the current JoinPoint
|
||||
* @param jpMatch the join point match that matched this execution join point
|
||||
* @param returnValue the return value from the method execution (may be null)
|
||||
* @param ex the exception thrown by the method execution (may be null)
|
||||
* @return the empty array if there are no arguments
|
||||
*/
|
||||
protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
|
||||
@Nullable Object returnValue, @Nullable Throwable ex) {
|
||||
|
||||
protected Object[] argBinding(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable ex) {
|
||||
calculateArgumentBindings();
|
||||
|
||||
// AMC start
|
||||
@@ -619,23 +607,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* @return the invocation result
|
||||
* @throws Throwable in case of invocation failure
|
||||
*/
|
||||
protected Object invokeAdviceMethod(
|
||||
@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
|
||||
throws Throwable {
|
||||
|
||||
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
|
||||
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
|
||||
}
|
||||
|
||||
// As above, but in this case we are given the join point.
|
||||
protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
|
||||
@Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
|
||||
protected Object invokeAdviceMethod(JoinPoint jp, JoinPointMatch jpMatch, Object returnValue, Throwable t)
|
||||
throws Throwable {
|
||||
|
||||
return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
|
||||
}
|
||||
|
||||
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
|
||||
Object[] actualArgs = args;
|
||||
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
|
||||
actualArgs = null;
|
||||
}
|
||||
try {
|
||||
@@ -663,7 +648,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
/**
|
||||
* Get the current join point match at the join point we are being dispatched on.
|
||||
*/
|
||||
@Nullable
|
||||
protected JoinPointMatch getJoinPointMatch() {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
@@ -678,10 +662,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
// 'last man wins' which is not what we want at all.
|
||||
// Using the expression is guaranteed to be safe, since 2 identical expressions
|
||||
// are guaranteed to bind in exactly the same way.
|
||||
@Nullable
|
||||
protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
|
||||
String expression = this.pointcut.getExpression();
|
||||
return (expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null);
|
||||
return (JoinPointMatch) pmi.getUserAttribute(this.pointcut.getExpression());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 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.aspectj;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface implemented to provide an instance of an AspectJ aspect.
|
||||
@@ -41,10 +40,8 @@ public interface AspectInstanceFactory extends Ordered {
|
||||
|
||||
/**
|
||||
* Expose the aspect class loader that this factory uses.
|
||||
* @return the aspect class loader (or {@code null} for the bootstrap loader)
|
||||
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
|
||||
* @return the aspect class loader (never {@code null})
|
||||
*/
|
||||
@Nullable
|
||||
ClassLoader getAspectClassLoader();
|
||||
|
||||
}
|
||||
|
||||
+32
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -30,7 +30,6 @@ import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -114,7 +113,6 @@ import org.springframework.util.StringUtils;
|
||||
* returning {@code null} in the case that the parameter names cannot be discovered.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
@@ -132,8 +130,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
private static final int STEP_REFERENCE_PCUT_BINDING = 7;
|
||||
private static final int STEP_FINISHED = 8;
|
||||
|
||||
private static final Set<String> singleValuedAnnotationPcds = new HashSet<>();
|
||||
private static final Set<String> nonReferencePointcutTokens = new HashSet<>();
|
||||
private static final Set<String> singleValuedAnnotationPcds = new HashSet<String>();
|
||||
private static final Set<String> nonReferencePointcutTokens = new HashSet<String>();
|
||||
|
||||
|
||||
static {
|
||||
@@ -156,36 +154,38 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
|
||||
/** The pointcut expression associated with the advice, as a simple String. */
|
||||
@Nullable
|
||||
private String pointcutExpression;
|
||||
|
||||
private boolean raiseExceptions;
|
||||
|
||||
/** If the advice is afterReturning, and binds the return value, this is the parameter name used. */
|
||||
@Nullable
|
||||
/**
|
||||
* If the advice is afterReturning, and binds the return value, this is the parameter name used.
|
||||
*/
|
||||
private String returningName;
|
||||
|
||||
/** If the advice is afterThrowing, and binds the thrown value, this is the parameter name used. */
|
||||
@Nullable
|
||||
/**
|
||||
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
|
||||
*/
|
||||
private String throwingName;
|
||||
|
||||
private Class<?>[] argumentTypes = new Class<?>[0];
|
||||
/**
|
||||
* The pointcut expression associated with the advice, as a simple String.
|
||||
*/
|
||||
private String pointcutExpression;
|
||||
|
||||
private String[] parameterNameBindings = new String[0];
|
||||
private Class<?>[] argumentTypes;
|
||||
|
||||
private String[] parameterNameBindings;
|
||||
|
||||
private int numberOfRemainingUnboundArguments;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new discoverer that attempts to discover parameter names.
|
||||
* Create a new discoverer that attempts to discover parameter names
|
||||
* from the given pointcut expression.
|
||||
*/
|
||||
public AspectJAdviceParameterNameDiscoverer(@Nullable String pointcutExpression) {
|
||||
public AspectJAdviceParameterNameDiscoverer(String pointcutExpression) {
|
||||
this.pointcutExpression = pointcutExpression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicate whether {@link IllegalArgumentException} and {@link AmbiguousBindingException}
|
||||
* must be thrown as appropriate in the case of failing to deduce advice parameter names.
|
||||
@@ -200,7 +200,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* returning variable name must be specified.
|
||||
* @param returningName the name of the returning variable
|
||||
*/
|
||||
public void setReturningName(@Nullable String returningName) {
|
||||
public void setReturningName(String returningName) {
|
||||
this.returningName = returningName;
|
||||
}
|
||||
|
||||
@@ -209,11 +209,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* throwing variable name must be specified.
|
||||
* @param throwingName the name of the throwing variable
|
||||
*/
|
||||
public void setThrowingName(@Nullable String throwingName) {
|
||||
public void setThrowingName(String throwingName) {
|
||||
this.throwingName = throwingName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deduce the parameter names for an advice method.
|
||||
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
|
||||
@@ -222,7 +221,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* @return the parameter names
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames(Method method) {
|
||||
this.argumentTypes = method.getParameterTypes();
|
||||
this.numberOfRemainingUnboundArguments = this.argumentTypes.length;
|
||||
@@ -311,7 +309,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames(Constructor<?> ctor) {
|
||||
if (this.raiseExceptions) {
|
||||
throw new UnsupportedOperationException("An advice method can never be a constructor");
|
||||
@@ -417,11 +414,11 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* <p>Some more support from AspectJ in doing this exercise would be nice... :)
|
||||
*/
|
||||
private void maybeBindAnnotationsFromPointcutExpression() {
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
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);
|
||||
}
|
||||
@@ -476,9 +473,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
/*
|
||||
* If the token starts meets Java identifier conventions, it's in.
|
||||
*/
|
||||
@Nullable
|
||||
private String maybeExtractVariableName(@Nullable String candidateToken) {
|
||||
if (!StringUtils.hasLength(candidateToken)) {
|
||||
private String maybeExtractVariableName(String candidateToken) {
|
||||
if (candidateToken == null || candidateToken.equals("")) {
|
||||
return null;
|
||||
}
|
||||
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
|
||||
@@ -500,7 +496,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* Given an args pointcut body (could be {@code args} or {@code at_args}),
|
||||
* add any candidate variable names to the given list.
|
||||
*/
|
||||
private void maybeExtractVariableNamesFromArgs(@Nullable String argsSpec, List<String> varNames) {
|
||||
private void maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames) {
|
||||
if (argsSpec == null) {
|
||||
return;
|
||||
}
|
||||
@@ -524,7 +520,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
+ " unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("this") ||
|
||||
@@ -541,7 +537,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
else if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
List<String> candidateVarNames = new ArrayList<>();
|
||||
List<String> candidateVarNames = new ArrayList<String>();
|
||||
maybeExtractVariableNamesFromArgs(body.text, candidateVarNames);
|
||||
// we may have found some var names that were bound in previous primitive args binding step,
|
||||
// filter them out...
|
||||
@@ -575,14 +571,14 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
+ " unbound args at reference pointcut binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
if (toMatch.startsWith("!")) {
|
||||
toMatch = toMatch.substring(1);
|
||||
}
|
||||
int firstParenIndex = toMatch.indexOf('(');
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
@@ -677,7 +673,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
/**
|
||||
* Match up args against unbound arguments of primitive types.
|
||||
* Match up args against unbound arguments of primitive types
|
||||
*/
|
||||
private void maybeBindPrimitiveArgsFromPointcutExpression() {
|
||||
int numUnboundPrimitives = countNumberOfUnboundPrimitiveArguments();
|
||||
@@ -687,7 +683,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
if (numUnboundPrimitives == 1) {
|
||||
// Look for arg variable and bind it if we find exactly one...
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
@@ -781,10 +777,9 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
|
||||
private int numTokensConsumed;
|
||||
|
||||
@Nullable
|
||||
private String text;
|
||||
|
||||
public PointcutBody(int tokens, @Nullable String text) {
|
||||
public PointcutBody(int tokens, String text) {
|
||||
this.numTokensConsumed = tokens;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
+3
-4
@@ -22,7 +22,6 @@ import java.lang.reflect.Type;
|
||||
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
import org.springframework.aop.AfterReturningAdvice;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.TypeUtils;
|
||||
|
||||
@@ -61,7 +60,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
|
||||
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
|
||||
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
|
||||
}
|
||||
@@ -76,7 +75,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
* @param returnValue the return value of the target method
|
||||
* @return whether to invoke the advice method for the given return value
|
||||
*/
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, @Nullable Object returnValue) {
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
|
||||
Class<?> type = getDiscoveredReturningType();
|
||||
Type genericType = getDiscoveredReturningGenericType();
|
||||
// If we aren't dealing with a raw type, check if generic parameters are assignable.
|
||||
@@ -95,7 +94,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
* @param returnValue the return value of the target method
|
||||
* @return whether to invoke the advice method for the given return value and type
|
||||
*/
|
||||
private boolean matchesReturnValue(Class<?> type, Method method, @Nullable Object returnValue) {
|
||||
private boolean matchesReturnValue(Class<?> type, Method method, Object returnValue) {
|
||||
if (returnValue != null) {
|
||||
return ClassUtils.isAssignableValue(type, returnValue);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.AfterAdvice;
|
||||
import org.springframework.aop.BeforeAdvice;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Utility methods for dealing with AspectJ advisors.
|
||||
@@ -59,7 +58,6 @@ public abstract class AspectJAopUtils {
|
||||
* If neither the advisor nor the advice have precedence information, this method
|
||||
* will return {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
|
||||
if (anAdvisor instanceof AspectJPrecedenceInformation) {
|
||||
return (AspectJPrecedenceInformation) anAdvisor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 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
-106
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,7 +19,6 @@ 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;
|
||||
@@ -55,10 +54,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -85,7 +81,7 @@ import org.springframework.util.StringUtils;
|
||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||
|
||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
|
||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
|
||||
|
||||
static {
|
||||
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
|
||||
@@ -103,23 +99,19 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
|
||||
|
||||
@Nullable
|
||||
private Class<?> pointcutDeclarationScope;
|
||||
|
||||
private String[] pointcutParameterNames = new String[0];
|
||||
|
||||
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
|
||||
|
||||
@Nullable
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Nullable
|
||||
private transient ClassLoader pointcutClassLoader;
|
||||
|
||||
@Nullable
|
||||
private transient PointcutExpression pointcutExpression;
|
||||
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
|
||||
|
||||
|
||||
/**
|
||||
@@ -174,13 +166,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
@Override
|
||||
public ClassFilter getClassFilter() {
|
||||
obtainPointcutExpression();
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
obtainPointcutExpression();
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -189,7 +181,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* Check whether this pointcut is ready to match,
|
||||
* lazily building the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private PointcutExpression obtainPointcutExpression() {
|
||||
private void checkReadyToMatch() {
|
||||
if (getExpression() == null) {
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
@@ -197,13 +189,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
this.pointcutClassLoader = determinePointcutClassLoader();
|
||||
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
|
||||
}
|
||||
return this.pointcutExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the ClassLoader to use for pointcut evaluation.
|
||||
*/
|
||||
@Nullable
|
||||
private ClassLoader determinePointcutClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
@@ -217,31 +207,25 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
|
||||
private PointcutExpression buildPointcutExpression(ClassLoader classLoader) {
|
||||
PointcutParser parser = initializePointcutParser(classLoader);
|
||||
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
|
||||
for (int i = 0; i < pointcutParameters.length; i++) {
|
||||
pointcutParameters[i] = parser.createPointcutParameter(
|
||||
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
|
||||
}
|
||||
return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
|
||||
return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()),
|
||||
this.pointcutDeclarationScope, pointcutParameters);
|
||||
}
|
||||
|
||||
private String resolveExpression() {
|
||||
String expression = getExpression();
|
||||
Assert.state(expression != null, "No expression set");
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the underlying AspectJ pointcut parser.
|
||||
*/
|
||||
private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
|
||||
private PointcutParser initializePointcutParser(ClassLoader cl) {
|
||||
PointcutParser parser = PointcutParser
|
||||
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
|
||||
SUPPORTED_PRIMITIVES, classLoader);
|
||||
parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
|
||||
SUPPORTED_PRIMITIVES, cl);
|
||||
parser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
|
||||
return parser;
|
||||
}
|
||||
|
||||
@@ -264,15 +248,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* Return the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
public PointcutExpression getPointcutExpression() {
|
||||
return obtainPointcutExpression();
|
||||
checkReadyToMatch();
|
||||
return this.pointcutExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> targetClass) {
|
||||
PointcutExpression pointcutExpression = obtainPointcutExpression();
|
||||
checkReadyToMatch();
|
||||
try {
|
||||
try {
|
||||
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
|
||||
@@ -290,9 +275,10 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
|
||||
obtainPointcutExpression();
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
checkReadyToMatch();
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
|
||||
|
||||
// Special handling for this, target, @this, @target, @annotation
|
||||
// in Spring - we can optimize since we know we have exactly this class,
|
||||
@@ -305,7 +291,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
else {
|
||||
// the maybe case
|
||||
if (hasIntroductions) {
|
||||
if (beanHasIntroductions) {
|
||||
return true;
|
||||
}
|
||||
// A match test returned maybe - if there are any subtype sensitive variables
|
||||
@@ -324,13 +310,15 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return obtainPointcutExpression().mayNeedDynamicTest();
|
||||
checkReadyToMatch();
|
||||
return this.pointcutExpression.mayNeedDynamicTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
obtainPointcutExpression();
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
checkReadyToMatch();
|
||||
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
|
||||
|
||||
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
|
||||
// consistent with return of MethodInvocationProceedingJoinPoint
|
||||
@@ -364,8 +352,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null && thisObject != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
@@ -385,7 +373,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
return ProxyCreationContext.getCurrentProxiedBeanName();
|
||||
}
|
||||
@@ -394,7 +381,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
/**
|
||||
* Get a new pointcut expression based on a target class's loader rather than the default.
|
||||
*/
|
||||
@Nullable
|
||||
private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
|
||||
try {
|
||||
ClassLoader classLoader = targetClass.getClassLoader();
|
||||
@@ -422,29 +408,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
// 'last man wins' which is not what we want at all.
|
||||
// Using the expression is guaranteed to be safe, since 2 identical expressions
|
||||
// are guaranteed to bind in exactly the same way.
|
||||
invocation.setUserAttribute(resolveExpression(), jpm);
|
||||
}
|
||||
|
||||
private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
if (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) {
|
||||
try {
|
||||
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
|
||||
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
|
||||
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
// Implemented interfaces probably expose conflicting method signatures...
|
||||
// Proceed with original target method.
|
||||
}
|
||||
}
|
||||
}
|
||||
return getShadowMatch(targetMethod, method);
|
||||
invocation.setUserAttribute(getExpression(), jpm);
|
||||
}
|
||||
|
||||
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
|
||||
@@ -454,12 +418,12 @@ 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);
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
@@ -474,16 +438,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
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).
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
catch (ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
@@ -492,7 +452,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
catch (ReflectionWorldException ex4) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
@@ -546,16 +506,18 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("AspectJExpressionPointcut: ");
|
||||
sb.append("(");
|
||||
for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
|
||||
sb.append(this.pointcutParameterTypes[i].getName());
|
||||
sb.append(" ");
|
||||
sb.append(this.pointcutParameterNames[i]);
|
||||
if ((i+1) < this.pointcutParameterTypes.length) {
|
||||
sb.append(", ");
|
||||
if (this.pointcutParameterNames != null && this.pointcutParameterTypes != null) {
|
||||
sb.append("(");
|
||||
for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
|
||||
sb.append(this.pointcutParameterTypes[i].getName());
|
||||
sb.append(" ");
|
||||
sb.append(this.pointcutParameterNames[i]);
|
||||
if ((i+1) < this.pointcutParameterTypes.length) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
sb.append(")");
|
||||
sb.append(" ");
|
||||
if (getExpression() != null) {
|
||||
sb.append(getExpression());
|
||||
@@ -566,19 +528,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization, just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
// pointcutExpression will be initialized lazily by checkReadyToMatch()
|
||||
this.shadowMatchCache = new ConcurrentHashMap<>(32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the Spring-specific {@code bean()} pointcut designator
|
||||
@@ -588,7 +537,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* automatically by examining a thread local variable and therefore a matching
|
||||
* context need not be set on the pointcut.
|
||||
*/
|
||||
private class BeanPointcutDesignatorHandler implements PointcutDesignatorHandler {
|
||||
private class BeanNamePointcutDesignatorHandler implements PointcutDesignatorHandler {
|
||||
|
||||
private static final String BEAN_DESIGNATOR_NAME = "bean";
|
||||
|
||||
@@ -599,7 +548,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
@Override
|
||||
public ContextBasedMatcher parse(String expression) {
|
||||
return new BeanContextMatcher(expression);
|
||||
return new BeanNameContextMatcher(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,11 +560,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* For static match tests, this matcher abstains to allow the overall
|
||||
* pointcut to match even when negation is used with the bean() pointcut.
|
||||
*/
|
||||
private class BeanContextMatcher implements ContextBasedMatcher {
|
||||
private class BeanNameContextMatcher implements ContextBasedMatcher {
|
||||
|
||||
private final NamePattern expressionPattern;
|
||||
|
||||
public BeanContextMatcher(String expression) {
|
||||
public BeanNameContextMatcher(String expression) {
|
||||
this.expressionPattern = new NamePattern(expression);
|
||||
}
|
||||
|
||||
@@ -648,7 +597,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
return false;
|
||||
}
|
||||
|
||||
private FuzzyBoolean contextMatch(@Nullable Class<?> targetType) {
|
||||
private FuzzyBoolean contextMatch(Class<?> targetType) {
|
||||
String advisedBeanName = getCurrentProxiedBeanName();
|
||||
if (advisedBeanName == null) { // no proxy creation in progress
|
||||
// abstain; can't return YES, since that will make pointcut with negation fail
|
||||
@@ -660,21 +609,45 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
if (targetType != null) {
|
||||
boolean isFactory = FactoryBean.class.isAssignableFrom(targetType);
|
||||
return FuzzyBoolean.fromBoolean(
|
||||
matchesBean(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
|
||||
matchesBeanName(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
|
||||
}
|
||||
else {
|
||||
return FuzzyBoolean.fromBoolean(matchesBean(advisedBeanName) ||
|
||||
matchesBean(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
|
||||
return FuzzyBoolean.fromBoolean(matchesBeanName(advisedBeanName) ||
|
||||
matchesBeanName(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesBean(String advisedBeanName) {
|
||||
return BeanFactoryAnnotationUtils.isQualifierMatch(
|
||||
this.expressionPattern::matches, advisedBeanName, beanFactory);
|
||||
private boolean matchesBeanName(String advisedBeanName) {
|
||||
if (this.expressionPattern.matches(advisedBeanName)) {
|
||||
return true;
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
String[] aliases = beanFactory.getAliases(advisedBeanName);
|
||||
for (String alias : aliases) {
|
||||
if (this.expressionPattern.matches(alias)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Serialization support
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||
// Rely on default serialization, just initialize state after deserialization.
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
// pointcutExpression will be initialized lazily by checkReadyToMatch()
|
||||
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
|
||||
}
|
||||
|
||||
|
||||
private static class DefensiveShadowMatch implements ShadowMatch {
|
||||
|
||||
private final ShadowMatch primary;
|
||||
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2016 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 org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Spring AOP Advisor that can be used for any AspectJ pointcut expression.
|
||||
@@ -34,20 +33,18 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
|
||||
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
public void setExpression(@Nullable String expression) {
|
||||
public void setExpression(String expression) {
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
public void setLocation(@Nullable String location) {
|
||||
public void setLocation(String location) {
|
||||
this.pointcut.setLocation(location);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getLocation() {
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
+1
-2
@@ -20,7 +20,6 @@ import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Spring AOP advice that wraps an AspectJ before method.
|
||||
@@ -40,7 +39,7 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
|
||||
|
||||
|
||||
@Override
|
||||
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, null);
|
||||
}
|
||||
|
||||
|
||||
+10
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2017 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 org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -38,12 +37,11 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
|
||||
private final Pointcut pointcut;
|
||||
|
||||
@Nullable
|
||||
private Integer order;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectJPointcutAdvisor for the given advice.
|
||||
* Create a new AspectJPointcutAdvisor for the given advice
|
||||
* @param advice the AbstractAspectJAdvice to wrap
|
||||
*/
|
||||
public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) {
|
||||
@@ -57,16 +55,6 @@ 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;
|
||||
@@ -82,13 +70,14 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.order != null) {
|
||||
return this.order;
|
||||
}
|
||||
else {
|
||||
return this.advice.getOrder();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2006 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.
|
||||
|
||||
/**
|
||||
* Return the name of the aspect (bean) in which the advice was declared.
|
||||
* The name of the aspect (bean) in which the advice was declared.
|
||||
*/
|
||||
String getAspectName();
|
||||
|
||||
/**
|
||||
* Return the declaration order of the advice member within the aspect.
|
||||
* The declaration order of the advice member within the aspect.
|
||||
*/
|
||||
int getDeclarationOrder();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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,8 +36,8 @@ public abstract class AspectJProxyUtils {
|
||||
* This will expose the current Spring AOP invocation (necessary for some AspectJ pointcut matching)
|
||||
* and make available the current AspectJ JoinPoint. The call will have no effect if there are no
|
||||
* AspectJ advisors in the advisor chain.
|
||||
* @param advisors the advisors available
|
||||
* @return {@code true} if any special {@link Advisor Advisors} were added, otherwise {@code false}
|
||||
* @param advisors Advisors available
|
||||
* @return {@code true} if any special {@link Advisor Advisors} were added, otherwise {@code false}.
|
||||
*/
|
||||
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
|
||||
// Don't add advisors to an empty list; may indicate that proxying is just not required
|
||||
@@ -66,7 +66,7 @@ public abstract class AspectJProxyUtils {
|
||||
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
|
||||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
|
||||
(advisor instanceof PointcutAdvisor &&
|
||||
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
|
||||
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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 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;
|
||||
@@ -35,12 +34,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.
|
||||
@@ -49,8 +48,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param defaultImpl the default implementation class
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
|
||||
this(interfaceType, typePattern,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
this(interfaceType, typePattern, defaultImpl,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,24 +59,32 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param delegateRef the delegate implementation object
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
|
||||
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(delegateRef));
|
||||
this(interfaceType, typePattern, delegateRef.getClass(),
|
||||
new DelegatingIntroductionInterceptor(delegateRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to share common code between impl-based delegate and reference-based delegate
|
||||
* (cannot use method such as init() to share common code, due the use of final fields).
|
||||
* (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 interceptor the delegation advice as {@link IntroductionInterceptor}
|
||||
* @param implementationClass implementation class
|
||||
* @param advice delegation advice
|
||||
*/
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
|
||||
this.advice = interceptor;
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
|
||||
this.introducedInterface = interfaceType;
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
|
||||
// Excludes methods implemented.
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
ClassFilter exclusion = (clazz -> !this.introducedInterface.isAssignableFrom(clazz));
|
||||
ClassFilter exclusion = new ClassFilter() {
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
return !(introducedInterface.isAssignableFrom(clazz));
|
||||
}
|
||||
};
|
||||
|
||||
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
|
||||
this.advice = advice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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,19 +29,20 @@ import org.aspectj.runtime.internal.AroundClosure;
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
|
||||
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
|
||||
* Implementation of AspectJ ProceedingJoinPoint interface
|
||||
* wrapping an AOP Alliance 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 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.
|
||||
* {@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.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -55,15 +56,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
@Nullable
|
||||
private Object[] args;
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
|
||||
/** Lazily initialized signature object. */
|
||||
@Nullable
|
||||
/** Lazily initialized signature object */
|
||||
private Signature signature;
|
||||
|
||||
/** Lazily initialized source location object. */
|
||||
@Nullable
|
||||
/** Lazily initialized source location object */
|
||||
private SourceLocation sourceLocation;
|
||||
|
||||
|
||||
@@ -77,7 +75,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
this.methodInvocation = methodInvocation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void set$AroundClosure(AroundClosure aroundClosure) {
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -112,17 +109,18 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
* Returns the Spring AOP target. May be {@code null} if there is no target.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getTarget() {
|
||||
return this.methodInvocation.getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArgs() {
|
||||
if (this.args == null) {
|
||||
this.args = this.methodInvocation.getArguments().clone();
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
this.defensiveCopyOfArgs = new Object[argsSource.length];
|
||||
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
|
||||
}
|
||||
return this.args;
|
||||
return this.defensiveCopyOfArgs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,7 +128,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
}
|
||||
return this.signature;
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,7 +176,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
*/
|
||||
private class MethodSignatureImpl implements MethodSignature {
|
||||
|
||||
@Nullable
|
||||
private volatile String[] parameterNames;
|
||||
|
||||
@Override
|
||||
@@ -217,7 +214,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames() {
|
||||
if (this.parameterNames == null) {
|
||||
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -37,7 +37,6 @@ import org.aspectj.weaver.reflect.ReflectionVar;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -51,7 +50,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* migrate to {@code ShadowMatch.getVariablesInvolvedInRuntimeTest()}
|
||||
* or some similar operation.
|
||||
*
|
||||
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593">Bug 151593</a>
|
||||
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>Bug 151593</a>
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Ramnivas Laddad
|
||||
@@ -79,7 +78,6 @@ class RuntimeTestWalker {
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private final Test runtimeTest;
|
||||
|
||||
|
||||
@@ -175,7 +173,7 @@ class RuntimeTestWalker {
|
||||
}
|
||||
|
||||
|
||||
private abstract static class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private final Class<?> matchClass;
|
||||
|
||||
|
||||
+3
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,13 +16,9 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AspectInstanceFactory} that creates a new instance
|
||||
@@ -45,7 +41,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
this.aspectClass = aspectClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the specified aspect class (never {@code null}).
|
||||
*/
|
||||
@@ -53,14 +48,11 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Object getAspectInstance() {
|
||||
try {
|
||||
return ReflectionUtils.accessibleConstructor(this.aspectClass).newInstance();
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new AopConfigException(
|
||||
"No default constructor on aspect class: " + this.aspectClass.getName(), ex);
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException(
|
||||
@@ -70,14 +62,9 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new AopConfigException(
|
||||
"Failed to invoke aspect constructor: " + this.aspectClass.getName(), ex.getTargetException());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectClass.getClassLoader();
|
||||
}
|
||||
|
||||
-2
@@ -19,7 +19,6 @@ package org.springframework.aop.aspectj;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -54,7 +53,6 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectInstance.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
+5
-3
@@ -20,7 +20,6 @@ import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.TypePatternMatcher;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -33,9 +32,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class TypePatternClassFilter implements ClassFilter {
|
||||
|
||||
private String typePattern = "";
|
||||
private String typePattern;
|
||||
|
||||
@Nullable
|
||||
private TypePatternMatcher aspectJTypePatternMatcher;
|
||||
|
||||
|
||||
@@ -53,6 +51,8 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* Create a fully configured {@link TypePatternClassFilter} using the
|
||||
* given type pattern.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied {@code typePattern} is {@code null}
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public TypePatternClassFilter(String typePattern) {
|
||||
setTypePattern(typePattern);
|
||||
@@ -73,6 +73,8 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* that implements it.
|
||||
* <p>These conventions are established by AspectJ, not Spring AOP.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied {@code typePattern} is {@code null}
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public void setTypePattern(String typePattern) {
|
||||
Assert.notNull(typePattern, "Type pattern must not be null");
|
||||
|
||||
+53
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -41,7 +41,7 @@ import org.aspectj.lang.reflect.PerClauseKind;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for factories that can create Spring AOP Advisors
|
||||
@@ -59,11 +59,8 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
|
||||
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
|
||||
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();
|
||||
@@ -125,13 +122,14 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...).
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
|
||||
Class<?>[] classesToLookFor = new Class<?>[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<?> c : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
@@ -139,11 +137,10 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<>(result);
|
||||
return new AspectJAnnotation<A>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
@@ -151,34 +148,35 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enum for AspectJ annotation types.
|
||||
* @see AspectJAnnotation#getAnnotationType()
|
||||
*/
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
AtAfterReturning,
|
||||
AtAfterThrowing,
|
||||
AtAround
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class modelling an AspectJ annotation, exposing its type enumeration and
|
||||
* pointcut String.
|
||||
* @param <A> the annotation type
|
||||
*/
|
||||
protected static class AspectJAnnotation<A extends Annotation> {
|
||||
|
||||
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
|
||||
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypes =
|
||||
new HashMap<Class<?>, AspectJAnnotationType>();
|
||||
|
||||
static {
|
||||
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
|
||||
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
|
||||
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
|
||||
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
|
||||
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
|
||||
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
|
||||
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
|
||||
}
|
||||
|
||||
private final A annotation;
|
||||
@@ -192,35 +190,44 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
public AspectJAnnotation(A annotation) {
|
||||
this.annotation = annotation;
|
||||
this.annotationType = determineAnnotationType(annotation);
|
||||
// We know these methods exist with the same name on each object,
|
||||
// but need to invoke them reflectively as there isn't a common interface.
|
||||
try {
|
||||
this.pointcutExpression = resolveExpression(annotation);
|
||||
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
|
||||
this.argumentNames = (argNames instanceof String ? (String) argNames : "");
|
||||
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
|
||||
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private AspectJAnnotationType determineAnnotationType(A annotation) {
|
||||
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
|
||||
if (type != null) {
|
||||
return type;
|
||||
for (Class<?> type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(annotation)) {
|
||||
return annotationTypes.get(type);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation);
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
|
||||
}
|
||||
|
||||
private String resolveExpression(A annotation) {
|
||||
for (String attributeName : EXPRESSION_ATTRIBUTES) {
|
||||
Object val = AnnotationUtils.getValue(annotation, attributeName);
|
||||
if (val instanceof String) {
|
||||
String str = (String) val;
|
||||
if (!str.isEmpty()) {
|
||||
return str;
|
||||
private String resolveExpression(A annotation) throws Exception {
|
||||
String expression = null;
|
||||
for (String methodName : EXPRESSION_PROPERTIES) {
|
||||
Method method;
|
||||
try {
|
||||
method = annotation.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
method = null;
|
||||
}
|
||||
if (method != null) {
|
||||
String candidate = (String) method.invoke(annotation);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
expression = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to resolve expression: " + annotation);
|
||||
return expression;
|
||||
}
|
||||
|
||||
public AspectJAnnotationType getAnnotationType() {
|
||||
@@ -253,20 +260,19 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames(Method method) {
|
||||
if (method.getParameterCount() == 0) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
return new String[0];
|
||||
}
|
||||
AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (nameTokens.countTokens() > 0) {
|
||||
String[] names = new String[nameTokens.countTokens()];
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (strTok.countTokens() > 0) {
|
||||
String[] names = new String[strTok.countTokens()];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = nameTokens.nextToken();
|
||||
names[i] = strTok.nextToken();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
@@ -276,7 +282,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String[] getParameterNames(Constructor<?> ctor) {
|
||||
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
|
||||
}
|
||||
|
||||
+4
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -24,7 +24,6 @@ import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -49,13 +48,10 @@ import org.springframework.util.Assert;
|
||||
@SuppressWarnings("serial")
|
||||
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
|
||||
|
||||
@Nullable
|
||||
private List<Pattern> includePatterns;
|
||||
|
||||
@Nullable
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory;
|
||||
|
||||
@Nullable
|
||||
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
|
||||
|
||||
|
||||
@@ -64,7 +60,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
* <p>Default is to consider all @AspectJ beans as eligible.
|
||||
*/
|
||||
public void setIncludePatterns(List<String> patterns) {
|
||||
this.includePatterns = new ArrayList<>(patterns.size());
|
||||
this.includePatterns = new ArrayList<Pattern>(patterns.size());
|
||||
for (String patternText : patterns) {
|
||||
this.includePatterns.add(Pattern.compile(patternText));
|
||||
}
|
||||
@@ -91,9 +87,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
// Add all the Spring advisors found according to superclass rules.
|
||||
List<Advisor> advisors = super.findCandidateAdvisors();
|
||||
// Build Advisors for all AspectJ aspects in the bean factory.
|
||||
if (this.aspectJAdvisorsBuilder != null) {
|
||||
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
|
||||
}
|
||||
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
|
||||
return advisors;
|
||||
}
|
||||
|
||||
@@ -107,8 +101,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
// proxied by that interface and fail at runtime as the advice method is not
|
||||
// defined on the interface. We could potentially relax the restriction about
|
||||
// not advising aspects in the future.
|
||||
return (super.isInfrastructureClass(beanClass) ||
|
||||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
|
||||
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-3
@@ -24,7 +24,6 @@ import org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Interface for factories that can create Spring AOP Advisors from classes
|
||||
@@ -80,7 +79,6 @@ public interface AspectJAdvisorFactory {
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
* create a Spring advice in its own right
|
||||
*/
|
||||
@Nullable
|
||||
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
int declarationOrder, String aspectName);
|
||||
|
||||
@@ -100,7 +98,6 @@ public interface AspectJAdvisorFactory {
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
|
||||
*/
|
||||
@Nullable
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
|
||||
|
||||
|
||||
+17
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -24,7 +24,7 @@ import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyCreatorSupport;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
@@ -49,8 +49,8 @@ import org.springframework.util.ClassUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/** Cache for singleton aspect instances. */
|
||||
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();
|
||||
/** Cache for singleton aspect instances */
|
||||
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<Class<?>, Object>();
|
||||
|
||||
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
@@ -119,9 +119,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
*/
|
||||
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
|
||||
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
|
||||
Class<?> targetClass = getTargetClass();
|
||||
Assert.state(targetClass != null, "Unresolvable target class");
|
||||
advisors = AopUtils.findAdvisorsThatCanApply(advisors, targetClass);
|
||||
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
|
||||
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
|
||||
AnnotationAwareOrderComparator.sort(advisors);
|
||||
addAdvisors(advisors);
|
||||
@@ -170,9 +168,19 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
synchronized (aspectCache) {
|
||||
// To be safe, check within full lock now...
|
||||
instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+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 name.
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
|
||||
+18
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -55,33 +54,27 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
* Create a BeanFactoryAspectInstanceFactory. AspectJ will be called to
|
||||
* introspect to create AJType metadata using the type returned for the
|
||||
* given bean name from the BeanFactory.
|
||||
* @param beanFactory the BeanFactory to obtain instance(s) from
|
||||
* @param beanFactory BeanFactory to obtain instance(s) from
|
||||
* @param name name of the bean
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
|
||||
this(beanFactory, name, null);
|
||||
this(beanFactory, name, beanFactory.getType(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a BeanFactoryAspectInstanceFactory, providing a type that AspectJ should
|
||||
* introspect to create AJType metadata. Use if the BeanFactory may consider the type
|
||||
* to be a subclass (as when using CGLIB), and the information should relate to a superclass.
|
||||
* @param beanFactory the BeanFactory to obtain instance(s) from
|
||||
* @param beanFactory BeanFactory to obtain instance(s) from
|
||||
* @param name the name of the bean
|
||||
* @param type the type that should be introspected by AspectJ
|
||||
* ({@code null} indicates resolution through {@link BeanFactory#getType} via the bean name)
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, @Nullable Class<?> type) {
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(name, "Bean name must not be null");
|
||||
this.beanFactory = beanFactory;
|
||||
this.name = name;
|
||||
Class<?> resolvedType = type;
|
||||
if (type == null) {
|
||||
resolvedType = beanFactory.getType(name);
|
||||
Assert.notNull(resolvedType, "Unresolvable bean type - explicitly specify the aspect class");
|
||||
}
|
||||
this.aspectMetadata = new AspectMetadata(resolvedType, name);
|
||||
this.aspectMetadata = new AspectMetadata(type, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +84,6 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
@@ -104,21 +96,20 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getAspectCreationMutex() {
|
||||
if (this.beanFactory.isSingleton(this.name)) {
|
||||
// Rely on singleton semantics provided by the factory -> no local lock.
|
||||
return null;
|
||||
}
|
||||
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
else {
|
||||
return this;
|
||||
if (this.beanFactory != null) {
|
||||
if (this.beanFactory.isSingleton(name)) {
|
||||
// Rely on singleton semantics provided by the factory -> no local lock.
|
||||
return null;
|
||||
}
|
||||
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,8 +16,8 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -27,7 +27,6 @@ import org.aspectj.lang.reflect.PerClauseKind;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -44,12 +43,12 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private final AspectJAdvisorFactory advisorFactory;
|
||||
|
||||
@Nullable
|
||||
private volatile List<String> aspectBeanNames;
|
||||
|
||||
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
|
||||
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<String, List<Advisor>>();
|
||||
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
|
||||
new ConcurrentHashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -87,8 +86,8 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
aspectNames = new ArrayList<>();
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
@@ -138,7 +137,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
if (aspectNames.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (String aspectName : aspectNames) {
|
||||
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
|
||||
if (cachedAdvisors != null) {
|
||||
|
||||
+53
-63
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -31,7 +31,6 @@ import org.springframework.aop.aspectj.InstantiationModelAwarePointcutAdvisor;
|
||||
import org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.AspectJAnnotation;
|
||||
import org.springframework.aop.support.DynamicMethodMatcherPointcut;
|
||||
import org.springframework.aop.support.Pointcuts;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Internal implementation of AspectJPointcutAdvisor.
|
||||
@@ -42,12 +41,9 @@ import org.springframework.lang.Nullable;
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
class InstantiationModelAwarePointcutAdvisorImpl
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
|
||||
|
||||
private static final Advice EMPTY_ADVICE = new Advice() {};
|
||||
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
@@ -70,13 +66,10 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
private final boolean lazy;
|
||||
|
||||
@Nullable
|
||||
private Advice instantiatedAdvice;
|
||||
|
||||
@Nullable
|
||||
private Boolean isBeforeAdvice;
|
||||
|
||||
@Nullable
|
||||
private Boolean isAfterAdvice;
|
||||
|
||||
|
||||
@@ -116,41 +109,14 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
|
||||
/**
|
||||
* The pointcut for Spring AOP to use.
|
||||
* Actual behaviour of the pointcut will change depending on the state of the advice.
|
||||
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
|
||||
* depending on the state of the advice.
|
||||
*/
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
|
||||
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return (advice != null ? advice : EMPTY_ADVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only of interest for Spring AOP: AspectJ instantiation semantics
|
||||
* are much richer. In AspectJ terminology, all a return of {@code true}
|
||||
@@ -168,6 +134,33 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.aspectInstanceFactory.getAspectMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
return this.aspectInstanceFactory;
|
||||
}
|
||||
@@ -220,26 +213,33 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
else {
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
case AtAround:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isBeforeAdvice = true;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtAfter:
|
||||
case AtAfterReturning:
|
||||
case AtAfterThrowing:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = true;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtAround:
|
||||
case AtPointcut:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
@@ -250,31 +250,22 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
|
||||
* if it does not at first match statically.
|
||||
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
|
||||
* be optimized out if it does not at first match statically.
|
||||
*/
|
||||
private final class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
|
||||
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private final Pointcut preInstantiationPointcut;
|
||||
|
||||
@Nullable
|
||||
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
|
||||
|
||||
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
this.preInstantiationPointcut = preInstantiationPointcut;
|
||||
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
|
||||
@@ -284,8 +275,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
// We're either instantiated and matching on declared pointcut,
|
||||
// or uninstantiated matching on either pointcut...
|
||||
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
|
||||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
|
||||
}
|
||||
|
||||
+6
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2016 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,7 +18,6 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -33,7 +32,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory maaif;
|
||||
|
||||
@Nullable
|
||||
private volatile Object materialized;
|
||||
|
||||
|
||||
@@ -49,24 +47,20 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
Object aspectInstance = this.materialized;
|
||||
if (aspectInstance == null) {
|
||||
if (this.materialized == null) {
|
||||
Object mutex = this.maaif.getAspectCreationMutex();
|
||||
if (mutex == null) {
|
||||
aspectInstance = this.maaif.getAspectInstance();
|
||||
this.materialized = aspectInstance;
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
else {
|
||||
synchronized (mutex) {
|
||||
aspectInstance = this.materialized;
|
||||
if (aspectInstance == null) {
|
||||
aspectInstance = this.maaif.getAspectInstance();
|
||||
this.materialized = aspectInstance;
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return aspectInstance;
|
||||
return this.materialized;
|
||||
}
|
||||
|
||||
public boolean isMaterialized() {
|
||||
@@ -74,7 +68,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.maaif.getAspectClassLoader();
|
||||
}
|
||||
@@ -85,7 +78,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getAspectCreationMutex() {
|
||||
return this.maaif.getAspectCreationMutex();
|
||||
}
|
||||
|
||||
-2
@@ -17,7 +17,6 @@
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectInstanceFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Subinterface of {@link org.springframework.aop.aspectj.AspectInstanceFactory}
|
||||
@@ -45,7 +44,6 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
|
||||
* @return the mutex object (may be {@code null} for no mutex to use)
|
||||
* @since 4.3
|
||||
*/
|
||||
@Nullable
|
||||
Object getAspectCreationMutex();
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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,7 @@ import org.springframework.aop.framework.AopConfigException;
|
||||
@SuppressWarnings("serial")
|
||||
public class NotAnAtAspectException extends AopConfigException {
|
||||
|
||||
private final Class<?> nonAspectClass;
|
||||
private Class<?> nonAspectClass;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+52
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,8 +20,9 @@ import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
@@ -49,9 +50,9 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConvertingComparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.comparator.CompoundComparator;
|
||||
import org.springframework.util.comparator.InstanceComparator;
|
||||
|
||||
/**
|
||||
@@ -72,20 +73,29 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
static {
|
||||
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
|
||||
new InstanceComparator<>(
|
||||
CompoundComparator<Method> comparator = new CompoundComparator<Method>();
|
||||
comparator.addComparator(new ConvertingComparator<Method, Annotation>(
|
||||
new InstanceComparator<Annotation>(
|
||||
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
|
||||
(Converter<Method, Annotation>) method -> {
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
});
|
||||
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
|
||||
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
|
||||
new Converter<Method, Annotation>() {
|
||||
@Override
|
||||
public Annotation convert(Method method) {
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
}
|
||||
}));
|
||||
comparator.addComparator(new ConvertingComparator<Method, String>(
|
||||
new Converter<Method, String>() {
|
||||
@Override
|
||||
public String convert(Method method) {
|
||||
return method.getName();
|
||||
}
|
||||
}));
|
||||
METHOD_COMPARATOR = comparator;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
|
||||
@@ -105,7 +115,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
* @see AspectJExpressionPointcut#setBeanFactory
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader()
|
||||
*/
|
||||
public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
|
||||
public ReflectiveAspectJAdvisorFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@@ -121,7 +131,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
|
||||
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
@@ -147,14 +157,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
|
||||
final List<Method> methods = new ArrayList<>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, method -> {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
methods.add(method);
|
||||
final List<Method> methods = new LinkedList<Method>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
});
|
||||
methods.sort(METHOD_COMPARATOR);
|
||||
Collections.sort(methods, METHOD_COMPARATOR);
|
||||
return methods;
|
||||
}
|
||||
|
||||
@@ -163,9 +176,8 @@ 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 the Advisor instance, or {@code null} if not an Advisor
|
||||
* @return {@code null} if not an Advisor
|
||||
*/
|
||||
@Nullable
|
||||
private Advisor getDeclareParentsAdvisor(Field introductionField) {
|
||||
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
|
||||
if (declareParents == null) {
|
||||
@@ -183,7 +195,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
@@ -199,7 +210,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
|
||||
@@ -210,15 +220,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
|
||||
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
|
||||
if (this.beanFactory != null) {
|
||||
ajexp.setBeanFactory(this.beanFactory);
|
||||
}
|
||||
ajexp.setBeanFactory(this.beanFactory);
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
|
||||
|
||||
@@ -246,15 +253,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
AbstractAspectJAdvice springAdvice;
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
@@ -279,6 +277,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
@@ -292,7 +299,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
springAdvice.setArgumentNamesFromStringArray(argNames);
|
||||
}
|
||||
springAdvice.calculateArgumentBindings();
|
||||
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
@@ -306,8 +312,13 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
|
||||
|
||||
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
|
||||
(method, args, target) -> aif.getAspectInstance());
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
|
||||
@Override
|
||||
public void before(Method method, Object[] args, Object target) {
|
||||
// Simply instantiate the aspect
|
||||
aif.getAspectInstance();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,4 @@
|
||||
*
|
||||
* <p>Normally to be used through an AspectJAutoProxyCreator rather than directly.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
|
||||
+10
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2013 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,16 @@ 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<PartiallyComparableAdvisorHolder>(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());
|
||||
List<Advisor> result = new ArrayList<Advisor>(advisors.size());
|
||||
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
|
||||
result.add(pcAdvisor.getAdvisor());
|
||||
}
|
||||
@@ -100,9 +102,10 @@ 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 &&
|
||||
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
|
||||
return true;
|
||||
if (advisor instanceof AspectJPointcutAdvisor) {
|
||||
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.shouldSkip(beanClass, beanName);
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -132,9 +132,7 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
|
||||
// pre-condition is that hasAspectName returned true
|
||||
private String getAspectName(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation pi = AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
Assert.state(pi != null, "Unresolvable precedence information");
|
||||
return pi.getAspectName();
|
||||
return AspectJAopUtils.getAspectJPrecedenceInformationFor(anAdvisor).getAspectName();
|
||||
}
|
||||
|
||||
private int getAspectDeclarationOrder(Advisor anAdvisor) {
|
||||
|
||||
@@ -2,9 +2,4 @@
|
||||
* Base classes enabling auto-proxying based on AspectJ.
|
||||
* Support for AspectJ annotation aspects resides in the "aspectj.annotation" package.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
|
||||
@@ -8,9 +8,4 @@
|
||||
* or AspectJ load-time weaver. It is intended to enable the use of a valuable subset of AspectJ
|
||||
* functionality, with consistent semantics, with the proxy-based Spring AOP framework.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -30,7 +30,6 @@ import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -106,8 +105,8 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addInterceptorNameToList(String interceptorName, BeanDefinition beanDefinition) {
|
||||
List<String> list = (List<String>) beanDefinition.getPropertyValues().get("interceptorNames");
|
||||
Assert.state(list != null, "Missing 'interceptorNames' property");
|
||||
List<String> list = (List<String>)
|
||||
beanDefinition.getPropertyValues().getPropertyValue("interceptorNames").getValue();
|
||||
list.add(interceptorName);
|
||||
}
|
||||
|
||||
@@ -116,9 +115,7 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
}
|
||||
|
||||
protected String getInterceptorNameSuffix(BeanDefinition interceptorDefinition) {
|
||||
String beanClassName = interceptorDefinition.getBeanClassName();
|
||||
return (StringUtils.hasLength(beanClassName) ?
|
||||
StringUtils.uncapitalize(ClassUtils.getShortName(beanClassName)) : "");
|
||||
return StringUtils.uncapitalize(ClassUtils.getShortName(interceptorDefinition.getBeanClassName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+19
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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 org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.parsing.AbstractComponentDefinition;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -39,28 +38,31 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
|
||||
private final BeanDefinition advisorDefinition;
|
||||
|
||||
private final String description;
|
||||
private String description;
|
||||
|
||||
private final BeanReference[] beanReferences;
|
||||
private BeanReference[] beanReferences;
|
||||
|
||||
private final BeanDefinition[] beanDefinitions;
|
||||
private BeanDefinition[] beanDefinitions;
|
||||
|
||||
|
||||
public AdvisorComponentDefinition(String advisorBeanName, BeanDefinition advisorDefinition) {
|
||||
this(advisorBeanName, advisorDefinition, null);
|
||||
this(advisorBeanName, advisorDefinition, null);
|
||||
}
|
||||
|
||||
public AdvisorComponentDefinition(
|
||||
String advisorBeanName, BeanDefinition advisorDefinition, @Nullable BeanDefinition pointcutDefinition) {
|
||||
String advisorBeanName, BeanDefinition advisorDefinition, BeanDefinition pointcutDefinition) {
|
||||
|
||||
Assert.notNull(advisorBeanName, "'advisorBeanName' must not be null");
|
||||
Assert.notNull(advisorDefinition, "'advisorDefinition' must not be null");
|
||||
this.advisorBeanName = advisorBeanName;
|
||||
this.advisorDefinition = advisorDefinition;
|
||||
unwrapDefinitions(advisorDefinition, pointcutDefinition);
|
||||
}
|
||||
|
||||
|
||||
private void unwrapDefinitions(BeanDefinition advisorDefinition, BeanDefinition pointcutDefinition) {
|
||||
MutablePropertyValues pvs = advisorDefinition.getPropertyValues();
|
||||
BeanReference adviceReference = (BeanReference) pvs.get("adviceBeanName");
|
||||
Assert.state(adviceReference != null, "Missing 'adviceBeanName' property");
|
||||
BeanReference adviceReference = (BeanReference) pvs.getPropertyValue("adviceBeanName").getValue();
|
||||
|
||||
if (pointcutDefinition != null) {
|
||||
this.beanReferences = new BeanReference[] {adviceReference};
|
||||
@@ -68,8 +70,7 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
this.description = buildDescription(adviceReference, pointcutDefinition);
|
||||
}
|
||||
else {
|
||||
BeanReference pointcutReference = (BeanReference) pvs.get("pointcut");
|
||||
Assert.state(pointcutReference != null, "Missing 'pointcut' property");
|
||||
BeanReference pointcutReference = (BeanReference) pvs.getPropertyValue("pointcut").getValue();
|
||||
this.beanReferences = new BeanReference[] {adviceReference, pointcutReference};
|
||||
this.beanDefinitions = new BeanDefinition[] {advisorDefinition};
|
||||
this.description = buildDescription(adviceReference, pointcutReference);
|
||||
@@ -77,15 +78,16 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
}
|
||||
|
||||
private String buildDescription(BeanReference adviceReference, BeanDefinition pointcutDefinition) {
|
||||
return "Advisor <advice(ref)='" +
|
||||
adviceReference.getBeanName() + "', pointcut(expression)=[" +
|
||||
pointcutDefinition.getPropertyValues().get("expression") + "]>";
|
||||
return new StringBuilder("Advisor <advice(ref)='").
|
||||
append(adviceReference.getBeanName()).append("', pointcut(expression)=[").
|
||||
append(pointcutDefinition.getPropertyValues().getPropertyValue("expression").getValue()).
|
||||
append("]>").toString();
|
||||
}
|
||||
|
||||
private String buildDescription(BeanReference adviceReference, BeanReference pointcutReference) {
|
||||
return "Advisor <advice(ref)='" +
|
||||
adviceReference.getBeanName() + "', pointcut(ref)='" +
|
||||
pointcutReference.getBeanName() + "'>";
|
||||
return new StringBuilder("Advisor <advice(ref)='").
|
||||
append(adviceReference.getBeanName()).append("', pointcut(ref)='").
|
||||
append(pointcutReference.getBeanName()).append("'>").toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +112,6 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getSource() {
|
||||
return this.advisorDefinition.getSource();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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,16 +26,16 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class for handling registration of AOP auto-proxy creators.
|
||||
*
|
||||
* <p>Only a single auto-proxy creator should be registered yet multiple concrete
|
||||
* implementations are available. This class provides a simple escalation protocol,
|
||||
* allowing a caller to request a particular auto-proxy creator and know that creator,
|
||||
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
|
||||
* <p>Only a single auto-proxy creator can be registered yet multiple concrete
|
||||
* implementations are available. Therefore this class wraps a simple escalation
|
||||
* protocol, allowing classes to request a particular auto-proxy creator and know
|
||||
* that class, {@code or a subclass thereof}, will eventually be resident
|
||||
* in the application context.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -54,49 +54,39 @@ public abstract class AopConfigUtils {
|
||||
/**
|
||||
* Stores the auto proxy creator classes in escalation order.
|
||||
*/
|
||||
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
|
||||
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>();
|
||||
|
||||
/**
|
||||
* Setup the escalation list.
|
||||
*/
|
||||
static {
|
||||
// Set up the escalation list...
|
||||
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
|
||||
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
|
||||
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
|
||||
return registerAutoProxyCreatorIfNecessary(registry, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
|
||||
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
|
||||
return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
|
||||
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
|
||||
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
|
||||
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
|
||||
@@ -114,12 +104,9 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(
|
||||
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
|
||||
|
||||
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
|
||||
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
|
||||
@@ -131,7 +118,6 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
|
||||
beanDefinition.setSource(source);
|
||||
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
|
||||
@@ -144,7 +130,7 @@ public abstract class AopConfigUtils {
|
||||
return APC_PRIORITY_LIST.indexOf(clazz);
|
||||
}
|
||||
|
||||
private static int findPriorityForClass(@Nullable String className) {
|
||||
private static int findPriorityForClass(String className) {
|
||||
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
|
||||
Class<?> clazz = APC_PRIORITY_LIST.get(i);
|
||||
if (clazz.getName().equals(className)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -22,17 +22,16 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Utility class for handling registration of auto-proxy creators used internally
|
||||
* by the '{@code aop}' namespace tags.
|
||||
*
|
||||
* <p>Only a single auto-proxy creator should be registered and multiple configuration
|
||||
* elements may wish to register different concrete implementations. As such this class
|
||||
* delegates to {@link AopConfigUtils} which provides a simple escalation protocol.
|
||||
* Callers may request a particular auto-proxy creator and know that creator,
|
||||
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
|
||||
* <p>Only a single auto-proxy creator can be registered and multiple tags may wish
|
||||
* to register different concrete implementations. As such this class delegates to
|
||||
* {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
|
||||
* may request a particular auto-proxy creator and know that class, <i>or a subclass
|
||||
* thereof</i>, will eventually be resident in the application context.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -80,23 +79,24 @@ public abstract class AopNamespaceUtils {
|
||||
registerComponentIfNecessary(beanDefinition, parserContext);
|
||||
}
|
||||
|
||||
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
|
||||
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
|
||||
if (sourceElement != null) {
|
||||
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
|
||||
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
|
||||
if (proxyTargetClass) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
|
||||
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
|
||||
if (exposeProxy) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
|
||||
private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) {
|
||||
if (beanDefinition != null) {
|
||||
parserContext.registerComponent(
|
||||
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
parserContext.registerComponent(componentDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2007 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,7 +19,6 @@ package org.springframework.aop.config;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.parsing.ComponentDefinition}
|
||||
@@ -38,8 +37,8 @@ public class AspectComponentDefinition extends CompositeComponentDefinition {
|
||||
private final BeanReference[] beanReferences;
|
||||
|
||||
|
||||
public AspectComponentDefinition(String aspectName, @Nullable BeanDefinition[] beanDefinitions,
|
||||
@Nullable BeanReference[] beanReferences, @Nullable Object source) {
|
||||
public AspectComponentDefinition(
|
||||
String aspectName, BeanDefinition[] beanDefinitions, BeanReference[] beanReferences, Object source) {
|
||||
|
||||
super(aspectName, source);
|
||||
this.beanDefinitions = (beanDefinitions != null ? beanDefinitions : new BeanDefinition[0]);
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 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,7 +25,6 @@ import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} for the {@code aspectj-autoproxy} tag,
|
||||
@@ -39,7 +38,6 @@ import org.springframework.lang.Nullable;
|
||||
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
extendBeanDefinition(element, parserContext);
|
||||
@@ -55,7 +53,7 @@ class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
|
||||
ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
|
||||
ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
|
||||
+5
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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,7 +45,6 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
@@ -97,7 +96,6 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
CompositeComponentDefinition compositeDef =
|
||||
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
|
||||
@@ -201,8 +199,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
try {
|
||||
this.parseState.push(new AspectEntry(aspectId, aspectName));
|
||||
List<BeanDefinition> beanDefinitions = new ArrayList<>();
|
||||
List<BeanReference> beanReferences = new ArrayList<>();
|
||||
List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
|
||||
List<BeanReference> beanReferences = new ArrayList<BeanReference>();
|
||||
|
||||
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
|
||||
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
|
||||
@@ -253,8 +251,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
Element aspectElement, String aspectId, List<BeanDefinition> beanDefs,
|
||||
List<BeanReference> beanRefs, ParserContext parserContext) {
|
||||
|
||||
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[0]);
|
||||
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[0]);
|
||||
BeanDefinition[] beanDefArray = beanDefs.toArray(new BeanDefinition[beanDefs.size()]);
|
||||
BeanReference[] beanRefArray = beanRefs.toArray(new BeanReference[beanRefs.size()]);
|
||||
Object source = parserContext.extractSource(aspectElement);
|
||||
return new AspectComponentDefinition(aspectId, beanDefArray, beanRefArray, source);
|
||||
}
|
||||
@@ -468,7 +466,6 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
* {@link org.springframework.beans.factory.config.BeanDefinition} for the pointcut if necessary
|
||||
* and returns its bean name, otherwise returns the bean name of the referred pointcut.
|
||||
*/
|
||||
@Nullable
|
||||
private Object parsePointcutProperty(Element element, ParserContext parserContext) {
|
||||
if (element.hasAttribute(POINTCUT) && element.hasAttribute(POINTCUT_REF)) {
|
||||
parserContext.getReaderContext().error(
|
||||
|
||||
+1
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -22,7 +22,6 @@ import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -33,13 +32,10 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class MethodLocatingFactoryBean implements FactoryBean<Method>, BeanFactoryAware {
|
||||
|
||||
@Nullable
|
||||
private String targetBeanName;
|
||||
|
||||
@Nullable
|
||||
private String methodName;
|
||||
|
||||
@Nullable
|
||||
private Method method;
|
||||
|
||||
|
||||
@@ -84,7 +80,6 @@ public class MethodLocatingFactoryBean implements FactoryBean<Method>, BeanFacto
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Method getObject() throws Exception {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
-2
@@ -18,7 +18,6 @@ package org.springframework.aop.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.AbstractComponentDefinition;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -63,7 +62,6 @@ public class PointcutComponentDefinition extends AbstractComponentDefinition {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object getSource() {
|
||||
return this.pointcutDefinition.getSource();
|
||||
}
|
||||
|
||||
+1
-8
@@ -21,7 +21,6 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -35,10 +34,8 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstanceFactory, BeanFactoryAware {
|
||||
|
||||
@Nullable
|
||||
private String aspectBeanName;
|
||||
|
||||
@Nullable
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
@@ -63,13 +60,10 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
*/
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
Assert.state(this.beanFactory != null, "No BeanFactory set");
|
||||
Assert.state(this.aspectBeanName != null, "No 'aspectBeanName' set");
|
||||
return this.beanFactory.getBean(this.aspectBeanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
@@ -81,8 +75,7 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.beanFactory != null && this.aspectBeanName != null &&
|
||||
this.beanFactory.isSingleton(this.aspectBeanName) &&
|
||||
if (this.beanFactory.isSingleton(this.aspectBeanName) &&
|
||||
this.beanFactory.isTypeMatch(this.aspectBeanName, Ordered.class)) {
|
||||
return ((Ordered) this.beanFactory.getBean(this.aspectBeanName)).getOrder();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,4 @@
|
||||
* Support package for declarative AOP configuration,
|
||||
* with XML schema being the primary configuration format.
|
||||
*/
|
||||
@NonNullApi
|
||||
@NonNullFields
|
||||
package org.springframework.aop.config;
|
||||
|
||||
import org.springframework.lang.NonNullApi;
|
||||
import org.springframework.lang.NonNullFields;
|
||||
|
||||
+5
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -22,7 +22,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for {@link BeanPostProcessor} implementations that apply a
|
||||
@@ -34,12 +33,11 @@ import org.springframework.lang.Nullable;
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
|
||||
|
||||
@Nullable
|
||||
protected Advisor advisor;
|
||||
|
||||
protected boolean beforeExistingAdvisors = false;
|
||||
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<>(256);
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(256);
|
||||
|
||||
|
||||
/**
|
||||
@@ -63,7 +61,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
|
||||
if (bean instanceof AopInfrastructureBean) {
|
||||
// Ignore AOP infrastructure such as scoped proxies.
|
||||
return bean;
|
||||
}
|
||||
@@ -92,7 +90,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
}
|
||||
|
||||
// No proxy needed.
|
||||
// No async proxy needed.
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -127,9 +125,6 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
if (eligible != null) {
|
||||
return eligible;
|
||||
}
|
||||
if (this.advisor == null) {
|
||||
return false;
|
||||
}
|
||||
eligible = AopUtils.canApply(this.advisor, targetClass);
|
||||
this.eligibleBeans.put(targetClass, eligible);
|
||||
return eligible;
|
||||
@@ -160,7 +155,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
* Subclasses may choose to implement this: for example,
|
||||
* to change the interfaces exposed.
|
||||
* <p>The default implementation is empty.
|
||||
* @param proxyFactory the ProxyFactory that is already configured with
|
||||
* @param proxyFactory ProxyFactory that is already configured with
|
||||
* target, advisor and interfaces and will be used to create the proxy
|
||||
* immediately after this method returns
|
||||
* @since 4.2.3
|
||||
|
||||
+4
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -24,7 +24,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -42,25 +41,19 @@ import org.springframework.util.ClassUtils;
|
||||
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean {
|
||||
|
||||
@Nullable
|
||||
private Object target;
|
||||
|
||||
@Nullable
|
||||
private Class<?>[] proxyInterfaces;
|
||||
|
||||
@Nullable
|
||||
private Object[] preInterceptors;
|
||||
|
||||
@Nullable
|
||||
private Object[] postInterceptors;
|
||||
|
||||
/** Default is global AdvisorAdapterRegistry. */
|
||||
/** Default is global AdvisorAdapterRegistry */
|
||||
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
|
||||
|
||||
@Nullable
|
||||
private transient ClassLoader proxyClassLoader;
|
||||
|
||||
@Nullable
|
||||
private Object proxy;
|
||||
|
||||
|
||||
@@ -176,10 +169,8 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
}
|
||||
else if (!isProxyTargetClass()) {
|
||||
// Rely on AOP infrastructure to tell us what interfaces to proxy.
|
||||
Class<?> targetClass = targetSource.getTargetClass();
|
||||
if (targetClass != null) {
|
||||
proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
|
||||
}
|
||||
proxyFactory.setInterfaces(
|
||||
ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
|
||||
}
|
||||
|
||||
postProcessProxyFactory(proxyFactory);
|
||||
@@ -221,7 +212,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getObjectType() {
|
||||
if (this.proxy != null) {
|
||||
return this.proxy.getClass();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -211,7 +211,7 @@ public interface Advised extends TargetClassAware {
|
||||
* or -1 if no such advice is an advice for this proxy.
|
||||
* <p>The return value of this method can be used to index into
|
||||
* the advisors array.
|
||||
* @param advice the AOP Alliance advice to search for
|
||||
* @param advice AOP Alliance advice to search for
|
||||
* @return index from 0 of this advice, or -1 if there's no such advice
|
||||
*/
|
||||
int indexOf(Advice advice);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -37,7 +38,6 @@ import org.springframework.aop.support.DefaultIntroductionAdvisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.aop.target.EmptyTargetSource;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -60,7 +60,7 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
/** use serialVersionUID from Spring 2.0 for interoperability. */
|
||||
/** use serialVersionUID from Spring 2.0 for interoperability */
|
||||
private static final long serialVersionUID = 2651364800145442165L;
|
||||
|
||||
|
||||
@@ -71,29 +71,29 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
|
||||
|
||||
|
||||
/** Package-protected to allow direct access for efficiency. */
|
||||
/** Package-protected to allow direct access for efficiency */
|
||||
TargetSource targetSource = EMPTY_TARGET_SOURCE;
|
||||
|
||||
/** Whether the Advisors are already filtered for the specific target class. */
|
||||
/** Whether the Advisors are already filtered for the specific target class */
|
||||
private boolean preFiltered = false;
|
||||
|
||||
/** The AdvisorChainFactory to use. */
|
||||
/** The AdvisorChainFactory to use */
|
||||
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
|
||||
|
||||
/** Cache with Method as key and advisor chain List as value. */
|
||||
/** Cache with Method as key and advisor chain List as value */
|
||||
private transient Map<MethodCacheKey, List<Object>> methodCache;
|
||||
|
||||
/**
|
||||
* Interfaces to be implemented by the proxy. Held in List to keep the order
|
||||
* of registration, to create JDK proxy with specified order of interfaces.
|
||||
*/
|
||||
private List<Class<?>> interfaces = new ArrayList<>();
|
||||
private List<Class<?>> interfaces = new ArrayList<Class<?>>();
|
||||
|
||||
/**
|
||||
* List of Advisors. If an Advice is added, it will be wrapped
|
||||
* in an Advisor before being added to this List.
|
||||
*/
|
||||
private List<Advisor> advisors = new ArrayList<>();
|
||||
private List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
|
||||
/**
|
||||
* Array updated on changes to the advisors list, which is easier
|
||||
@@ -106,7 +106,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* No-arg constructor for use as a JavaBean.
|
||||
*/
|
||||
public AdvisedSupport() {
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
initMethodCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,6 +118,13 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the method cache.
|
||||
*/
|
||||
private void initMethodCache() {
|
||||
this.methodCache = new ConcurrentHashMap<MethodCacheKey, List<Object>>(32);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the given object as target.
|
||||
@@ -130,7 +137,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetSource(@Nullable TargetSource targetSource) {
|
||||
public void setTargetSource(TargetSource targetSource) {
|
||||
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
|
||||
}
|
||||
|
||||
@@ -152,12 +159,11 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @see #setTargetSource
|
||||
* @see #setTarget
|
||||
*/
|
||||
public void setTargetClass(@Nullable Class<?> targetClass) {
|
||||
public void setTargetClass(Class<?> targetClass) {
|
||||
this.targetSource = EmptyTargetSource.forClass(targetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetSource.getTargetClass();
|
||||
}
|
||||
@@ -228,7 +234,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
@Override
|
||||
public Class<?>[] getProxiedInterfaces() {
|
||||
return ClassUtils.toClassArray(this.interfaces);
|
||||
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -372,7 +378,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[0]);
|
||||
this.advisorArray = this.advisors.toArray(new Advisor[this.advisors.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -440,7 +446,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param advice the advice to check inclusion of
|
||||
* @return whether this advice instance is included
|
||||
*/
|
||||
public boolean adviceIncluded(@Nullable Advice advice) {
|
||||
public boolean adviceIncluded(Advice advice) {
|
||||
if (advice != null) {
|
||||
for (Advisor advisor : this.advisors) {
|
||||
if (advisor.getAdvice() == advice) {
|
||||
@@ -456,7 +462,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param adviceClass the advice class to check
|
||||
* @return the count of the interceptors of this class or subclasses
|
||||
*/
|
||||
public int countAdvicesOfType(@Nullable Class<?> adviceClass) {
|
||||
public int countAdvicesOfType(Class<?> adviceClass) {
|
||||
int count = 0;
|
||||
if (adviceClass != null) {
|
||||
for (Advisor advisor : this.advisors) {
|
||||
@@ -474,9 +480,9 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* for the given method, based on this configuration.
|
||||
* @param method the proxied method
|
||||
* @param targetClass the target class
|
||||
* @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
*/
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
|
||||
MethodCacheKey cacheKey = new MethodCacheKey(method);
|
||||
List<Object> cached = this.methodCache.get(cacheKey);
|
||||
if (cached == null) {
|
||||
@@ -500,7 +506,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param other the AdvisedSupport object to copy configuration from
|
||||
*/
|
||||
protected void copyConfigurationFrom(AdvisedSupport other) {
|
||||
copyConfigurationFrom(other, other.targetSource, new ArrayList<>(other.advisors));
|
||||
copyConfigurationFrom(other, other.targetSource, new ArrayList<Advisor>(other.advisors));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,7 +520,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
copyFrom(other);
|
||||
this.targetSource = targetSource;
|
||||
this.advisorChainFactory = other.advisorChainFactory;
|
||||
this.interfaces = new ArrayList<>(other.interfaces);
|
||||
this.interfaces = new ArrayList<Class<?>>(other.interfaces);
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
|
||||
@@ -528,7 +534,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
/**
|
||||
* Build a configuration-only copy of this AdvisedSupport,
|
||||
* replacing the TargetSource.
|
||||
* replacing the TargetSource
|
||||
*/
|
||||
AdvisedSupport getConfigurationOnlyCopy() {
|
||||
AdvisedSupport copy = new AdvisedSupport();
|
||||
@@ -551,7 +557,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
initMethodCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2014 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,8 +19,6 @@ package org.springframework.aop.framework;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Factory interface for advisor chains.
|
||||
*
|
||||
@@ -36,8 +34,8 @@ public interface AdvisorChainFactory {
|
||||
* @param method the proxied method
|
||||
* @param targetClass the target class (may be {@code null} to indicate a proxy without
|
||||
* target object, in which case the method's declaring class is the next best option)
|
||||
* @return a List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
*/
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2012 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;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Class containing static methods used to obtain information about the current AOP invocation.
|
||||
@@ -39,7 +38,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Juergen Hoeller
|
||||
* @since 13.03.2003
|
||||
*/
|
||||
public final class AopContext {
|
||||
public abstract class AopContext {
|
||||
|
||||
/**
|
||||
* ThreadLocal holder for AOP proxy associated with this thread.
|
||||
@@ -47,18 +46,14 @@ public final class AopContext {
|
||||
* the controlling proxy configuration has been set to "true".
|
||||
* @see ProxyConfig#setExposeProxy
|
||||
*/
|
||||
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");
|
||||
|
||||
|
||||
private AopContext() {
|
||||
}
|
||||
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy");
|
||||
|
||||
|
||||
/**
|
||||
* Try to return the current AOP proxy. This method is usable only if the
|
||||
* calling method has been invoked via AOP, and the AOP framework has been set
|
||||
* to expose proxies. Otherwise, this method will throw an IllegalStateException.
|
||||
* @return the current AOP proxy (never returns {@code null})
|
||||
* @return Object the current AOP proxy (never returns {@code null})
|
||||
* @throws IllegalStateException if the proxy cannot be found, because the
|
||||
* method was invoked outside an AOP invocation context, or because the
|
||||
* AOP framework has not been configured to expose the proxy
|
||||
@@ -79,8 +74,7 @@ public final class AopContext {
|
||||
* @return the old proxy, which may be {@code null} if none was bound
|
||||
* @see #currentProxy()
|
||||
*/
|
||||
@Nullable
|
||||
static Object setCurrentProxy(@Nullable Object proxy) {
|
||||
static Object setCurrentProxy(Object proxy) {
|
||||
Object old = currentProxy.get();
|
||||
if (proxy != null) {
|
||||
currentProxy.set(proxy);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user