mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
603 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fe1eaddec | |||
| fc8f31ccfb | |||
| a3781a45d6 | |||
| fd34533a3e | |||
| 84568e8dbc | |||
| 77e0100f42 | |||
| bb9cf7cce1 | |||
| ae51ca9bca | |||
| 9764f0e59b | |||
| c3aed75b92 | |||
| 0a1ce75c7c | |||
| e7b97f5be7 | |||
| 03179aa397 | |||
| da45bd2dfd | |||
| 12244b2e51 | |||
| 0b716c4f90 | |||
| ae1956cac7 | |||
| 1392b0f557 | |||
| 4db2f8ea1b | |||
| e9655e8a7b | |||
| 5598f99816 | |||
| 92d9aee3a2 | |||
| 389747f91c | |||
| 542b6427c3 | |||
| 2ab871fbc3 | |||
| c249b578b5 | |||
| 2858c1efb5 | |||
| 672555a568 | |||
| 1b7892c559 | |||
| 2a9a1f1c3a | |||
| 7be6816129 | |||
| 66d758d677 | |||
| 5abaf20a74 | |||
| 0e7c7b444c | |||
| 1742e121e7 | |||
| 93a2651417 | |||
| f3181dc583 | |||
| a0061b7fb9 | |||
| 4184294835 | |||
| 67b7c16bc0 | |||
| 9809752c3c | |||
| e873715737 | |||
| 9b07457d06 | |||
| 30cd14d61d | |||
| b5695b9248 | |||
| 7255a8b48e | |||
| 9ba927215e | |||
| 653dc5951d | |||
| ec6a19fc6b | |||
| 5bc701d4fe | |||
| cc57b55c61 | |||
| fd191d165b | |||
| 14b147ce70 | |||
| c541bde513 | |||
| 97986b368a | |||
| ea19b92deb | |||
| 20b17f02a2 | |||
| 572d017370 | |||
| 2c3407b0e5 | |||
| 1be3eecb2a | |||
| 5119aafe4f | |||
| f7d49e3957 | |||
| c1033dbfb3 | |||
| 9cb4783296 | |||
| 68757073b0 | |||
| 14ae522172 | |||
| 66e9095ee9 | |||
| 466dd825ac | |||
| 27ee9cdcde | |||
| c9795597c8 | |||
| 9340e9b716 | |||
| c03def79d4 | |||
| b045e5baef | |||
| 679432ece6 | |||
| 76be6373a8 | |||
| 3efedef161 | |||
| 714d451260 | |||
| 65394b00ea | |||
| 5e75f6e009 | |||
| 33004a9efd | |||
| a28b49ac27 | |||
| b4eb895927 | |||
| e85001f332 | |||
| 819d4256b7 | |||
| ad3095f197 | |||
| be8224a590 | |||
| 01214b3473 | |||
| 6a73d2655f | |||
| 8c6d59aaaf | |||
| c5c926726d | |||
| 42d114534b | |||
| 8c5a407a7d | |||
| 968efb34f6 | |||
| 6c832598c9 | |||
| 4a470e0a37 | |||
| 41ee23345d | |||
| 8506778608 | |||
| 0814c67913 | |||
| b96474707b | |||
| 3c0a5fd063 | |||
| 69db0f7b45 | |||
| 7f5110a549 | |||
| c1987e5b8c | |||
| 3463106532 | |||
| b3306f4e3d | |||
| 18b8e4ec5c | |||
| 2cee63491d | |||
| bbd35ded91 | |||
| 5fbd01f28f | |||
| d2d54c826f | |||
| c42023f20e | |||
| 552e02cb44 | |||
| 7412625929 | |||
| 11de64d609 | |||
| c732b56edd | |||
| 2141373c43 | |||
| 5bbc7dbce2 | |||
| 4782d4c080 | |||
| c5e1a774a5 | |||
| bfe9d4fc49 | |||
| 4c410cbe54 | |||
| 7ecfce2386 | |||
| ad2722b3a3 | |||
| 303e363adf | |||
| 2a0ec0b2dd | |||
| 5e64081ed1 | |||
| 70269addb7 | |||
| e6ce328be4 | |||
| 7b0443333d | |||
| 37b03aee82 | |||
| a4e192e33d | |||
| 5ae9217271 | |||
| 7257f31ca8 | |||
| 6c42bcfaec | |||
| 2019e176ee | |||
| 1a4573641d | |||
| d64f8c1a05 | |||
| b3ceb0f625 | |||
| dfae8effa8 | |||
| 7a2c9b80c2 | |||
| 5c60a721a7 | |||
| 1deb6b04b8 | |||
| 839cc5f7f8 | |||
| bf40033e86 | |||
| a0c97e4c36 | |||
| 6936f7e0cb | |||
| e077a753f8 | |||
| 2ae6431a50 | |||
| 04fbfddb13 | |||
| 1e0e477833 | |||
| 9a0f691e86 | |||
| b0bca7f5ae | |||
| 3eb9886724 | |||
| d07e1be623 | |||
| 6b1c2dc944 | |||
| e5af4aa608 | |||
| 9688e61e20 | |||
| 4358b48b08 | |||
| c064e90697 | |||
| b3f786728e | |||
| 32cd73261a | |||
| 9a5ecd0c46 | |||
| 12342d7f8e | |||
| c263cbfbe4 | |||
| 54565e95b5 | |||
| 5ad261228d | |||
| d94298aae5 | |||
| 823958bcc5 | |||
| 6e4551131d | |||
| 84ebbdd38e | |||
| 5378f2040d | |||
| 24ff2d2b6f | |||
| e3529453d1 | |||
| de33e3b575 | |||
| ed2696287a | |||
| 8e2bb5f3af | |||
| e5129c58f4 | |||
| a9a6b071d9 | |||
| 786d80c0bb | |||
| 29768cdd11 | |||
| 4d54e5ad87 | |||
| 84e6d2a95c | |||
| f64cc08b62 | |||
| e7b9d61225 | |||
| c58885fc35 | |||
| 065ac8e081 | |||
| 48ce714d15 | |||
| 72fc706c22 | |||
| 08daacfc1b | |||
| f9a19c749b | |||
| 54c7f53eff | |||
| b943a7a07c | |||
| a323c39e97 | |||
| 9af2c9d55d | |||
| e94e67cd93 | |||
| 1cf2960eb6 | |||
| a6deac3ffe | |||
| f7c3706361 | |||
| 912bb16e44 | |||
| 66732afc10 | |||
| e565d2cabb | |||
| d72cf89ebf | |||
| 4a51e4bbc7 | |||
| 4388a7c4d0 | |||
| 19da4e309f | |||
| 316e84f04f | |||
| f43fb41bce | |||
| a849f76586 | |||
| 198576dbc5 | |||
| 680ec30148 | |||
| 2d9c9fe9cc | |||
| d6e56ce327 | |||
| 148d7ab1df | |||
| 4b68dfb6f5 | |||
| 50faa29329 | |||
| 12315d5b20 | |||
| d61d0d41a3 | |||
| b56815f995 | |||
| 6643efe0b4 | |||
| 3477ec0a35 | |||
| 9346c89f5c | |||
| 29fe109440 | |||
| 5aefcd2fdb | |||
| f2fe8a87fa | |||
| 6ecb488327 | |||
| b848acd86d | |||
| 368201975a | |||
| d57bc176f2 | |||
| 4ebc53a424 | |||
| 1941ae6696 | |||
| 3c500aa000 | |||
| 5a76939a15 | |||
| 519fa60c25 | |||
| 5d508de2c0 | |||
| ab88ff374a | |||
| 86387db045 | |||
| ae5d8b645b | |||
| b981e36174 | |||
| e1991f981a | |||
| 7769ded887 | |||
| aaa10e9060 | |||
| 7c637f01c4 | |||
| 338f8907ac | |||
| 83827031a7 | |||
| 202b7ea47b | |||
| eb783e6690 | |||
| 61c3d7a989 | |||
| ee292ec116 | |||
| 948f5999c3 | |||
| 2ed7268ded | |||
| 7311620915 | |||
| 941b6af9ac | |||
| ab240f5d8e | |||
| 7021eb5bb1 | |||
| 6555d3b42d | |||
| 97625e3658 | |||
| 1dee80e750 | |||
| 0b8c815c6f | |||
| a410f4c0f2 | |||
| b24cbc5e97 | |||
| eb5022924e | |||
| 900e0f56eb | |||
| 65d2e9bb54 | |||
| 7f73cb6726 | |||
| 8a7a046bf0 | |||
| 88d4eac537 | |||
| c09a674dcb | |||
| c204cc7ba0 | |||
| f0125afb5e | |||
| 7ba089be95 | |||
| 414169b1eb | |||
| 772630caf1 | |||
| f3fd7b156e | |||
| 544e9bb403 | |||
| f1fe16e3cd | |||
| b69ab8d568 | |||
| f64ede3c83 | |||
| ca6911a532 | |||
| dbbdd044cd | |||
| 5532615361 | |||
| 713795cc34 | |||
| fa78fb4351 | |||
| ac1032ffc9 | |||
| 731af9444c | |||
| db21cbd4af | |||
| 1aaf5262b1 | |||
| 08a34ca1ec | |||
| ec9ce5b4b0 | |||
| 9dc5c9f935 | |||
| e15bed781d | |||
| 96e2fc69ed | |||
| 50c7c84886 | |||
| efaccd6356 | |||
| 2f3a9dbc68 | |||
| b6faaf1fc1 | |||
| 73ee87aadf | |||
| b7cd049d7d | |||
| bdbcc4f98c | |||
| 3e6eb987d0 | |||
| bfdb93b406 | |||
| ea9b8c1d0f | |||
| c5c2053b63 | |||
| bb53a99def | |||
| 8d93dc4abb | |||
| ceea00f733 | |||
| 2fb3f9993f | |||
| 64b6beed5b | |||
| 86eda279c8 | |||
| aeff664cf9 | |||
| ba468a731f | |||
| 9a513cfdea | |||
| 37bebeaaaf | |||
| 32b8710489 | |||
| 3600644ed1 | |||
| 2db6795a1a | |||
| 5d91560f92 | |||
| 7854dbb025 | |||
| 21c3623cdc | |||
| 61601de250 | |||
| 4453102e85 | |||
| 782a94fd25 | |||
| 49c4d310b5 | |||
| e822be5a75 | |||
| d836fb4a7a | |||
| aa302515a4 | |||
| e1acbca4e4 | |||
| 101d92c166 | |||
| 62f480adc3 | |||
| 8d6cc7dc10 | |||
| a15393836c | |||
| b5ffcfb4ba | |||
| 866708942c | |||
| 3a43ca3a34 | |||
| ce253041c5 | |||
| 81af7330f6 | |||
| 982ba0e86d | |||
| 68cf95f499 | |||
| 7f43128a0e | |||
| 110e0f7f2b | |||
| 0a41da9ec9 | |||
| 8144f8666e | |||
| a57ea39707 | |||
| 65eceafeee | |||
| a9d2016007 | |||
| ba568ff79c | |||
| 720c30ce84 | |||
| 1b4fa0370c | |||
| 65dc2afe9d | |||
| 5ec1e20242 | |||
| 24cb1def7d | |||
| 2d2db530b1 | |||
| 9cc690a9bb | |||
| a0ba808217 | |||
| e0979d0e74 | |||
| e986ff8d07 | |||
| baed0785fd | |||
| 32359c52b4 | |||
| 5589e6ceed | |||
| 792b366bda | |||
| 6283456ef2 | |||
| 7794606305 | |||
| 445f25c466 | |||
| 9c1a0d32be | |||
| 46cb5ab135 | |||
| 5c4cde7853 | |||
| da3b4cb65d | |||
| 7a4207cd7b | |||
| 6e335e3a9f | |||
| f57004db2c | |||
| a0d54105e9 | |||
| 44950bb862 | |||
| 1ebe62f646 | |||
| f88344db03 | |||
| 2f32806bcb | |||
| e66095b1a2 | |||
| 6605953eb5 | |||
| fab9abd7fe | |||
| d178eafc11 | |||
| 804b343cab | |||
| 79d3f5c64c | |||
| 51ecbdecd8 | |||
| dcc342ccc5 | |||
| d5f36c7e2c | |||
| 975ca284fb | |||
| 259bcd60fb | |||
| 6d9136013e | |||
| a7789db067 | |||
| 38062c3373 | |||
| 247d2bb0ae | |||
| 974d326bf5 | |||
| 5eafcac3d6 | |||
| ac46338fdb | |||
| bee0af2b26 | |||
| 1694691b79 | |||
| fe8d42ff59 | |||
| b3b50f8f4b | |||
| dcc7154641 | |||
| d930617442 | |||
| ab2b3d91fc | |||
| aa80c4873a | |||
| 0b0fab8952 | |||
| 9d65ff73f9 | |||
| 2be80b8fc8 | |||
| 4750a9430c | |||
| 17cdd97c37 | |||
| 62a4a4c0bf | |||
| b88ed7f4bb | |||
| 555807ea9c | |||
| 5593e1e406 | |||
| f3b83e7ad4 | |||
| c705e32a88 | |||
| ac694eeac8 | |||
| 33ed92e552 | |||
| 5c972fcc54 | |||
| 2fba0bc272 | |||
| 54bd66755c | |||
| 32af39d6e6 | |||
| 75036fa0ad | |||
| 0e1ba7aae5 | |||
| cd5657d158 | |||
| 8de58f4f32 | |||
| ec947065a9 | |||
| 5acc3228f7 | |||
| ebfec822cb | |||
| ea86b4d36c | |||
| 1eb8c93689 | |||
| a71f0eb267 | |||
| 56fd97184c | |||
| 4464468465 | |||
| 32c14a2b42 | |||
| 8dd385b440 | |||
| 5ea1cf532e | |||
| 0a9746e820 | |||
| 0a58419df4 | |||
| 6fd0615be9 | |||
| c989470f94 | |||
| 267df1c0f2 | |||
| 63697ca06d | |||
| 683bdf2675 | |||
| 65bf5f7c81 | |||
| e4e667acdb | |||
| 63509e64d4 | |||
| 1e36518182 | |||
| d9e9a33b66 | |||
| c3650f3cd6 | |||
| e9fc35495e | |||
| bd55f609a7 | |||
| 170d6dd5f2 | |||
| 71036e7da5 | |||
| 59beef71df | |||
| e4b493456b | |||
| dd79be3664 | |||
| 8e245e4410 | |||
| f78d9cdf22 | |||
| fe8518dcb2 | |||
| aa5a2a8600 | |||
| 22f75d9ea9 | |||
| 9804e75051 | |||
| b681c6b4bc | |||
| 24b0035369 | |||
| f01b856064 | |||
| 3b531d9494 | |||
| b51813e408 | |||
| 1f248b34f6 | |||
| 8135ae6d38 | |||
| 785212d676 | |||
| e9cf645b86 | |||
| b8fc79543d | |||
| 9b4f3880b3 | |||
| 40ead013fa | |||
| 1cd70bbe6b | |||
| d70a610a0d | |||
| 971f665eb1 | |||
| 4e6ef82d8f | |||
| cb17441780 | |||
| 9b9906cfc4 | |||
| b3473a3e81 | |||
| 0eb73c130c | |||
| 67333a3f94 | |||
| 401c0d220a | |||
| 63c6a7e15e | |||
| 07cd6ab761 | |||
| fba92c0120 | |||
| 940a37f9ce | |||
| 7e4870577d | |||
| 4fc359f75e | |||
| d312c13721 | |||
| 8134fb7a7c | |||
| 921701b48d | |||
| ca999fb38c | |||
| 3633b2a24f | |||
| 373b90d263 | |||
| 1ef47fa369 | |||
| 887ecffaa9 | |||
| 49c8cb5a60 | |||
| 28a497f3b3 | |||
| 95da027397 | |||
| daf10d6c45 | |||
| 627fc7612d | |||
| a74031454c | |||
| 8820c893e6 | |||
| da457abd5b | |||
| 7957b9cc0f | |||
| 87cb84b832 | |||
| 276aa46a1c | |||
| d16574f807 | |||
| f479668938 | |||
| bd85cb8bac | |||
| 1709d609c2 | |||
| 22f0f9f3df | |||
| 56eefe2a13 | |||
| fa3a2dc981 | |||
| f14bd50033 | |||
| e3b48c23dd | |||
| 932291b867 | |||
| 6e92c4d674 | |||
| ccb080f948 | |||
| 942a5986a8 | |||
| 6eaaf294f3 | |||
| 359661df9d | |||
| 2c583517cb | |||
| 2d1e0d5e38 | |||
| fb7eea9757 | |||
| c1856d24e2 | |||
| c25aefdb2b | |||
| 381b7d035a | |||
| dabe823a4a | |||
| 837dd30661 | |||
| a9418b613c | |||
| 48eb51a22f | |||
| 5766855514 | |||
| 04eed155cd | |||
| 545b1a33c6 | |||
| e314a79fb0 | |||
| b452d1b41d | |||
| 543738ca58 | |||
| 1b8a5051ca | |||
| cb9246e481 | |||
| ad873617d2 | |||
| f6a392c5ae | |||
| dc5807ea51 | |||
| a4b74a320e | |||
| 4f61e9cdee | |||
| 167e538dd1 | |||
| 3e53e54b80 | |||
| 030ba52805 | |||
| 3ad796e913 | |||
| ac5dc698e2 | |||
| f32f04d841 | |||
| 4d7fa9a632 | |||
| 1e6c0d2f7b | |||
| 08bce08018 | |||
| 6337e08f2b | |||
| 93efb20a53 | |||
| 3dc84c2d92 | |||
| 16bf39ea1b | |||
| d483992177 | |||
| b3f6d60dc9 | |||
| e6112344d2 | |||
| 30efa4d478 | |||
| 50f2016293 | |||
| 693ab84347 | |||
| f440fb8baf | |||
| 0241c5ebb3 | |||
| 66b15efa21 | |||
| 6689b3cd70 | |||
| a247b83cd9 | |||
| b808b53bcc | |||
| 8f96ca4a2d | |||
| 774583dfa7 | |||
| 6976bf774b | |||
| 0d4be7deb0 | |||
| d6570fa2ac | |||
| 7135051c55 | |||
| 01d82ef0c6 | |||
| 070d087dbc | |||
| 69a46a7296 | |||
| 3beb074278 | |||
| 5ab789b310 | |||
| cf46384887 | |||
| 958eb0f964 | |||
| 01426481ea | |||
| 8b5f5d9f65 | |||
| 853ab5d67b | |||
| 513cc1576e | |||
| 48875dc44f | |||
| b732ff3495 | |||
| cce61c3918 | |||
| 5eac8555d9 | |||
| d84ca2ba90 | |||
| 5822f1bf85 | |||
| 3c8724ba3d | |||
| b7b078d26e | |||
| b74e93807e | |||
| e0a4b05142 | |||
| 33cddef026 | |||
| 4e3d1fa4e9 | |||
| cf2429b0f0 | |||
| 0640da74bc | |||
| f53bf8e9e1 | |||
| 350d3e8b22 | |||
| 09b233365f | |||
| c0e479460e |
@@ -1,3 +1,3 @@
|
||||
# Enable auto-env through the sdkman_auto_env config
|
||||
# Add key=value pairs of SDKs to use below
|
||||
java=8.0.322-librca
|
||||
java=17.0.2-librca
|
||||
|
||||
+12
-8
@@ -6,7 +6,7 @@ First off, thank you for taking the time to contribute! :+1: :tada:
|
||||
|
||||
* [Code of Conduct](#code-of-conduct)
|
||||
* [How to Contribute](#how-to-contribute)
|
||||
* [Discuss](#discuss)
|
||||
* [Ask questions](#ask-questions)
|
||||
* [Create an Issue](#create-an-issue)
|
||||
* [Issue Lifecycle](#issue-lifecycle)
|
||||
* [Submit a Pull Request](#submit-a-pull-request)
|
||||
@@ -22,11 +22,10 @@ Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
### How to Contribute
|
||||
|
||||
#### Discuss
|
||||
#### Ask questions
|
||||
|
||||
If you have a question, check Stack Overflow using
|
||||
[this list of tags](https://stackoverflow.com/questions/tagged/spring+or+spring-mvc+or+spring-aop+or+spring-jdbc+or+spring-transactions+or+spring-annotations+or+spring-jms+or+spring-el+or+spring-test+or+spring+or+spring-remoting+or+spring-orm+or+spring-jmx+or+spring-cache+or+spring-webflux?tab=Newest).
|
||||
Find an existing discussion, or start a new one if necessary.
|
||||
[this list of tags](https://stackoverflow.com/questions/tagged/spring+or+spring-mvc+or+spring-aop+or+spring-jdbc+or+spring-transactions+or+spring-annotations+or+spring-jms+or+spring-el+or+spring-test+or+spring+or+spring-remoting+or+spring-orm+or+spring-jmx+or+spring-cache+or+spring-webflux?tab=Newest). Find an existing discussion, or start a new one if necessary.
|
||||
|
||||
If you believe there is an issue, search through
|
||||
[existing issues](https://github.com/spring-projects/spring-framework/issues) trying a
|
||||
@@ -39,14 +38,18 @@ decision.
|
||||
|
||||
Reporting an issue or making a feature request is a great way to contribute. Your feedback
|
||||
and the conversations that result from it provide a continuous flow of ideas. However,
|
||||
before creating a ticket, please take the time to [discuss and research](#discuss) first.
|
||||
before creating a ticket, please take the time to [ask and research](#ask-questions) first.
|
||||
|
||||
If creating an issue after a discussion on Stack Overflow, please provide a description
|
||||
If you create an issue after a discussion on Stack Overflow, please provide a description
|
||||
in the issue instead of simply referring to Stack Overflow. The issue tracker is an
|
||||
important place of record for design discussions and should be self-sufficient.
|
||||
|
||||
Once you're ready, create an issue on
|
||||
[GitHub](https://github.com/spring-projects/spring-framework/issues).
|
||||
Once you're ready, create an issue on [GitHub](https://github.com/spring-projects/spring-framework/issues).
|
||||
|
||||
Many issues are caused by subtle behavior, typos, and unintended configuration.
|
||||
Creating a [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)
|
||||
(starting with https://start.spring.io for example) of the problem helps the team
|
||||
quickly triage your issue and get to the core of the problem.
|
||||
|
||||
#### Issue Lifecycle
|
||||
|
||||
@@ -129,3 +132,4 @@ When making changes locally, execute `./gradlew asciidoctor` and then browse the
|
||||
|
||||
Asciidoctor also supports live editing. For more details see
|
||||
[AsciiDoc Tooling](https://docs.asciidoctor.org/asciidoctor/latest/tooling/).
|
||||
|
||||
|
||||
+68
-110
@@ -1,10 +1,10 @@
|
||||
plugins {
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE' apply false
|
||||
id 'io.spring.nohttp' version '0.0.10'
|
||||
id "io.freefair.aspectj" version '6.2.0' apply false
|
||||
id "io.freefair.aspectj" version '6.4.0' apply false
|
||||
id 'org.jetbrains.dokka' version '1.6.10' apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.32' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "1.5.32" apply false
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.6.20-RC' apply false
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version '1.6.20-RC' apply false
|
||||
id 'org.asciidoctor.jvm.convert' version '3.3.2'
|
||||
id 'org.asciidoctor.jvm.pdf' version '3.3.2'
|
||||
id "org.unbroken-dome.xjc" version '2.0.0' apply false
|
||||
@@ -27,15 +27,15 @@ configure(allprojects) { project ->
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.6"
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.13.1"
|
||||
mavenBom "io.netty:netty-bom:4.1.75.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.17"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR12"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Borca-RELEASE"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.1"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.45.v20220203"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.5.32"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.2"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.2.2"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:11.0.8"
|
||||
mavenBom "org.jetbrains.kotlin:kotlin-bom:1.6.20-RC"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.0"
|
||||
mavenBom "org.jetbrains.kotlinx:kotlinx-serialization-bom:1.3.2"
|
||||
mavenBom "org.junit:junit-bom:5.8.2"
|
||||
}
|
||||
dependencies {
|
||||
@@ -51,27 +51,22 @@ configure(allprojects) { project ->
|
||||
}
|
||||
dependency "com.google.code.findbugs:jsr305:3.0.2"
|
||||
|
||||
dependencySet(group: 'org.aspectj', version: '1.9.7') {
|
||||
dependencySet(group: 'org.aspectj', version: '1.9.8') {
|
||||
entry 'aspectjrt'
|
||||
entry 'aspectjtools'
|
||||
entry 'aspectjweaver'
|
||||
}
|
||||
dependencySet(group: 'org.codehaus.groovy', version: '3.0.9') {
|
||||
dependencySet(group: 'org.apache.groovy', version: '4.0.1') {
|
||||
entry 'groovy'
|
||||
entry 'groovy-jsr223'
|
||||
entry 'groovy-templates' // requires findbugs for warning-free compilation
|
||||
entry 'groovy-test'
|
||||
entry 'groovy-xml'
|
||||
}
|
||||
|
||||
dependency "io.reactivex:rxjava:1.3.8"
|
||||
dependency "io.reactivex:rxjava-reactive-streams:1.2.1"
|
||||
dependency "io.reactivex.rxjava2:rxjava:2.2.21"
|
||||
dependency "io.reactivex.rxjava3:rxjava:3.1.3"
|
||||
dependency "io.smallrye.reactive:mutiny:1.4.0"
|
||||
dependency "io.projectreactor.tools:blockhound:1.0.6.RELEASE"
|
||||
|
||||
dependency "com.caucho:hessian:4.0.63"
|
||||
dependency "com.fasterxml:aalto-xml:1.3.1"
|
||||
dependency("com.fasterxml.woodstox:woodstox-core:6.2.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
@@ -79,26 +74,23 @@ configure(allprojects) { project ->
|
||||
dependency "com.google.code.gson:gson:2.8.9"
|
||||
dependency "com.google.protobuf:protobuf-java-util:3.19.3"
|
||||
dependency "com.googlecode.protobuf-java-format:protobuf-java-format:1.4"
|
||||
dependency "com.thoughtworks.qdox:qdox:2.0.1"
|
||||
dependency("com.thoughtworks.xstream:xstream:1.4.18") {
|
||||
exclude group: "xpp3", name: "xpp3_min"
|
||||
exclude group: "xmlpull", name: "xmlpull"
|
||||
}
|
||||
dependency "org.apache.johnzon:johnzon-jsonb:1.2.16"
|
||||
dependency "org.eclipse:yasson:2.0.4"
|
||||
dependency("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: "stax", name: "stax-api"
|
||||
}
|
||||
dependencySet(group: 'org.jibx', version: '1.3.3') {
|
||||
entry 'jibx-bind'
|
||||
entry 'jibx-run'
|
||||
}
|
||||
dependency "org.ogce:xpp3:1.1.6"
|
||||
dependency "org.yaml:snakeyaml:1.30"
|
||||
|
||||
dependency "com.h2database:h2:2.1.210"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:2.9.3"
|
||||
dependency "com.github.ben-manes.caffeine:caffeine:3.0.5"
|
||||
dependency "com.github.librepdf:openpdf:1.3.26"
|
||||
dependency "com.rometools:rome:1.18.0"
|
||||
dependency "commons-io:commons-io:2.5"
|
||||
dependency "commons-io:commons-io:2.11.0"
|
||||
dependency "io.vavr:vavr:0.10.4"
|
||||
dependency "net.sf.jopt-simple:jopt-simple:5.0.4"
|
||||
dependencySet(group: 'org.apache.activemq', version: '5.16.2') {
|
||||
@@ -108,70 +100,57 @@ configure(allprojects) { project ->
|
||||
}
|
||||
entry 'activemq-stomp'
|
||||
}
|
||||
dependency "org.apache.bcel:bcel:6.0"
|
||||
dependency "org.apache.commons:commons-pool2:2.9.0"
|
||||
dependencySet(group: 'org.apache.derby', version: '10.14.2.0') {
|
||||
entry 'derby'
|
||||
entry 'derbyclient'
|
||||
}
|
||||
dependency "org.apache.poi:poi-ooxml:4.1.2"
|
||||
dependency "org.apache.poi:poi-ooxml:5.2.0"
|
||||
dependency "org.apache-extras.beanshell:bsh:2.0b6"
|
||||
dependency "org.freemarker:freemarker:2.3.31"
|
||||
dependency "org.hsqldb:hsqldb:2.5.2"
|
||||
dependency "org.quartz-scheduler:quartz:2.3.2"
|
||||
dependency "org.codehaus.fabric3.api:commonj:1.1.0"
|
||||
dependency "net.sf.ehcache:ehcache:2.10.6"
|
||||
dependency "org.ehcache:jcache:1.0.1"
|
||||
dependency "org.ehcache:ehcache:3.4.0"
|
||||
dependency "org.hibernate:hibernate-core:5.4.33.Final"
|
||||
dependency "org.hibernate:hibernate-validator:6.2.3.Final"
|
||||
dependency "org.hibernate:hibernate-core-jakarta:5.6.6.Final"
|
||||
dependency "org.hibernate:hibernate-validator:7.0.4.Final"
|
||||
dependency "org.webjars:webjars-locator-core:0.48"
|
||||
dependency "org.webjars:underscorejs:1.8.3"
|
||||
|
||||
dependencySet(group: 'org.apache.tomcat', version: '9.0.60') {
|
||||
dependencySet(group: 'org.apache.tomcat', version: '10.0.14') {
|
||||
entry 'tomcat-util'
|
||||
entry('tomcat-websocket') {
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-servlet-api"
|
||||
exclude group: "org.apache.tomcat", name: "tomcat-websocket-api"
|
||||
}
|
||||
}
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '9.0.60') {
|
||||
dependencySet(group: 'org.apache.tomcat.embed', version: '10.0.14') {
|
||||
entry 'tomcat-embed-core'
|
||||
entry 'tomcat-embed-websocket'
|
||||
}
|
||||
dependencySet(group: 'io.undertow', version: '2.2.16.Final') {
|
||||
entry 'undertow-core'
|
||||
entry('undertow-servlet') {
|
||||
exclude group: "org.jboss.spec.javax.servlet", name: "jboss-servlet-api_4.0_spec"
|
||||
exclude group: "org.jboss.spec.javax.annotation", name: "jboss-annotations-api_1.3_spec"
|
||||
}
|
||||
entry('undertow-websockets-jsr') {
|
||||
exclude group: "org.jboss.spec.javax.websocket", name: "jboss-websocket-api_1.1_spec"
|
||||
}
|
||||
entry 'undertow-servlet-jakarta'
|
||||
entry 'undertow-websockets-jsr-jakarta'
|
||||
}
|
||||
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:1.1.10"
|
||||
dependency "org.eclipse.jetty:jetty-reactive-httpclient:3.0.5"
|
||||
dependency 'org.apache.httpcomponents.client5:httpclient5:5.1.3'
|
||||
dependency 'org.apache.httpcomponents.core5:httpcore5-reactive:5.1.3'
|
||||
dependency("org.apache.httpcomponents:httpclient:4.5.13") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependency("org.apache.httpcomponents:httpasyncclient:4.1.5") {
|
||||
exclude group: "commons-logging", name: "commons-logging"
|
||||
}
|
||||
dependencySet(group: 'com.squareup.okhttp3', version: '3.14.9') {
|
||||
entry 'okhttp'
|
||||
entry 'mockwebserver'
|
||||
}
|
||||
|
||||
dependency "org.jruby:jruby:9.2.20.1"
|
||||
dependency "org.jruby:jruby:9.3.3.0"
|
||||
dependency "org.python:jython-standalone:2.7.1"
|
||||
dependency "org.mozilla:rhino:1.7.11"
|
||||
|
||||
dependency "commons-fileupload:commons-fileupload:1.4"
|
||||
dependency "org.synchronoss.cloud:nio-multipart-parser:1.1.0"
|
||||
|
||||
dependency("org.dom4j:dom4j:2.1.3") {
|
||||
exclude group: 'javax.xml.bind', name: "jaxb-api"
|
||||
exclude group: "jaxen", name: "jaxen"
|
||||
exclude group: "net.java.dev.msv", name: "xsdlib"
|
||||
exclude group: "pull-parser", name: "pull-parser"
|
||||
@@ -220,68 +199,47 @@ configure(allprojects) { project ->
|
||||
dependency "com.jayway.jsonpath:json-path:2.6.0"
|
||||
dependency "org.bouncycastle:bcpkix-jdk15on:1.66"
|
||||
|
||||
dependencySet(group: 'org.apache.tiles', version: '3.0.8') {
|
||||
entry 'tiles-api'
|
||||
entry('tiles-core', withoutJclOverSlf4j)
|
||||
entry('tiles-servlet', withoutJclOverSlf4j)
|
||||
entry('tiles-jsp', withoutJclOverSlf4j)
|
||||
entry('tiles-el', withoutJclOverSlf4j)
|
||||
entry('tiles-extras') {
|
||||
exclude group: "org.springframework", name: "spring-web"
|
||||
exclude group: "org.slf4j", name: "jcl-over-slf4j"
|
||||
}
|
||||
}
|
||||
dependency("org.apache.taglibs:taglibs-standard-jstlel:1.2.5") {
|
||||
exclude group: "org.apache.taglibs", name: "taglibs-standard-spec"
|
||||
}
|
||||
dependency "javax.cache:cache-api:1.1.1"
|
||||
dependency "javax.money:money-api:1.1"
|
||||
dependency "org.javamoney:moneta:1.4.2"
|
||||
|
||||
dependency "com.ibm.websphere:uow:6.0.2.17"
|
||||
dependency "com.jamonapi:jamon:2.82"
|
||||
dependency "joda-time:joda-time:2.10.13"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10"
|
||||
dependency "org.javamoney:moneta:1.3"
|
||||
dependency "jakarta.activation:jakarta.activation-api:2.0.1"
|
||||
dependency "jakarta.annotation:jakarta.annotation-api:2.0.0"
|
||||
dependency "jakarta.ejb:jakarta.ejb-api:4.0.0"
|
||||
dependency "jakarta.el:jakarta.el-api:4.0.0"
|
||||
dependency "jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:2.0.0"
|
||||
dependency "jakarta.faces:jakarta.faces-api:3.0.0"
|
||||
dependency "jakarta.inject:jakarta.inject-api:2.0.0"
|
||||
dependency "jakarta.inject:jakarta.inject-tck:2.0.1"
|
||||
dependency "jakarta.interceptor:jakarta.interceptor-api:2.0.0"
|
||||
dependency "jakarta.jms:jakarta.jms-api:3.0.0"
|
||||
dependency "jakarta.json:jakarta.json-api:2.0.1"
|
||||
dependency "jakarta.json.bind:jakarta.json.bind-api:2.0.0"
|
||||
dependency "jakarta.mail:jakarta.mail-api:2.0.1"
|
||||
dependency "jakarta.persistence:jakarta.persistence-api:3.0.0"
|
||||
dependency "jakarta.resource:jakarta.resource-api:2.0.0"
|
||||
dependency "jakarta.servlet:jakarta.servlet-api:5.0.0"
|
||||
dependency "jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0"
|
||||
dependency "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:2.0.0"
|
||||
dependency "jakarta.transaction:jakarta.transaction-api:2.0.0"
|
||||
dependency "jakarta.validation:jakarta.validation-api:3.0.0"
|
||||
dependency "jakarta.websocket:jakarta.websocket-api:2.0.0"
|
||||
dependency "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"
|
||||
|
||||
dependency "com.sun.activation:javax.activation:1.2.0"
|
||||
dependency "com.sun.mail:javax.mail:1.6.2"
|
||||
dependencySet(group: 'com.sun.xml.bind', version: '2.3.0.1') {
|
||||
dependency "com.sun.activation:jakarta.activation:2.0.1"
|
||||
dependency "com.sun.mail:jakarta.mail:2.0.1"
|
||||
dependencySet(group: 'com.sun.xml.bind', version: '3.0.2') {
|
||||
entry 'jaxb-core'
|
||||
entry 'jaxb-impl'
|
||||
entry 'jaxb-xjc'
|
||||
}
|
||||
|
||||
dependency "javax.activation:javax.activation-api:1.2.0"
|
||||
dependency "javax.annotation:javax.annotation-api:1.3.2"
|
||||
dependency "javax.cache:cache-api:1.1.0"
|
||||
dependency "javax.ejb:javax.ejb-api:3.2"
|
||||
dependency "javax.el:javax.el-api:3.0.1-b04"
|
||||
dependency "javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0"
|
||||
dependency "javax.faces:javax.faces-api:2.2"
|
||||
dependency "javax.inject:javax.inject:1"
|
||||
dependency "javax.inject:javax.inject-tck:1"
|
||||
dependency "javax.interceptor:javax.interceptor-api:1.2.2"
|
||||
dependency "javax.jms:javax.jms-api:2.0.1"
|
||||
dependency "javax.json:javax.json-api:1.1.4"
|
||||
dependency "javax.json.bind:javax.json.bind-api:1.0"
|
||||
dependency "javax.mail:javax.mail-api:1.6.2"
|
||||
dependency "javax.money:money-api:1.0.3"
|
||||
dependency "javax.resource:javax.resource-api:1.7.1"
|
||||
dependency "javax.servlet:javax.servlet-api:4.0.1"
|
||||
dependency "javax.servlet.jsp:javax.servlet.jsp-api:2.3.2-b02"
|
||||
dependency "javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1"
|
||||
dependency "javax.transaction:javax.transaction-api:1.3"
|
||||
dependency "javax.validation:validation-api:2.0.1.Final"
|
||||
dependency "javax.websocket:javax.websocket-api:1.1"
|
||||
dependency "javax.xml.bind:jaxb-api:2.3.1"
|
||||
dependency "javax.xml.ws:jaxws-api:2.3.1"
|
||||
|
||||
dependency "org.eclipse.persistence:javax.persistence:2.2.0"
|
||||
|
||||
// Substitute for "javax.management:jmxremote_optional:1.0.1_04" which
|
||||
// is not available on Maven Central
|
||||
dependency "org.glassfish.external:opendmk_jmxremote_optional_jar:1.0-b01-ea"
|
||||
dependency "org.glassfish:javax.el:3.0.1-b08"
|
||||
dependency "org.glassfish.main:javax.jws:4.0-b33"
|
||||
dependency "org.glassfish.tyrus:tyrus-container-servlet:1.13.1"
|
||||
dependency "org.glassfish:jakarta.el:4.0.2"
|
||||
dependency "org.glassfish.tyrus:tyrus-container-servlet:2.0.1"
|
||||
dependency "org.eclipse.persistence:org.eclipse.persistence.jpa:3.0.2"
|
||||
}
|
||||
generatedPomCustomization {
|
||||
enabled = false
|
||||
@@ -318,15 +276,15 @@ configure([rootProject] + javaProjects) { project ->
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
languageVersion = "1.3"
|
||||
apiVersion = "1.3"
|
||||
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings", "-Xopt-in=kotlin.RequiresOptIn"]
|
||||
languageVersion = "1.6"
|
||||
apiVersion = "1.6"
|
||||
freeCompilerArgs = ["-Xjsr305=strict", "-Xsuppress-version-warnings", "-opt-in=kotlin.RequiresOptIn"]
|
||||
allWarningsAsErrors = true
|
||||
}
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
freeCompilerArgs = ["-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,16 +324,13 @@ configure([rootProject] + javaProjects) { project ->
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"https://docs.oracle.com/javase/8/docs/api/",
|
||||
"https://docs.oracle.com/javaee/7/api/",
|
||||
"https://docs.oracle.com/en/java/javase/17/docs/api/",
|
||||
"https://jakarta.ee/specifications/platform/9/apidocs/",
|
||||
"https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
|
||||
"https://www.ibm.com/docs/api/v1/content/SSEQTP_8.5.5/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/",
|
||||
"https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/",
|
||||
"https://tiles.apache.org/tiles-request/apidocs/",
|
||||
"https://tiles.apache.org/framework/apidocs/",
|
||||
"https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"https://www.ehcache.org/apidocs/2.10.4/",
|
||||
"https://www.quartz-scheduler.org/api/2.3.0/",
|
||||
"https://fasterxml.github.io/jackson-core/javadoc/2.10/",
|
||||
"https://fasterxml.github.io/jackson-databind/javadoc/2.10/",
|
||||
@@ -383,12 +338,15 @@ configure([rootProject] + javaProjects) { project ->
|
||||
"https://hc.apache.org/httpcomponents-client-5.1.x/current/httpclient5/apidocs/",
|
||||
"https://projectreactor.io/docs/test/release/api/",
|
||||
"https://junit.org/junit4/javadoc/4.13.2/",
|
||||
// Disabling linking to JUnit 5.8.2, since the `package-list` file no longer exists due to
|
||||
// https://github.com/junit-team/junit5/commit/67ad4e545518b0ce2b0e7c96df31a669866d5003.
|
||||
// TODO Uncomment link to JUnit 5 docs once we have sorted out
|
||||
// the following warning in the build.
|
||||
//
|
||||
// warning: The code being documented uses packages in the unnamed module, but the packages defined in https://junit.org/junit5/docs/5.8.1/api/ are in named modules.
|
||||
//
|
||||
// "https://junit.org/junit5/docs/5.8.2/api/",
|
||||
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
|
||||
"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
|
||||
"https://r2dbc.io/spec/0.8.5.RELEASE/api/",
|
||||
"https://r2dbc.io/spec/0.9.1.RELEASE/api/",
|
||||
// The external Javadoc link for JSR 305 must come last to ensure that types from
|
||||
// JSR 250 (such as @PostConstruct) are still supported. This is due to the fact
|
||||
// that JSR 250 and JSR 305 both define types in javax.annotation, which results
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.build.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
@@ -23,10 +24,14 @@ import java.util.List;
|
||||
|
||||
import me.champeau.gradle.japicmp.JapicmpPlugin;
|
||||
import me.champeau.gradle.japicmp.JapicmpTask;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.repositories.ArtifactRepository;
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
|
||||
import org.gradle.api.artifacts.repositories.RepositoryContentDescriptor;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
|
||||
@@ -52,6 +57,8 @@ public class ApiDiffPlugin implements Plugin<Project> {
|
||||
|
||||
private static final List<String> PACKAGE_INCLUDES = Collections.singletonList("org.springframework.*");
|
||||
|
||||
private static final URI SPRING_MILESTONE_REPOSITORY = URI.create("https://repo.spring.io/milestone");
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
if (project.hasProperty(BASELINE_VERSION_PROPERTY) && project.equals(project.getRootProject())) {
|
||||
@@ -68,6 +75,10 @@ public class ApiDiffPlugin implements Plugin<Project> {
|
||||
|
||||
private void createApiDiffTask(String baselineVersion, Project project) {
|
||||
if (isProjectEligible(project)) {
|
||||
// Add Spring Milestone repository for generating diffs against previous milestones
|
||||
project.getRootProject()
|
||||
.getRepositories()
|
||||
.maven(mavenArtifactRepository -> mavenArtifactRepository.setUrl(SPRING_MILESTONE_REPOSITORY));
|
||||
JapicmpTask apiDiff = project.getTasks().create(TASK_NAME, JapicmpTask.class);
|
||||
apiDiff.setDescription("Generates an API diff report with japicmp");
|
||||
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
|
||||
|
||||
-2
@@ -24,7 +24,6 @@ import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaLibraryPlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
|
||||
/**
|
||||
@@ -70,7 +69,6 @@ public class CompilerConventionsPlugin implements Plugin<Project> {
|
||||
* @param project the current project
|
||||
*/
|
||||
private void applyJavaCompileConventions(Project project) {
|
||||
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
|
||||
project.getTasks().withType(JavaCompile.class)
|
||||
.matching(compileTask -> compileTask.getName().equals(JavaPlugin.COMPILE_JAVA_TASK_NAME))
|
||||
.forEach(compileTask -> {
|
||||
|
||||
+2
-5
@@ -19,12 +19,9 @@ package org.springframework.build.optional;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.tasks.SourceSetContainer;
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin;
|
||||
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
|
||||
|
||||
/**
|
||||
* A {@code Plugin} that adds support for Maven-style optional dependencies. Creates a new
|
||||
@@ -47,7 +44,7 @@ public class OptionalDependenciesPlugin implements Plugin<Project> {
|
||||
optional.setCanBeConsumed(false);
|
||||
optional.setCanBeResolved(false);
|
||||
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
|
||||
SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class)
|
||||
SourceSetContainer sourceSets = project.getExtensions().getByType(JavaPluginExtension.class)
|
||||
.getSourceSets();
|
||||
sourceSets.all((sourceSet) -> {
|
||||
project.getConfigurations().getByName(sourceSet.getCompileClasspathConfigurationName()).extendsFrom(optional);
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
The Spring Framework uses https://concourse-ci.org/[Concourse] for its CI build and other automated tasks.
|
||||
The Spring team has a dedicated Concourse instance available at https://ci.spring.io with a build pipeline
|
||||
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-5.3.x[Spring Framework 5.3.x].
|
||||
for https://ci.spring.io/teams/spring-framework/pipelines/spring-framework-6.0.x[Spring Framework 6.0.x].
|
||||
|
||||
=== Setting up your development environment
|
||||
|
||||
@@ -51,7 +51,7 @@ The pipeline can be deployed using the following command:
|
||||
|
||||
[source]
|
||||
----
|
||||
$ fly -t spring set-pipeline -p spring-framework-5.3.x -c ci/pipeline.yml -l ci/parameters.yml
|
||||
$ fly -t spring set-pipeline -p spring-framework-6.0.x -c ci/pipeline.yml -l ci/parameters.yml
|
||||
----
|
||||
|
||||
NOTE: This assumes that you have credhub integration configured with the appropriate secrets.
|
||||
|
||||
@@ -2,10 +2,10 @@ FROM ubuntu:focal-20220302
|
||||
|
||||
ADD setup.sh /setup.sh
|
||||
ADD get-jdk-url.sh /get-jdk-url.sh
|
||||
RUN ./setup.sh java8
|
||||
RUN ./setup.sh
|
||||
|
||||
ENV JAVA_HOME /opt/openjdk/java8
|
||||
ENV JDK11 /opt/openjdk/java11
|
||||
ENV JAVA_HOME /opt/openjdk/java17
|
||||
ENV JDK17 /opt/openjdk/java17
|
||||
ENV JDK18 /opt/openjdk/java18
|
||||
|
||||
ENV PATH $JAVA_HOME/bin:$PATH
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
java8)
|
||||
echo "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u322-b06/OpenJDK8U-jdk_x64_linux_hotspot_8u322b06.tar.gz"
|
||||
;;
|
||||
java11)
|
||||
echo "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.14.1%2B1/OpenJDK11U-jdk_x64_linux_hotspot_11.0.14.1_1.tar.gz"
|
||||
;;
|
||||
java17)
|
||||
echo "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz"
|
||||
echo "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.2%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.2_8.tar.gz"
|
||||
;;
|
||||
java18)
|
||||
echo "https://github.com/adoptium/temurin18-binaries/releases/download/jdk18-2022-02-12-08-06-beta/OpenJDK18-jdk_x64_linux_hotspot_2022-02-12-08-06.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo $"Unknown java version"
|
||||
exit 1
|
||||
echo $"Unknown java version"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ curl --output /opt/concourse-release-scripts.jar https://repo.spring.io/release/
|
||||
|
||||
mkdir -p /opt/openjdk
|
||||
pushd /opt/openjdk > /dev/null
|
||||
for jdk in java8 java11 java17
|
||||
for jdk in java17 java18
|
||||
do
|
||||
JDK_URL=$( /get-jdk-url.sh $jdk )
|
||||
mkdir $jdk
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@ github-repo: "https://github.com/spring-projects/spring-framework.git"
|
||||
github-repo-name: "spring-projects/spring-framework"
|
||||
docker-hub-organization: "springci"
|
||||
artifactory-server: "https://repo.spring.io"
|
||||
branch: "5.3.x"
|
||||
milestone: "5.3.x"
|
||||
branch: "main"
|
||||
milestone: "6.0.x"
|
||||
build-name: "spring-framework"
|
||||
pipeline-name: "spring-framework"
|
||||
concourse-url: "https://ci.spring.io"
|
||||
|
||||
+22
-58
@@ -72,13 +72,6 @@ resources:
|
||||
icon: github
|
||||
source:
|
||||
<<: *git-repo-resource-source
|
||||
- name: every-morning
|
||||
type: time
|
||||
icon: alarm
|
||||
source:
|
||||
start: 8:00 AM
|
||||
stop: 9:00 AM
|
||||
location: Europe/Vienna
|
||||
- name: ci-images-git-repo
|
||||
type: git
|
||||
icon: github
|
||||
@@ -92,6 +85,13 @@ resources:
|
||||
source:
|
||||
<<: *docker-resource-source
|
||||
repository: ((docker-hub-organization))/spring-framework-ci
|
||||
- name: every-morning
|
||||
type: time
|
||||
icon: alarm
|
||||
source:
|
||||
start: 8:00 AM
|
||||
stop: 9:00 AM
|
||||
location: Europe/Vienna
|
||||
- name: artifactory-repo
|
||||
type: artifactory-resource
|
||||
icon: package-variant
|
||||
@@ -116,22 +116,14 @@ resources:
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: build
|
||||
- name: repo-status-jdk11-build
|
||||
- name: repo-status-jdk18-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk11-build
|
||||
- name: repo-status-jdk17-build
|
||||
type: github-status-resource
|
||||
icon: eye-check-outline
|
||||
source:
|
||||
repository: ((github-repo-name))
|
||||
access_token: ((github-ci-status-token))
|
||||
branch: ((branch))
|
||||
context: jdk17-build
|
||||
context: jdk18-build
|
||||
- name: slack-alert
|
||||
type: slack-notification
|
||||
icon: slack
|
||||
@@ -221,35 +213,7 @@ jobs:
|
||||
"zip.type": "schema"
|
||||
get_params:
|
||||
threads: 8
|
||||
- name: jdk11-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
- get: ci-image
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 11
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk11-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: jdk17-build
|
||||
- name: jdk18-build
|
||||
serial: true
|
||||
public: true
|
||||
plan:
|
||||
@@ -257,25 +221,25 @@ jobs:
|
||||
- get: git-repo
|
||||
- get: every-morning
|
||||
trigger: true
|
||||
- put: repo-status-jdk17-build
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "pending", commit: "git-repo" }
|
||||
- do:
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 15
|
||||
<<: *build-project-task-params
|
||||
- task: check-project
|
||||
image: ci-image
|
||||
file: git-repo/ci/tasks/check-project.yml
|
||||
privileged: true
|
||||
timeout: ((task-timeout))
|
||||
params:
|
||||
TEST_TOOLCHAIN: 18
|
||||
<<: *build-project-task-params
|
||||
on_failure:
|
||||
do:
|
||||
- put: repo-status-jdk17-build
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "failure", commit: "git-repo" }
|
||||
- put: slack-alert
|
||||
params:
|
||||
<<: *slack-fail-params
|
||||
- put: repo-status-jdk17-build
|
||||
- put: repo-status-jdk18-build
|
||||
params: { state: "success", commit: "git-repo" }
|
||||
- name: build-pull-requests
|
||||
serial: true
|
||||
@@ -458,7 +422,7 @@ jobs:
|
||||
|
||||
groups:
|
||||
- name: "builds"
|
||||
jobs: ["build", "jdk11-build", "jdk17-build"]
|
||||
jobs: ["build", "jdk18-build"]
|
||||
- name: "releases"
|
||||
jobs: ["stage-milestone", "stage-rc", "stage-release", "promote-milestone", "promote-rc", "promote-release", "create-github-release"]
|
||||
- name: "ci-images"
|
||||
|
||||
@@ -4,6 +4,6 @@ set -e
|
||||
source $(dirname $0)/common.sh
|
||||
|
||||
pushd git-repo > /dev/null
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK11,JDK15 \
|
||||
./gradlew -Dorg.gradle.internal.launcher.welcomeMessageEnabled=false -Porg.gradle.java.installations.fromEnv=JDK17,JDK18 \
|
||||
-PmainToolchain=${MAIN_TOOLCHAIN} -PtestToolchain=${TEST_TOOLCHAIN} --no-daemon --max-workers=4 check
|
||||
popd > /dev/null
|
||||
|
||||
@@ -7,7 +7,7 @@ group = "org.springframework"
|
||||
|
||||
dependencies {
|
||||
constraints {
|
||||
parent.moduleProjects.sort { "$it.name" }.each {
|
||||
parent.moduleProjects.findAll{ it.name != 'spring-core-test' }.sort{ "$it.name" }.each {
|
||||
api it
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
version=5.3.17-SNAPSHOT
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
version=6.0.0-M3
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
kotlin.stdlib.default.dependency=false
|
||||
kotlin.stdlib.default.dependency=false
|
||||
|
||||
@@ -20,7 +20,7 @@ tasks.findByName("dokkaHtmlPartial")?.configure {
|
||||
url.set(new URL("https://javadoc.io/doc/org.hamcrest/hamcrest/2.1/"))
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url.set(new URL("https://javadoc.io/doc/javax.servlet/javax.servlet-api/latest/"))
|
||||
url.set(new URL("https://javadoc.io/doc/jakarta.servlet/jakarta.servlet-api/latest/"))
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url.set(new URL("https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/"))
|
||||
|
||||
+1
-5
@@ -43,14 +43,10 @@ task api(type: Javadoc) {
|
||||
header = rootProject.description
|
||||
use = true
|
||||
overview = "src/docs/api/overview.html"
|
||||
stylesheetFile = file("src/docs/api/stylesheet.css")
|
||||
splitIndex = true
|
||||
links(project.ext.javadocLinks)
|
||||
addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
|
||||
addBooleanOption('Xwerror', true) // fail build on Javadoc warnings
|
||||
if (JavaVersion.current().isJava9Compatible()) {
|
||||
addBooleanOption('html5', true)
|
||||
}
|
||||
addBooleanOption('Werror', true) // fail build on Javadoc warnings
|
||||
}
|
||||
source moduleProjects.collect { project ->
|
||||
project.sourceSets.main.allJava
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
eclipse.jdt {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
}
|
||||
|
||||
// Replace classpath entries with project dependencies (GRADLE-1116)
|
||||
|
||||
+21
-60
@@ -5,13 +5,13 @@
|
||||
* One can choose the toolchain to use for compiling the MAIN sources and/or compiling
|
||||
* and running the TEST sources. These options apply to Java, Kotlin and Groovy sources
|
||||
* when available.
|
||||
* {@code "./gradlew check -PmainToolchain=8 -PtestToolchain=11"} will use:
|
||||
* {@code "./gradlew check -PmainToolchain=17 -PtestToolchain=18"} will use:
|
||||
* <ul>
|
||||
* <li>a JDK8 toolchain for compiling the main SourceSet
|
||||
* <li>a JDK11 toolchain for compiling and running the test SourceSet
|
||||
* <li>a JDK17 toolchain for compiling the main SourceSet
|
||||
* <li>a JDK18 toolchain for compiling and running the test SourceSet
|
||||
* </ul>
|
||||
*
|
||||
* By default, the build will fall back to using the current JDK and 1.8 language level for all sourceSets.
|
||||
* By default, the build will fall back to using the current JDK and 17 language level for all sourceSets.
|
||||
*
|
||||
* Gradle will automatically detect JDK distributions in well-known locations.
|
||||
* The following command will list the detected JDKs on the host.
|
||||
@@ -21,11 +21,11 @@
|
||||
*
|
||||
* We can also configure ENV variables and let Gradle know about them:
|
||||
* {@code
|
||||
* $ echo JDK11
|
||||
* /opt/openjdk/java11
|
||||
* $ echo JDK15
|
||||
* /opt/openjdk/java15
|
||||
* $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK11,JDK15 check
|
||||
* $ echo JDK17
|
||||
* /opt/openjdk/java17
|
||||
* $ echo JDK18
|
||||
* /opt/openjdk/java18
|
||||
* $ ./gradlew -Porg.gradle.java.installations.fromEnv=JDK17,JDK18 check
|
||||
* }
|
||||
*
|
||||
* @author Brian Clozel
|
||||
@@ -44,7 +44,7 @@ def mainToolchainLanguageVersion() {
|
||||
if (mainToolchainConfigured()) {
|
||||
return JavaLanguageVersion.of(project.mainToolchain.toString())
|
||||
}
|
||||
return JavaLanguageVersion.of(8)
|
||||
return JavaLanguageVersion.of(17)
|
||||
}
|
||||
|
||||
def testToolchainLanguageVersion() {
|
||||
@@ -64,9 +64,9 @@ plugins.withType(JavaPlugin) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Fallback to JDK8
|
||||
// Fallback to JDK17
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
// Configure a specific Java Toolchain for compiling and running tests if the 'testToolchain' property is defined
|
||||
@@ -86,63 +86,24 @@ plugins.withType(JavaPlugin) {
|
||||
}
|
||||
|
||||
plugins.withType(GroovyPlugin) {
|
||||
// Fallback to JDK8
|
||||
// Fallback to JDK17
|
||||
if (!mainToolchainConfigured()) {
|
||||
compileGroovy {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pluginManager.withPlugin("kotlin") {
|
||||
// Configure the Kotlin compiler if the 'mainToolchain' property is defined
|
||||
if (mainToolchainConfigured()) {
|
||||
def mainLanguageVersion = mainToolchainLanguageVersion()
|
||||
def compiler = javaToolchains.compilerFor {
|
||||
languageVersion = mainLanguageVersion
|
||||
}
|
||||
// See https://kotlinlang.org/docs/gradle.html#attributes-specific-for-jvm
|
||||
def javaVersion = mainLanguageVersion.toString() == '8' ? '1.8' : mainLanguageVersion.toString()
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
|
||||
}
|
||||
}
|
||||
// Compile the test classes with the same version, 'testToolchain' will override if defined
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
|
||||
}
|
||||
// Fallback to JDK17
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = '17'
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Fallback to JDK8
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (testToolchainConfigured()) {
|
||||
def testLanguageVersion = testToolchainLanguageVersion()
|
||||
def compiler = javaToolchains.compilerFor {
|
||||
languageVersion = testLanguageVersion
|
||||
}
|
||||
// See https://kotlinlang.org/docs/gradle.html#attributes-specific-for-jvm
|
||||
def javaVersion = testLanguageVersion.toString() == '8' ? '1.8' : testLanguageVersion.toString()
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = javaVersion
|
||||
jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = '17'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
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. As a bare minimum you will need Eclipse with full Java
|
||||
8 support, Eclipse Buildship, and the Groovy plugin.
|
||||
17 support and Eclipse Buildship.
|
||||
|
||||
The following instructions have been tested against [STS](https://spring.io/tools) 4.12.0
|
||||
([download](https://github.com/spring-projects/sts4/wiki/Previous-Versions#spring-tools-4120-changelog))
|
||||
@@ -12,13 +12,14 @@ The instructions should work with the latest Eclipse distribution as long as you
|
||||
[Buildship](https://marketplace.eclipse.org/content/buildship-gradle-integration). Note
|
||||
that STS 4 comes with Buildship preinstalled.
|
||||
|
||||
If you are using Eclipse 4.21, you will need to install
|
||||
[Java 17 Support for Eclipse 2021-09 (4.21)](https://marketplace.eclipse.org/content/java-17-support-eclipse-2021-09-421)
|
||||
from the Eclipse Marketplace.
|
||||
|
||||
## Steps
|
||||
|
||||
_When instructed to execute `./gradlew` from the command line, be sure to execute it within your locally cloned `spring-framework` working directory._
|
||||
|
||||
1. Install the [Groovy Development Tools](https://marketplace.eclipse.org/content/groovy-development-tools).
|
||||
1. Switch to Groovy 3.0 in Eclipse (Preferences → Groovy → Compiler → Switch to 3.0...).
|
||||
- If you encounter build errors stating something similar to _"Groovy: compiler mismatch: project level is 2.5, workspace level is 3.0"_, change the Groovy compiler version to 3.0 for each affected project.
|
||||
1. Ensure that the _Forbidden reference (access rule)_ in Eclipse is set to `Info`
|
||||
(Preferences → Java → Compiler → Errors/Warnings → Deprecated and restricted API → Forbidden reference (access rule)).
|
||||
1. Optionally install the [Kotlin Plugin for Eclipse](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse) if you need to execute Kotlin-based tests or develop Kotlin extensions.
|
||||
|
||||
@@ -15,12 +15,12 @@ dependencies {
|
||||
testImplementation(project(":spring-test"))
|
||||
testImplementation(project(":spring-tx"))
|
||||
testImplementation(project(":spring-web"))
|
||||
testImplementation("javax.inject:javax.inject")
|
||||
testImplementation("javax.resource:javax.resource-api")
|
||||
testImplementation("javax.servlet:javax.servlet-api")
|
||||
testImplementation("jakarta.inject:jakarta.inject-api")
|
||||
testImplementation("jakarta.resource:jakarta.resource-api")
|
||||
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
||||
testImplementation("org.aspectj:aspectjweaver")
|
||||
testImplementation("org.hsqldb:hsqldb")
|
||||
testImplementation("org.hibernate:hibernate-core")
|
||||
testImplementation("org.hibernate:hibernate-core-jakarta")
|
||||
}
|
||||
|
||||
normalization {
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
|
||||
+8
-10
@@ -21,9 +21,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -308,19 +307,18 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
scanner.setIncludeAnnotationConfig(false);
|
||||
scanner.setScopeMetadataResolver(definition -> {
|
||||
ScopeMetadata metadata = new ScopeMetadata();
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||
if (definition instanceof AnnotatedBeanDefinition annDef) {
|
||||
for (String type : annDef.getMetadata().getAnnotationTypes()) {
|
||||
if (type.equals(javax.inject.Singleton.class.getName())) {
|
||||
if (type.equals(jakarta.inject.Singleton.class.getName())) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_SINGLETON);
|
||||
break;
|
||||
}
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(javax.inject.Scope.class.getName())) {
|
||||
else if (annDef.getMetadata().getMetaAnnotationTypes(type).contains(jakarta.inject.Scope.class.getName())) {
|
||||
metadata.setScopeName(type.substring(type.length() - 13, type.length() - 6).toLowerCase());
|
||||
metadata.setScopedProxyMode(scopedProxyMode);
|
||||
break;
|
||||
}
|
||||
else if (type.startsWith("javax.inject")) {
|
||||
else if (type.startsWith("jakarta.inject")) {
|
||||
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
}
|
||||
}
|
||||
@@ -387,14 +385,14 @@ class ClassPathBeanDefinitionScannerJsr330ScopeIntegrationTests {
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
@jakarta.inject.Scope
|
||||
public @interface RequestScoped {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@javax.inject.Scope
|
||||
@jakarta.inject.Scope
|
||||
public @interface SessionScoped {
|
||||
}
|
||||
|
||||
|
||||
Vendored
-19
@@ -41,9 +41,6 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jca.context.ResourceAdapterApplicationContext;
|
||||
import org.springframework.jca.support.SimpleBootstrapContext;
|
||||
import org.springframework.jca.work.SimpleTaskWorkManager;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.mock.web.MockServletConfig;
|
||||
@@ -535,22 +532,6 @@ public class EnvironmentSystemIntegrationTests {
|
||||
assertThat(environment.getProperty("pSysProps1")).isEqualTo("pSysProps1Value");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resourceAdapterApplicationContext() {
|
||||
ResourceAdapterApplicationContext ctx = new ResourceAdapterApplicationContext(new SimpleBootstrapContext(new SimpleTaskWorkManager()));
|
||||
|
||||
assertHasStandardEnvironment(ctx);
|
||||
|
||||
registerEnvironmentBeanDefinition(ctx);
|
||||
|
||||
ctx.setEnvironment(prodEnv);
|
||||
ctx.refresh();
|
||||
|
||||
assertHasEnvironment(ctx, prodEnv);
|
||||
assertEnvironmentBeanRegistered(ctx);
|
||||
assertEnvironmentAwareInvoked(ctx, prodEnv);
|
||||
}
|
||||
|
||||
@Test
|
||||
void abstractApplicationContextValidatesRequiredPropertiesOnRefresh() {
|
||||
{
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
<props>
|
||||
<prop key="setA*">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="rollbackOnly">PROPAGATION_REQUIRED</prop>
|
||||
<prop key="echoException">PROPAGATION_REQUIRED,+javax.servlet.ServletException,-java.lang.Exception</prop>
|
||||
<prop key="echoException">PROPAGATION_REQUIRED,+jakarta.servlet.ServletException,-java.lang.Exception</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -18,6 +18,7 @@ include "spring-context"
|
||||
include "spring-context-indexer"
|
||||
include "spring-context-support"
|
||||
include "spring-core"
|
||||
include "spring-core-test"
|
||||
include "spring-expression"
|
||||
include "spring-instrument"
|
||||
include "spring-jcl"
|
||||
|
||||
@@ -5,7 +5,6 @@ dependencies {
|
||||
api(project(":spring-core"))
|
||||
optional("org.aspectj:aspectjweaver")
|
||||
optional("org.apache.commons:commons-pool2")
|
||||
optional("com.jamonapi:jamon")
|
||||
testImplementation(testFixtures(project(":spring-beans")))
|
||||
testImplementation(testFixtures(project(":spring-core")))
|
||||
testFixturesImplementation(testFixtures(project(":spring-beans")))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -78,10 +78,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
*/
|
||||
public static JoinPoint currentJoinPoint() {
|
||||
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
if (!(mi instanceof ProxyMethodInvocation pmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
|
||||
if (jp == null) {
|
||||
jp = new MethodInvocationProceedingJoinPoint(pmi);
|
||||
@@ -262,7 +261,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
public void setArgumentNamesFromStringArray(String... args) {
|
||||
this.argumentNames = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
|
||||
this.argumentNames[i] = args[i].strip();
|
||||
if (!isVariableName(this.argumentNames[i])) {
|
||||
throw new IllegalArgumentException(
|
||||
"'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
|
||||
@@ -714,10 +713,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AdviceExcludingMethodMatcher)) {
|
||||
if (!(other instanceof AdviceExcludingMethodMatcher otherMm)) {
|
||||
return false;
|
||||
}
|
||||
AdviceExcludingMethodMatcher otherMm = (AdviceExcludingMethodMatcher) other;
|
||||
return this.adviceMethod.equals(otherMm.adviceMethod);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -158,7 +158,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
|
||||
/** The pointcut expression associated with the advice, as a simple String. */
|
||||
@Nullable
|
||||
private String pointcutExpression;
|
||||
private final String pointcutExpression;
|
||||
|
||||
private boolean raiseExceptions;
|
||||
|
||||
@@ -486,7 +486,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(argsSpec, ",");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
tokens[i] = StringUtils.trimWhitespace(tokens[i]);
|
||||
tokens[i] = tokens[i].strip();
|
||||
String varName = maybeExtractVariableName(tokens[i]);
|
||||
if (varName != null) {
|
||||
varNames.add(varName);
|
||||
@@ -759,10 +759,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
*/
|
||||
private static class PointcutBody {
|
||||
|
||||
private int numTokensConsumed;
|
||||
private final int numTokensConsumed;
|
||||
|
||||
@Nullable
|
||||
private String text;
|
||||
private final String text;
|
||||
|
||||
public PointcutBody(int tokens, @Nullable String text) {
|
||||
this.numTokensConsumed = tokens;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -63,10 +63,9 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
if (!(mi instanceof ProxyMethodInvocation pmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
|
||||
JoinPointMatch jpm = getJoinPointMatch(pmi);
|
||||
return invokeAdviceMethod(pjp, jpm, null, null);
|
||||
|
||||
+1
-2
@@ -523,10 +523,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AspectJExpressionPointcut)) {
|
||||
if (!(other instanceof AspectJExpressionPointcut otherPc)) {
|
||||
return false;
|
||||
}
|
||||
AspectJExpressionPointcut otherPc = (AspectJExpressionPointcut) other;
|
||||
return ObjectUtils.nullSafeEquals(this.getExpression(), otherPc.getExpression()) &&
|
||||
ObjectUtils.nullSafeEquals(this.pointcutDeclarationScope, otherPc.pointcutDeclarationScope) &&
|
||||
ObjectUtils.nullSafeEquals(this.pointcutParameterNames, otherPc.pointcutParameterNames) &&
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,10 +97,9 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AspectJPointcutAdvisor)) {
|
||||
if (!(other instanceof AspectJPointcutAdvisor otherAdvisor)) {
|
||||
return false;
|
||||
}
|
||||
AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other;
|
||||
return this.advice.equals(otherAdvisor.advice);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -214,8 +214,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
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 (val instanceof String str) {
|
||||
if (!str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
|
||||
+9
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -101,24 +101,22 @@ public class AspectMetadata implements Serializable {
|
||||
this.ajType = ajType;
|
||||
|
||||
switch (this.ajType.getPerClause().getKind()) {
|
||||
case SINGLETON:
|
||||
case SINGLETON -> {
|
||||
this.perClausePointcut = Pointcut.TRUE;
|
||||
return;
|
||||
case PERTARGET:
|
||||
case PERTHIS:
|
||||
}
|
||||
case PERTARGET, PERTHIS -> {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setLocation(aspectClass.getName());
|
||||
ajexp.setExpression(findPerClause(aspectClass));
|
||||
ajexp.setPointcutDeclarationScope(aspectClass);
|
||||
this.perClausePointcut = ajexp;
|
||||
return;
|
||||
case PERTYPEWITHIN:
|
||||
}
|
||||
case PERTYPEWITHIN -> {
|
||||
// Works with a type pattern
|
||||
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
|
||||
return;
|
||||
default:
|
||||
throw new AopConfigException(
|
||||
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
|
||||
}
|
||||
default -> throw new AopConfigException(
|
||||
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -220,21 +220,18 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
else {
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
case AtAround:
|
||||
case AtPointcut, AtAround -> {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
}
|
||||
case AtBefore -> {
|
||||
this.isBeforeAdvice = true;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtAfter:
|
||||
case AtAfterReturning:
|
||||
case AtAfterThrowing:
|
||||
}
|
||||
case AtAfter, AtAfterReturning, AtAfterThrowing -> {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -261,42 +261,36 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
AbstractAspectJAdvice springAdvice;
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
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);
|
||||
break;
|
||||
case AtAfter:
|
||||
springAdvice = new AspectJAfterAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtAfterReturning:
|
||||
}
|
||||
case AtAround -> springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
case AtBefore -> springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
case AtAfter -> springAdvice = new AspectJAfterAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
case AtAfterReturning -> {
|
||||
springAdvice = new AspectJAfterReturningAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
|
||||
springAdvice.setReturningName(afterReturningAnnotation.returning());
|
||||
}
|
||||
break;
|
||||
case AtAfterThrowing:
|
||||
}
|
||||
case AtAfterThrowing -> {
|
||||
springAdvice = new AspectJAfterThrowingAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
}
|
||||
default -> throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
}
|
||||
|
||||
// Now to configure the advice...
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -59,8 +59,7 @@ class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node instanceof Element) {
|
||||
Element includeElement = (Element) node;
|
||||
if (node instanceof Element includeElement) {
|
||||
TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
|
||||
valueHolder.setSource(parserContext.extractSource(includeElement));
|
||||
includePatterns.add(valueHolder);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -93,7 +93,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private static final int POINTCUT_INDEX = 1;
|
||||
private static final int ASPECT_INSTANCE_FACTORY_INDEX = 2;
|
||||
|
||||
private ParseState parseState = new ParseState();
|
||||
private final ParseState parseState = new ParseState();
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2021 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,8 +42,7 @@ class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
@Override
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
||||
boolean proxyTargetClass = true;
|
||||
if (node instanceof Element) {
|
||||
Element ele = (Element) node;
|
||||
if (node instanceof Element ele) {
|
||||
if (ele.hasAttribute(PROXY_TARGET_CLASS)) {
|
||||
proxyTargetClass = Boolean.parseBoolean(ele.getAttribute(PROXY_TARGET_CLASS));
|
||||
}
|
||||
|
||||
+1
-2
@@ -69,8 +69,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
return bean;
|
||||
}
|
||||
|
||||
if (bean instanceof Advised) {
|
||||
Advised advised = (Advised) bean;
|
||||
if (bean instanceof Advised advised) {
|
||||
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
|
||||
// Add our local Advisor to the existing proxy's Advisor chain...
|
||||
if (this.beforeExistingAdvisors) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -283,8 +283,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
Advisor advisor = this.advisors.remove(index);
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (advisor instanceof IntroductionAdvisor ia) {
|
||||
// We need to remove introduction interfaces.
|
||||
for (Class<?> ifc : ia.getInterfaces()) {
|
||||
removeInterface(ifc);
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for AOP proxy factories.
|
||||
@@ -49,11 +48,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public abstract class AopProxyUtils {
|
||||
|
||||
// JDK 17 Class.isSealed() method available?
|
||||
@Nullable
|
||||
private static final Method isSealedMethod = ClassUtils.getMethodIfAvailable(Class.class, "isSealed");
|
||||
|
||||
|
||||
/**
|
||||
* Obtain the singleton target object behind the given proxy, if any.
|
||||
* @param candidate the (potential) proxy to check
|
||||
@@ -143,7 +137,7 @@ public abstract class AopProxyUtils {
|
||||
List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
|
||||
for (Class<?> ifc : specifiedInterfaces) {
|
||||
// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
|
||||
if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) {
|
||||
if (!ifc.isSealed()) {
|
||||
proxiedInterfaces.add(ifc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,10 +949,9 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ProxyCallbackFilter)) {
|
||||
if (!(other instanceof ProxyCallbackFilter otherCallbackFilter)) {
|
||||
return false;
|
||||
}
|
||||
ProxyCallbackFilter otherCallbackFilter = (ProxyCallbackFilter) other;
|
||||
AdvisedSupport otherAdvised = otherCallbackFilter.advised;
|
||||
if (this.advised.isFrozen() != otherAdvised.isFrozen()) {
|
||||
return false;
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,9 +60,8 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
Boolean hasIntroductions = null;
|
||||
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof PointcutAdvisor) {
|
||||
if (advisor instanceof PointcutAdvisor pointcutAdvisor) {
|
||||
// Add it conditionally.
|
||||
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
|
||||
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
|
||||
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
|
||||
boolean match;
|
||||
@@ -90,8 +89,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
else if (advisor instanceof IntroductionAdvisor ia) {
|
||||
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
|
||||
Interceptor[] interceptors = registry.getInterceptors(advisor);
|
||||
interceptorList.addAll(Arrays.asList(interceptors));
|
||||
@@ -111,8 +109,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
*/
|
||||
private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (advisor instanceof IntroductionAdvisor ia) {
|
||||
if (ia.getClassFilter().matches(actualClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -475,8 +475,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
Advisor[] advisors = getAdvisors();
|
||||
List<Advisor> freshAdvisors = new ArrayList<>(advisors.length);
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof PrototypePlaceholderAdvisor) {
|
||||
PrototypePlaceholderAdvisor pa = (PrototypePlaceholderAdvisor) advisor;
|
||||
if (advisor instanceof PrototypePlaceholderAdvisor pa) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Refreshing bean named '" + pa.getBeanName() + "'");
|
||||
}
|
||||
|
||||
+2
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -165,11 +165,9 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
|
||||
Object interceptorOrInterceptionAdvice =
|
||||
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
|
||||
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
|
||||
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher dm) {
|
||||
// Evaluate dynamic method matcher here: static part will already have
|
||||
// been evaluated and found to match.
|
||||
InterceptorAndDynamicMethodMatcher dm =
|
||||
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
|
||||
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
|
||||
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
|
||||
return dm.interceptor.invoke(this);
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -58,10 +58,9 @@ public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Se
|
||||
if (adviceObject instanceof Advisor) {
|
||||
return (Advisor) adviceObject;
|
||||
}
|
||||
if (!(adviceObject instanceof Advice)) {
|
||||
if (!(adviceObject instanceof Advice advice)) {
|
||||
throw new UnknownAdviceTypeException(adviceObject);
|
||||
}
|
||||
Advice advice = (Advice) adviceObject;
|
||||
if (advice instanceof MethodInterceptor) {
|
||||
// So well-known it doesn't even need an adapter.
|
||||
return new DefaultPointcutAdvisor(advice);
|
||||
|
||||
+1
-2
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Auto proxy creator that identifies beans to proxy via a list of names.
|
||||
@@ -69,7 +68,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
|
||||
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
|
||||
this.beanNames = new ArrayList<>(beanNames.length);
|
||||
for (String mappedName : beanNames) {
|
||||
this.beanNames.add(StringUtils.trimWhitespace(mappedName));
|
||||
this.beanNames.add(mappedName.strip());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-4
@@ -34,6 +34,8 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.EmbeddedValueResolver;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
@@ -156,7 +158,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Determine the specific executor to use when executing the given method.
|
||||
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
|
||||
* <p>Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
|
||||
* @return the executor to use (or {@code null}, but just if no default executor is available)
|
||||
*/
|
||||
@Nullable
|
||||
@@ -184,7 +186,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
/**
|
||||
* Return the qualifier or bean name of the executor to be used when executing the
|
||||
* given async method, typically specified in the form of an annotation attribute.
|
||||
* Returning an empty string or {@code null} indicates that no specific executor has
|
||||
* <p>Returning an empty string or {@code null} indicates that no specific executor has
|
||||
* been specified and that the {@linkplain #setExecutor(Executor) default executor}
|
||||
* should be used.
|
||||
* @param method the method to inspect for executor qualifier metadata
|
||||
@@ -208,12 +210,16 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
}
|
||||
if (beanFactory instanceof ConfigurableBeanFactory configurableBeanFactory) {
|
||||
EmbeddedValueResolver embeddedValueResolver = new EmbeddedValueResolver(configurableBeanFactory);
|
||||
qualifier = embeddedValueResolver.resolveStringValue(qualifier);
|
||||
}
|
||||
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve or build a default executor for this advice instance.
|
||||
* An executor returned from here will be cached for further use.
|
||||
* <p>An executor returned from here will be cached for further use.
|
||||
* <p>The default implementation searches for a unique {@link TaskExecutor} bean
|
||||
* in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
|
||||
* If neither of the two is resolvable, this implementation will return {@code null}.
|
||||
@@ -288,10 +294,14 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
else if (Future.class.isAssignableFrom(returnType)) {
|
||||
return executor.submit(task);
|
||||
}
|
||||
else {
|
||||
else if (void.class == returnType) {
|
||||
executor.submit(task);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid return type for async method (only Future and void supported): " + returnType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,7 +47,7 @@ import org.springframework.util.ClassUtils;
|
||||
* target method needs to implement the same signature, it will have to return
|
||||
* a temporary Future handle that just passes the return value through
|
||||
* (like Spring's {@link org.springframework.scheduling.annotation.AsyncResult}
|
||||
* or EJB 3.1's {@code javax.ejb.AsyncResult}).
|
||||
* or EJB's {@code jakarta.ejb.AsyncResult}).
|
||||
*
|
||||
* <p>When the return type is {@code java.util.concurrent.Future}, any exception thrown
|
||||
* during the execution can be accessed and managed by the caller. With {@code void}
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -299,7 +299,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
Object target = methodInvocation.getThis();
|
||||
Assert.state(target != null, "Target must not be null");
|
||||
|
||||
StringBuffer output = new StringBuffer();
|
||||
StringBuilder output = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
String match = matcher.group();
|
||||
if (PLACEHOLDER_METHOD_NAME.equals(match)) {
|
||||
@@ -341,15 +341,15 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
|
||||
/**
|
||||
* Adds the {@code String} representation of the method return value
|
||||
* to the supplied {@code StringBuffer}. Correctly handles
|
||||
* to the supplied {@code StringBuilder}. Correctly handles
|
||||
* {@code null} and {@code void} results.
|
||||
* @param methodInvocation the {@code MethodInvocation} that returned the value
|
||||
* @param matcher the {@code Matcher} containing the matched placeholder
|
||||
* @param output the {@code StringBuffer} to write output to
|
||||
* @param output the {@code StringBuilder} to write output to
|
||||
* @param returnValue the value returned by the method invocation.
|
||||
*/
|
||||
private void appendReturnValue(
|
||||
MethodInvocation methodInvocation, Matcher matcher, StringBuffer output, @Nullable Object returnValue) {
|
||||
MethodInvocation methodInvocation, Matcher matcher, StringBuilder output, @Nullable Object returnValue) {
|
||||
|
||||
if (methodInvocation.getMethod().getReturnType() == void.class) {
|
||||
matcher.appendReplacement(output, "void");
|
||||
@@ -370,9 +370,9 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
* @param methodInvocation the {@code MethodInvocation} being logged.
|
||||
* Arguments will be retrieved from the corresponding {@code Method}.
|
||||
* @param matcher the {@code Matcher} containing the state of the output
|
||||
* @param output the {@code StringBuffer} containing the output
|
||||
* @param output the {@code StringBuilder} containing the output
|
||||
*/
|
||||
private void appendArgumentTypes(MethodInvocation methodInvocation, Matcher matcher, StringBuffer output) {
|
||||
private void appendArgumentTypes(MethodInvocation methodInvocation, Matcher matcher, StringBuilder output) {
|
||||
Class<?>[] argumentTypes = methodInvocation.getMethod().getParameterTypes();
|
||||
String[] argumentTypeShortNames = new String[argumentTypes.length];
|
||||
for (int i = 0; i < argumentTypeShortNames.length; i++) {
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -68,10 +68,9 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
* @throws IllegalStateException if the bean name has not been exposed
|
||||
*/
|
||||
public static String getBeanName(MethodInvocation mi) throws IllegalStateException {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
if (!(mi instanceof ProxyMethodInvocation pmi)) {
|
||||
throw new IllegalArgumentException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
String beanName = (String) pmi.getUserAttribute(BEAN_NAME_ATTRIBUTE);
|
||||
if (beanName == null) {
|
||||
throw new IllegalStateException("Cannot get bean name; not set on MethodInvocation: " + mi);
|
||||
@@ -113,10 +112,9 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
if (!(mi instanceof ProxyMethodInvocation pmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
|
||||
return mi.proceed();
|
||||
}
|
||||
@@ -138,10 +136,9 @@ public abstract class ExposeBeanNameAdvisors {
|
||||
@Override
|
||||
@Nullable
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
if (!(mi instanceof ProxyMethodInvocation pmi)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
}
|
||||
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
|
||||
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
|
||||
return super.invoke(mi);
|
||||
}
|
||||
|
||||
-144
@@ -1,144 +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
|
||||
*
|
||||
* https://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.aop.interceptor;
|
||||
|
||||
import com.jamonapi.MonKey;
|
||||
import com.jamonapi.MonKeyImp;
|
||||
import com.jamonapi.Monitor;
|
||||
import com.jamonapi.MonitorFactory;
|
||||
import com.jamonapi.utils.Misc;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
/**
|
||||
* Performance monitor interceptor that uses <b>JAMon</b> library to perform the
|
||||
* performance measurement on the intercepted method and output the stats.
|
||||
* In addition, it tracks/counts exceptions thrown by the intercepted method.
|
||||
* The stack traces can be viewed in the JAMon web application.
|
||||
*
|
||||
* <p>This code is inspired by Thierry Templier's blog.
|
||||
*
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Steve Souza
|
||||
* @since 1.1.3
|
||||
* @see com.jamonapi.MonitorFactory
|
||||
* @see PerformanceMonitorInterceptor
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class JamonPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
|
||||
|
||||
private boolean trackAllInvocations = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new JamonPerformanceMonitorInterceptor with a static logger.
|
||||
*/
|
||||
public JamonPerformanceMonitorInterceptor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JamonPerformanceMonitorInterceptor with a dynamic or static logger,
|
||||
* according to the given flag.
|
||||
* @param useDynamicLogger whether to use a dynamic logger or a static logger
|
||||
* @see #setUseDynamicLogger
|
||||
*/
|
||||
public JamonPerformanceMonitorInterceptor(boolean useDynamicLogger) {
|
||||
setUseDynamicLogger(useDynamicLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JamonPerformanceMonitorInterceptor with a dynamic or static logger,
|
||||
* according to the given flag.
|
||||
* @param useDynamicLogger whether to use a dynamic logger or a static logger
|
||||
* @param trackAllInvocations whether to track all invocations that go through
|
||||
* this interceptor, or just invocations with trace logging enabled
|
||||
* @see #setUseDynamicLogger
|
||||
*/
|
||||
public JamonPerformanceMonitorInterceptor(boolean useDynamicLogger, boolean trackAllInvocations) {
|
||||
setUseDynamicLogger(useDynamicLogger);
|
||||
setTrackAllInvocations(trackAllInvocations);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to track all invocations that go through this interceptor,
|
||||
* or just invocations with trace logging enabled.
|
||||
* <p>Default is "false": Only invocations with trace logging enabled will
|
||||
* be monitored. Specify "true" to let JAMon track all invocations,
|
||||
* gathering statistics even when trace logging is disabled.
|
||||
*/
|
||||
public void setTrackAllInvocations(boolean trackAllInvocations) {
|
||||
this.trackAllInvocations = trackAllInvocations;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Always applies the interceptor if the "trackAllInvocations" flag has been set;
|
||||
* else just kicks in if the log is enabled.
|
||||
* @see #setTrackAllInvocations
|
||||
* @see #isLogEnabled
|
||||
*/
|
||||
@Override
|
||||
protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
|
||||
return (this.trackAllInvocations || isLogEnabled(logger));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the invocation with a JAMon Monitor and writes the current
|
||||
* performance statistics to the log (if enabled).
|
||||
* @see com.jamonapi.MonitorFactory#start
|
||||
* @see com.jamonapi.Monitor#stop
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
|
||||
String name = createInvocationTraceName(invocation);
|
||||
MonKey key = new MonKeyImp(name, name, "ms.");
|
||||
|
||||
Monitor monitor = MonitorFactory.start(key);
|
||||
try {
|
||||
return invocation.proceed();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
trackException(key, ex);
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
monitor.stop();
|
||||
if (!this.trackAllInvocations || isLogEnabled(logger)) {
|
||||
writeToLog(logger, "JAMon performance statistics for method [" + name + "]:\n" + monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the thrown exception and put the stack trace in the details portion of the key.
|
||||
* This will allow the stack trace to be viewed in the JAMon web application.
|
||||
*/
|
||||
protected void trackException(MonKey key, Throwable ex) {
|
||||
String stackTrace = "stackTrace=" + Misc.getExceptionTrace(ex);
|
||||
key.setDetails(stackTrace);
|
||||
|
||||
// Specific exception counter. Example: java.lang.RuntimeException
|
||||
MonitorFactory.add(new MonKeyImp(ex.getClass().getName(), stackTrace, "Exception"), 1);
|
||||
|
||||
// General exception counter which is a total for all exceptions thrown
|
||||
MonitorFactory.add(new MonKeyImp(MonitorFactory.EXCEPTIONS_LABEL, stackTrace, "Exception"), 1);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 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.util.StopWatch;
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Rob Harrop
|
||||
* @see org.springframework.util.StopWatch
|
||||
* @see JamonPerformanceMonitorInterceptor
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -85,11 +85,9 @@ public class ScopedProxyFactoryBean extends ProxyConfig
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (!(beanFactory instanceof ConfigurableBeanFactory)) {
|
||||
if (!(beanFactory instanceof ConfigurableBeanFactory cbf)) {
|
||||
throw new IllegalStateException("Not running in a ConfigurableBeanFactory: " + beanFactory);
|
||||
}
|
||||
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
|
||||
|
||||
this.scopedTargetSource.setBeanFactory(beanFactory);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -69,10 +69,9 @@ public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordere
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof PointcutAdvisor)) {
|
||||
if (!(other instanceof PointcutAdvisor otherAdvisor)) {
|
||||
return false;
|
||||
}
|
||||
PointcutAdvisor otherAdvisor = (PointcutAdvisor) other;
|
||||
return (ObjectUtils.nullSafeEquals(getAdvice(), otherAdvisor.getAdvice()) &&
|
||||
ObjectUtils.nullSafeEquals(getPointcut(), otherAdvisor.getPointcut()));
|
||||
}
|
||||
|
||||
+4
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base regular expression pointcut bean. JavaBean properties are:
|
||||
@@ -81,7 +80,7 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
|
||||
Assert.notEmpty(patterns, "'patterns' must not be empty");
|
||||
this.patterns = new String[patterns.length];
|
||||
for (int i = 0; i < patterns.length; i++) {
|
||||
this.patterns[i] = StringUtils.trimWhitespace(patterns[i]);
|
||||
this.patterns[i] = patterns[i].strip();
|
||||
}
|
||||
initPatternRepresentation(this.patterns);
|
||||
}
|
||||
@@ -111,7 +110,7 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
|
||||
Assert.notEmpty(excludedPatterns, "'excludedPatterns' must not be empty");
|
||||
this.excludedPatterns = new String[excludedPatterns.length];
|
||||
for (int i = 0; i < excludedPatterns.length; i++) {
|
||||
this.excludedPatterns[i] = StringUtils.trimWhitespace(excludedPatterns[i]);
|
||||
this.excludedPatterns[i] = excludedPatterns[i].strip();
|
||||
}
|
||||
initExcludedPatternRepresentation(this.excludedPatterns);
|
||||
}
|
||||
@@ -200,10 +199,9 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AbstractRegexpMethodPointcut)) {
|
||||
if (!(other instanceof AbstractRegexpMethodPointcut otherPointcut)) {
|
||||
return false;
|
||||
}
|
||||
AbstractRegexpMethodPointcut otherPointcut = (AbstractRegexpMethodPointcut) other;
|
||||
return (Arrays.equals(this.patterns, otherPointcut.patterns) &&
|
||||
Arrays.equals(this.excludedPatterns, otherPointcut.excludedPatterns));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -284,8 +284,7 @@ public abstract class AopUtils {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
|
||||
}
|
||||
else if (advisor instanceof PointcutAdvisor) {
|
||||
PointcutAdvisor pca = (PointcutAdvisor) advisor;
|
||||
else if (advisor instanceof PointcutAdvisor pca) {
|
||||
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -188,10 +188,9 @@ public class ComposablePointcut implements Pointcut, Serializable {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ComposablePointcut)) {
|
||||
if (!(other instanceof ComposablePointcut otherPointcut)) {
|
||||
return false;
|
||||
}
|
||||
ComposablePointcut otherPointcut = (ComposablePointcut) other;
|
||||
return (this.classFilter.equals(otherPointcut.classFilter) &&
|
||||
this.methodMatcher.equals(otherPointcut.methodMatcher));
|
||||
}
|
||||
|
||||
@@ -128,10 +128,9 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ControlFlowPointcut)) {
|
||||
if (!(other instanceof ControlFlowPointcut that)) {
|
||||
return false;
|
||||
}
|
||||
ControlFlowPointcut that = (ControlFlowPointcut) other;
|
||||
return (this.clazz.equals(that.clazz)) && ObjectUtils.nullSafeEquals(this.methodName, that.methodName);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -155,10 +155,9 @@ public class DefaultIntroductionAdvisor implements IntroductionAdvisor, ClassFil
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof DefaultIntroductionAdvisor)) {
|
||||
if (!(other instanceof DefaultIntroductionAdvisor otherAdvisor)) {
|
||||
return false;
|
||||
}
|
||||
DefaultIntroductionAdvisor otherAdvisor = (DefaultIntroductionAdvisor) other;
|
||||
return (this.advice.equals(otherAdvisor.advice) && this.interfaces.equals(otherAdvisor.interfaces));
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -61,9 +61,9 @@ public class DelegatePerTargetObjectIntroductionInterceptor extends Introduction
|
||||
*/
|
||||
private final Map<Object, Object> delegateMap = new WeakHashMap<>();
|
||||
|
||||
private Class<?> defaultImplType;
|
||||
private final Class<?> defaultImplType;
|
||||
|
||||
private Class<?> interfaceType;
|
||||
private final Class<?> interfaceType;
|
||||
|
||||
|
||||
public DelegatePerTargetObjectIntroductionInterceptor(Class<?> defaultImplType, Class<?> interfaceType) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -146,10 +146,9 @@ public abstract class MethodMatchers {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof UnionMethodMatcher)) {
|
||||
if (!(other instanceof UnionMethodMatcher that)) {
|
||||
return false;
|
||||
}
|
||||
UnionMethodMatcher that = (UnionMethodMatcher) other;
|
||||
return (this.mm1.equals(that.mm1) && this.mm2.equals(that.mm2));
|
||||
}
|
||||
|
||||
@@ -223,8 +222,7 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
ClassFilter otherCf1 = ClassFilter.TRUE;
|
||||
ClassFilter otherCf2 = ClassFilter.TRUE;
|
||||
if (other instanceof ClassFilterAwareUnionMethodMatcher) {
|
||||
ClassFilterAwareUnionMethodMatcher cfa = (ClassFilterAwareUnionMethodMatcher) other;
|
||||
if (other instanceof ClassFilterAwareUnionMethodMatcher cfa) {
|
||||
otherCf1 = cfa.cf1;
|
||||
otherCf2 = cfa.cf2;
|
||||
}
|
||||
@@ -312,10 +310,9 @@ public abstract class MethodMatchers {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof IntersectionMethodMatcher)) {
|
||||
if (!(other instanceof IntersectionMethodMatcher that)) {
|
||||
return false;
|
||||
}
|
||||
IntersectionMethodMatcher that = (IntersectionMethodMatcher) other;
|
||||
return (this.mm1.equals(that.mm1) && this.mm2.equals(that.mm2));
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -72,10 +72,9 @@ public class AnnotationClassFilter implements ClassFilter {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AnnotationClassFilter)) {
|
||||
if (!(other instanceof AnnotationClassFilter otherCf)) {
|
||||
return false;
|
||||
}
|
||||
AnnotationClassFilter otherCf = (AnnotationClassFilter) other;
|
||||
return (this.annotationType.equals(otherCf.annotationType) && this.checkInherited == otherCf.checkInherited);
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -125,10 +125,9 @@ public class AnnotationMatchingPointcut implements Pointcut {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AnnotationMatchingPointcut)) {
|
||||
if (!(other instanceof AnnotationMatchingPointcut otherPointcut)) {
|
||||
return false;
|
||||
}
|
||||
AnnotationMatchingPointcut otherPointcut = (AnnotationMatchingPointcut) other;
|
||||
return (this.classFilter.equals(otherPointcut.classFilter) &&
|
||||
this.methodMatcher.equals(otherPointcut.methodMatcher));
|
||||
}
|
||||
@@ -189,10 +188,9 @@ public class AnnotationMatchingPointcut implements Pointcut {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof AnnotationCandidateClassFilter)) {
|
||||
if (!(obj instanceof AnnotationCandidateClassFilter that)) {
|
||||
return false;
|
||||
}
|
||||
AnnotationCandidateClassFilter that = (AnnotationCandidateClassFilter) obj;
|
||||
return this.annotationType.equals(that.annotationType);
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -92,10 +92,9 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AnnotationMethodMatcher)) {
|
||||
if (!(other instanceof AnnotationMethodMatcher otherMm)) {
|
||||
return false;
|
||||
}
|
||||
AnnotationMethodMatcher otherMm = (AnnotationMethodMatcher) other;
|
||||
return (this.annotationType.equals(otherMm.annotationType) && this.checkInherited == otherMm.checkInherited);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -135,10 +135,9 @@ public final class EmptyTargetSource implements TargetSource, Serializable {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof EmptyTargetSource)) {
|
||||
if (!(other instanceof EmptyTargetSource otherTs)) {
|
||||
return false;
|
||||
}
|
||||
EmptyTargetSource otherTs = (EmptyTargetSource) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.targetClass, otherTs.targetClass) && this.isStatic == otherTs.isStatic);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -85,10 +85,9 @@ public class SingletonTargetSource implements TargetSource, Serializable {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof SingletonTargetSource)) {
|
||||
if (!(other instanceof SingletonTargetSource otherTargetSource)) {
|
||||
return false;
|
||||
}
|
||||
SingletonTargetSource otherTargetSource = (SingletonTargetSource) other;
|
||||
return this.target.equals(otherTargetSource.target);
|
||||
}
|
||||
|
||||
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.aop.interceptor;
|
||||
|
||||
import com.jamonapi.MonitorFactory;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Steve Souza
|
||||
* @since 4.1
|
||||
*/
|
||||
public class JamonPerformanceMonitorInterceptorTests {
|
||||
|
||||
private final JamonPerformanceMonitorInterceptor interceptor = new JamonPerformanceMonitorInterceptor();
|
||||
|
||||
private final MethodInvocation mi = mock(MethodInvocation.class);
|
||||
|
||||
private final Log log = mock(Log.class);
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
MonitorFactory.reset();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithNormalProcessing() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
|
||||
interceptor.invokeUnderTrace(mi, log);
|
||||
|
||||
assertThat(MonitorFactory.getNumRows() > 0).as("jamon must track the method being invoked").isTrue();
|
||||
assertThat(MonitorFactory.getReport().contains("toString")).as("The jamon report must contain the toString method that was invoked").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeUnderTraceWithExceptionTracking() throws Throwable {
|
||||
given(mi.getMethod()).willReturn(String.class.getMethod("toString"));
|
||||
given(mi.proceed()).willThrow(new IllegalArgumentException());
|
||||
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
interceptor.invokeUnderTrace(mi, log));
|
||||
|
||||
assertThat(MonitorFactory.getNumRows()).as("Monitors must exist for the method invocation and 2 exceptions").isEqualTo(3);
|
||||
assertThat(MonitorFactory.getReport().contains("toString")).as("The jamon report must contain the toString method that was invoked").isTrue();
|
||||
assertThat(MonitorFactory.getReport().contains(MonitorFactory.EXCEPTIONS_LABEL)).as("The jamon report must contain the generic exception: " + MonitorFactory.EXCEPTIONS_LABEL).isTrue();
|
||||
assertThat(MonitorFactory.getReport().contains("IllegalArgumentException")).as("The jamon report must contain the specific exception: IllegalArgumentException'").isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,14 @@ sourceSets.main.java.srcDirs = files()
|
||||
sourceSets.test.aspectj.srcDir "src/test/java"
|
||||
sourceSets.test.java.srcDirs = files()
|
||||
|
||||
aspectj.version = dependencyManagement.managedVersions['org.aspectj:aspectjweaver']
|
||||
compileAspectj {
|
||||
sourceCompatibility "17"
|
||||
targetCompatibility "17"
|
||||
}
|
||||
compileTestAspectj {
|
||||
sourceCompatibility "17"
|
||||
targetCompatibility "17"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.aspectj:aspectjweaver")
|
||||
@@ -20,14 +27,14 @@ dependencies {
|
||||
optional(project(":spring-orm")) // for JPA exception translation support
|
||||
optional(project(":spring-tx")) // for JPA, @Transactional support
|
||||
optional("javax.cache:cache-api") // for JCache aspect
|
||||
optional("javax.transaction:javax.transaction-api") // for @javax.transaction.Transactional support
|
||||
optional("jakarta.transaction:jakarta.transaction-api") // for @jakarta.transaction.Transactional support
|
||||
testImplementation(project(":spring-core")) // for CodeStyleAspect
|
||||
testImplementation(project(":spring-test"))
|
||||
testImplementation(testFixtures(project(":spring-context")))
|
||||
testImplementation(testFixtures(project(":spring-context-support")))
|
||||
testImplementation(testFixtures(project(":spring-core")))
|
||||
testImplementation(testFixtures(project(":spring-tx")))
|
||||
testImplementation("javax.mail:javax.mail-api")
|
||||
testImplementation("jakarta.mail:jakarta.mail-api")
|
||||
testCompileOnly("org.aspectj:aspectjrt")
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
/**
|
||||
* {@code @Configuration} class that registers the Spring infrastructure beans necessary
|
||||
* to enable AspectJ-based annotation-driven transaction management for the JTA 1.2
|
||||
* {@link javax.transaction.Transactional} annotation in addition to Spring's own
|
||||
* {@link jakarta.transaction.Transactional} annotation in addition to Spring's own
|
||||
* {@link org.springframework.transaction.annotation.Transactional} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+4
-4
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import org.aspectj.lang.annotation.RequiredTypes;
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute
|
||||
|
||||
/**
|
||||
* Concrete AspectJ transaction aspect using the JTA 1.2
|
||||
* {@link javax.transaction.Transactional} annotation.
|
||||
* {@link jakarta.transaction.Transactional} annotation.
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
||||
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
||||
@@ -42,10 +42,10 @@ import org.springframework.transaction.annotation.AnnotationTransactionAttribute
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.2
|
||||
* @see javax.transaction.Transactional
|
||||
* @see jakarta.transaction.Transactional
|
||||
* @see AnnotationTransactionAspect
|
||||
*/
|
||||
@RequiredTypes("javax.transaction.Transactional")
|
||||
@RequiredTypes("jakarta.transaction.Transactional")
|
||||
public aspect JtaAnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||
|
||||
public JtaAnnotationTransactionAspect() {
|
||||
|
||||
+5
-5
@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||
import org.springframework.cache.interceptor.CacheResolver;
|
||||
@@ -143,7 +143,7 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode = AdviceMode.ASPECTJ)
|
||||
static class EnableCachingConfig extends CachingConfigurerSupport {
|
||||
static class EnableCachingConfig implements CachingConfigurer {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
@@ -220,7 +220,7 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode = AdviceMode.ASPECTJ)
|
||||
static class MultiCacheManagerConfigurer extends CachingConfigurerSupport {
|
||||
static class MultiCacheManagerConfigurer implements CachingConfigurer {
|
||||
|
||||
@Bean
|
||||
public CacheManager cm1() {
|
||||
@@ -246,7 +246,7 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode = AdviceMode.ASPECTJ)
|
||||
static class EmptyConfigSupportConfig extends CachingConfigurerSupport {
|
||||
static class EmptyConfigSupportConfig implements CachingConfigurer {
|
||||
|
||||
@Bean
|
||||
public CacheManager cm() {
|
||||
@@ -258,7 +258,7 @@ public class AspectJEnableCachingIsolatedTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode = AdviceMode.ASPECTJ)
|
||||
static class FullCachingConfig extends CachingConfigurerSupport {
|
||||
static class FullCachingConfig implements CachingConfigurer {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
Vendored
+2
-2
@@ -17,7 +17,7 @@
|
||||
package org.springframework.cache.aspectj;
|
||||
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.CachingConfigurer;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.config.AnnotatedClassCacheableService;
|
||||
import org.springframework.cache.config.CacheableService;
|
||||
@@ -47,7 +47,7 @@ public class AspectJEnableCachingTests extends AbstractCacheAnnotationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCaching(mode = AdviceMode.ASPECTJ)
|
||||
static class EnableCachingConfig extends CachingConfigurerSupport {
|
||||
static class EnableCachingConfig implements CachingConfigurer {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
|
||||
+1
-2
@@ -18,8 +18,7 @@ package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
@@ -1,38 +1,17 @@
|
||||
description = "Spring Beans"
|
||||
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "kotlin"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-core"))
|
||||
optional("javax.inject:javax.inject")
|
||||
optional("jakarta.inject:jakarta.inject-api")
|
||||
optional("org.yaml:snakeyaml")
|
||||
optional("org.codehaus.groovy:groovy-xml")
|
||||
optional("org.apache.groovy:groovy-xml")
|
||||
optional("org.jetbrains.kotlin:kotlin-reflect")
|
||||
optional("org.jetbrains.kotlin:kotlin-stdlib")
|
||||
testImplementation(testFixtures(project(":spring-core")))
|
||||
testImplementation("javax.annotation:javax.annotation-api")
|
||||
testImplementation(project(":spring-core-test"))
|
||||
testImplementation("jakarta.annotation:jakarta.annotation-api")
|
||||
testFixturesApi("org.junit.jupiter:junit-jupiter-api")
|
||||
testFixturesImplementation("org.assertj:assertj-core")
|
||||
}
|
||||
|
||||
// This module does joint compilation for Java and Groovy code with the compileGroovy task.
|
||||
sourceSets {
|
||||
main.groovy.srcDirs += "src/main/java"
|
||||
main.java.srcDirs = []
|
||||
}
|
||||
|
||||
compileGroovy {
|
||||
options.compilerArgs += "-Werror"
|
||||
}
|
||||
|
||||
// This module also builds Kotlin code and the compileKotlin task naturally depends on
|
||||
// compileJava. We need to redefine dependencies to break task cycles.
|
||||
tasks.named('compileGroovy') {
|
||||
// Groovy only needs the declared dependencies (and not the result of Java compilation)
|
||||
classpath = sourceSets.main.compileClasspath
|
||||
}
|
||||
tasks.named('compileKotlin') {
|
||||
// Kotlin also depends on the result of Groovy compilation
|
||||
classpath += files(sourceSets.main.groovy.classesDirectory)
|
||||
}
|
||||
}
|
||||
+6
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -61,20 +61,15 @@ public class AbstractPropertyAccessorBenchmark {
|
||||
this.propertyAccessor = new BeanWrapperImpl(this.target);
|
||||
}
|
||||
switch (this.customEditor) {
|
||||
case "stringTrimmer":
|
||||
case "stringTrimmer" ->
|
||||
this.propertyAccessor.registerCustomEditor(String.class, new StringTrimmerEditor(false));
|
||||
break;
|
||||
case "numberOnPath":
|
||||
case "numberOnPath" ->
|
||||
this.propertyAccessor.registerCustomEditor(int.class, "array.somePath", new CustomNumberEditor(Integer.class, false));
|
||||
break;
|
||||
case "numberOnNestedPath":
|
||||
case "numberOnNestedPath" ->
|
||||
this.propertyAccessor.registerCustomEditor(int.class, "array[0].somePath", new CustomNumberEditor(Integer.class, false));
|
||||
break;
|
||||
case "numberOnType":
|
||||
case "numberOnType" ->
|
||||
this.propertyAccessor.registerCustomEditor(int.class, new CustomNumberEditor(Integer.class, false));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -98,4 +93,5 @@ public class AbstractPropertyAccessorBenchmark {
|
||||
this.array = array;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.beans.factory.groovy
|
||||
|
||||
import groovy.xml.StreamingMarkupBuilder
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate
|
||||
import org.w3c.dom.Element
|
||||
|
||||
/**
|
||||
* Used by GroovyBeanDefinitionReader to read a Spring XML namespace expression
|
||||
* in the Groovy DSL.
|
||||
*
|
||||
* @author Jeff Brown
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
*/
|
||||
@groovy.transform.PackageScope
|
||||
class GroovyDynamicElementReader extends GroovyObjectSupport {
|
||||
|
||||
private final String rootNamespace
|
||||
|
||||
private final Map<String, String> xmlNamespaces
|
||||
|
||||
private final BeanDefinitionParserDelegate delegate
|
||||
|
||||
private final GroovyBeanDefinitionWrapper beanDefinition
|
||||
|
||||
protected final boolean decorating;
|
||||
|
||||
private boolean callAfterInvocation = true
|
||||
|
||||
|
||||
public GroovyDynamicElementReader(String namespace, Map<String, String> namespaceMap,
|
||||
BeanDefinitionParserDelegate delegate, GroovyBeanDefinitionWrapper beanDefinition, boolean decorating) {
|
||||
super();
|
||||
this.rootNamespace = namespace
|
||||
this.xmlNamespaces = namespaceMap
|
||||
this.delegate = delegate
|
||||
this.beanDefinition = beanDefinition;
|
||||
this.decorating = decorating;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invokeMethod(String name, Object args) {
|
||||
if (name.equals("doCall")) {
|
||||
def callable = args[0]
|
||||
callable.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
callable.delegate = this
|
||||
def result = callable.call()
|
||||
|
||||
if (this.callAfterInvocation) {
|
||||
afterInvocation()
|
||||
this.callAfterInvocation = false
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
else {
|
||||
StreamingMarkupBuilder builder = new StreamingMarkupBuilder();
|
||||
def myNamespace = this.rootNamespace
|
||||
def myNamespaces = this.xmlNamespaces
|
||||
|
||||
def callable = {
|
||||
for (namespace in myNamespaces) {
|
||||
mkp.declareNamespace([(namespace.key):namespace.value])
|
||||
}
|
||||
if (args && (args[-1] instanceof Closure)) {
|
||||
args[-1].resolveStrategy = Closure.DELEGATE_FIRST
|
||||
args[-1].delegate = builder
|
||||
}
|
||||
delegate."$myNamespace"."$name"(*args)
|
||||
}
|
||||
|
||||
callable.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
callable.delegate = builder
|
||||
def writable = builder.bind(callable)
|
||||
def sw = new StringWriter()
|
||||
writable.writeTo(sw)
|
||||
|
||||
Element element = this.delegate.readerContext.readDocumentFromString(sw.toString()).documentElement
|
||||
this.delegate.initDefaults(element)
|
||||
if (this.decorating) {
|
||||
BeanDefinitionHolder holder = this.beanDefinition.beanDefinitionHolder;
|
||||
holder = this.delegate.decorateIfRequired(element, holder, null)
|
||||
this.beanDefinition.setBeanDefinitionHolder(holder)
|
||||
}
|
||||
else {
|
||||
def beanDefinition = this.delegate.parseCustomElement(element)
|
||||
if (beanDefinition) {
|
||||
this.beanDefinition.setBeanDefinition(beanDefinition)
|
||||
}
|
||||
}
|
||||
if (this.callAfterInvocation) {
|
||||
afterInvocation()
|
||||
this.callAfterInvocation = false
|
||||
}
|
||||
return element
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook that subclass or anonymous classes can overwrite to implement custom behavior
|
||||
* after invocation completes.
|
||||
*/
|
||||
protected void afterInvocation() {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -85,10 +85,9 @@ public class BeanMetadataAttribute implements BeanMetadataElement {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof BeanMetadataAttribute)) {
|
||||
if (!(other instanceof BeanMetadataAttribute otherMa)) {
|
||||
return false;
|
||||
}
|
||||
BeanMetadataAttribute otherMa = (BeanMetadataAttribute) other;
|
||||
return (this.name.equals(otherMa.name) &&
|
||||
ObjectUtils.nullSafeEquals(this.value, otherMa.value) &&
|
||||
ObjectUtils.nullSafeEquals(this.source, otherMa.source));
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.time.temporal.Temporal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -79,20 +78,15 @@ public abstract class BeanUtils {
|
||||
private static final Set<Class<?>> unknownEditorTypes =
|
||||
Collections.newSetFromMap(new ConcurrentReferenceHashMap<>(64));
|
||||
|
||||
private static final Map<Class<?>, Object> DEFAULT_TYPE_VALUES;
|
||||
|
||||
static {
|
||||
Map<Class<?>, Object> values = new HashMap<>();
|
||||
values.put(boolean.class, false);
|
||||
values.put(byte.class, (byte) 0);
|
||||
values.put(short.class, (short) 0);
|
||||
values.put(int.class, 0);
|
||||
values.put(long.class, 0L);
|
||||
values.put(float.class, 0F);
|
||||
values.put(double.class, 0D);
|
||||
values.put(char.class, '\0');
|
||||
DEFAULT_TYPE_VALUES = Collections.unmodifiableMap(values);
|
||||
}
|
||||
private static final Map<Class<?>, Object> DEFAULT_TYPE_VALUES = Map.of(
|
||||
boolean.class, false,
|
||||
byte.class, (byte) 0,
|
||||
short.class, (short) 0,
|
||||
int.class, 0,
|
||||
long.class, 0L,
|
||||
float.class, 0F,
|
||||
double.class, 0D,
|
||||
char.class, '\0');
|
||||
|
||||
|
||||
/**
|
||||
@@ -142,19 +136,20 @@ public abstract class BeanUtils {
|
||||
if (clazz.isInterface()) {
|
||||
throw new BeanInstantiationException(clazz, "Specified class is an interface");
|
||||
}
|
||||
Constructor<T> ctor;
|
||||
try {
|
||||
return instantiateClass(clazz.getDeclaredConstructor());
|
||||
ctor = clazz.getDeclaredConstructor();
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
Constructor<T> ctor = findPrimaryConstructor(clazz);
|
||||
if (ctor != null) {
|
||||
return instantiateClass(ctor);
|
||||
ctor = findPrimaryConstructor(clazz);
|
||||
if (ctor == null) {
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
catch (LinkageError err) {
|
||||
throw new BeanInstantiationException(clazz, "Unresolvable class definition", err);
|
||||
}
|
||||
return instantiateClass(ctor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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,11 +18,6 @@ package org.springframework.beans;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.Property;
|
||||
@@ -69,12 +64,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
@Nullable
|
||||
private CachedIntrospectionResults cachedIntrospectionResults;
|
||||
|
||||
/**
|
||||
* The security context used for invoking the property methods.
|
||||
*/
|
||||
@Nullable
|
||||
private AccessControlContext acc;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
|
||||
@@ -131,7 +120,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
*/
|
||||
private BeanWrapperImpl(Object object, String nestedPath, BeanWrapperImpl parent) {
|
||||
super(object, nestedPath, parent);
|
||||
setSecurityContext(parent.acc);
|
||||
}
|
||||
|
||||
|
||||
@@ -176,23 +164,6 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
return this.cachedIntrospectionResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
*/
|
||||
public void setSecurityContext(@Nullable AccessControlContext acc) {
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the security context used during the invocation of the wrapped instance methods.
|
||||
* Can be null.
|
||||
*/
|
||||
@Nullable
|
||||
public AccessControlContext getSecurityContext() {
|
||||
return this.acc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the given value for the specified property to the latter's type.
|
||||
@@ -290,23 +261,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
@Nullable
|
||||
public Object getValue() throws Exception {
|
||||
Method readMethod = this.pd.getReadMethod();
|
||||
if (System.getSecurityManager() != null) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
ReflectionUtils.makeAccessible(readMethod);
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
|
||||
() -> readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
|
||||
}
|
||||
catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReflectionUtils.makeAccessible(readMethod);
|
||||
return readMethod.invoke(getWrappedInstance(), (Object[]) null);
|
||||
}
|
||||
ReflectionUtils.makeAccessible(readMethod);
|
||||
return readMethod.invoke(getWrappedInstance(), (Object[]) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,23 +270,8 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
|
||||
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
|
||||
this.pd.getWriteMethod());
|
||||
if (System.getSecurityManager() != null) {
|
||||
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
||||
ReflectionUtils.makeAccessible(writeMethod);
|
||||
return null;
|
||||
});
|
||||
try {
|
||||
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
|
||||
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
|
||||
}
|
||||
catch (PrivilegedActionException ex) {
|
||||
throw ex.getException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReflectionUtils.makeAccessible(writeMethod);
|
||||
writeMethod.invoke(getWrappedInstance(), value);
|
||||
}
|
||||
ReflectionUtils.makeAccessible(writeMethod);
|
||||
writeMethod.invoke(getWrappedInstance(), value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -139,7 +139,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
// Sort non-void returning write methods to guard against the ill effects of
|
||||
// non-deterministic sorting of methods returned from Class#getDeclaredMethods
|
||||
// under JDK 7. See https://bugs.java.com/view_bug.do?bug_id=7023180
|
||||
matches.sort((m1, m2) -> m2.toString().compareTo(m1.toString()));
|
||||
matches.sort(Comparator.comparing(Method::toString).reversed());
|
||||
return matches;
|
||||
}
|
||||
|
||||
@@ -188,8 +188,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
for (PropertyDescriptor pd : this.propertyDescriptors) {
|
||||
final Class<?> candidateType;
|
||||
final String candidateName = pd.getName();
|
||||
if (pd instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
|
||||
if (pd instanceof IndexedPropertyDescriptor ipd) {
|
||||
candidateType = ipd.getIndexedPropertyType();
|
||||
if (candidateName.equals(propertyName) &&
|
||||
(candidateType.equals(propertyType) || candidateType.equals(propertyType.getComponentType()))) {
|
||||
@@ -494,10 +493,9 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof IndexedPropertyDescriptor)) {
|
||||
if (!(other instanceof IndexedPropertyDescriptor otherPd)) {
|
||||
return false;
|
||||
}
|
||||
IndexedPropertyDescriptor otherPd = (IndexedPropertyDescriptor) other;
|
||||
return (ObjectUtils.nullSafeEquals(getIndexedReadMethod(), otherPd.getIndexedReadMethod()) &&
|
||||
ObjectUtils.nullSafeEquals(getIndexedWriteMethod(), otherPd.getIndexedWriteMethod()) &&
|
||||
ObjectUtils.nullSafeEquals(getIndexedPropertyType(), otherPd.getIndexedPropertyType()) &&
|
||||
|
||||
+1
-2
@@ -168,10 +168,9 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof GenericTypeAwarePropertyDescriptor)) {
|
||||
if (!(other instanceof GenericTypeAwarePropertyDescriptor otherPd)) {
|
||||
return false;
|
||||
}
|
||||
GenericTypeAwarePropertyDescriptor otherPd = (GenericTypeAwarePropertyDescriptor) other;
|
||||
return (getBeanClass().equals(otherPd.getBeanClass()) && PropertyDescriptorUtils.equals(this, otherPd));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -221,8 +221,7 @@ public class MutablePropertyValues implements PropertyValues, Serializable {
|
||||
*/
|
||||
private PropertyValue mergeIfRequired(PropertyValue newPv, PropertyValue currentPv) {
|
||||
Object value = newPv.getValue();
|
||||
if (value instanceof Mergeable) {
|
||||
Mergeable mergeable = (Mergeable) value;
|
||||
if (value instanceof Mergeable mergeable) {
|
||||
if (mergeable.isMergeEnabled()) {
|
||||
Object merged = mergeable.merge(currentPv.getValue());
|
||||
return new PropertyValue(newPv.getName(), merged);
|
||||
|
||||
+3
-3
@@ -423,9 +423,6 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
if (editor == null) {
|
||||
// Find editor for superclass or interface.
|
||||
for (Map.Entry<Class<?>, PropertyEditor> entry : this.customEditors.entrySet()) {
|
||||
if (editor != null) {
|
||||
break;
|
||||
}
|
||||
Class<?> key = entry.getKey();
|
||||
if (key.isAssignableFrom(requiredType)) {
|
||||
editor = entry.getValue();
|
||||
@@ -435,6 +432,9 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
this.customEditorCache = new HashMap<>();
|
||||
}
|
||||
this.customEditorCache.put(requiredType, editor);
|
||||
if (editor != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -192,10 +192,9 @@ public class PropertyValue extends BeanMetadataAttributeAccessor implements Seri
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof PropertyValue)) {
|
||||
if (!(other instanceof PropertyValue otherPv)) {
|
||||
return false;
|
||||
}
|
||||
PropertyValue otherPv = (PropertyValue) other;
|
||||
return (this.name.equals(otherPv.name) &&
|
||||
ObjectUtils.nullSafeEquals(this.value, otherPv.value) &&
|
||||
ObjectUtils.nullSafeEquals(getSource(), otherPv.getSource()));
|
||||
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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
|
||||
*
|
||||
* https://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.beans.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations in JavaBeans style.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @deprecated as of 5.2, in favor of custom annotation attribute processing
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class AnnotationBeanUtils {
|
||||
|
||||
/**
|
||||
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
|
||||
* Any properties defined in {@code excludedProperties} will not be copied.
|
||||
* @param ann the annotation to copy from
|
||||
* @param bean the bean instance to copy to
|
||||
* @param excludedProperties the names of excluded properties, if any
|
||||
* @see org.springframework.beans.BeanWrapper
|
||||
*/
|
||||
public static void copyPropertiesToBean(Annotation ann, Object bean, String... excludedProperties) {
|
||||
copyPropertiesToBean(ann, bean, null, excludedProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
|
||||
* Any properties defined in {@code excludedProperties} will not be copied.
|
||||
* <p>A specified value resolver may resolve placeholders in property values, for example.
|
||||
* @param ann the annotation to copy from
|
||||
* @param bean the bean instance to copy to
|
||||
* @param valueResolver a resolve to post-process String property values (may be {@code null})
|
||||
* @param excludedProperties the names of excluded properties, if any
|
||||
* @see org.springframework.beans.BeanWrapper
|
||||
*/
|
||||
public static void copyPropertiesToBean(Annotation ann, Object bean, @Nullable StringValueResolver valueResolver,
|
||||
String... excludedProperties) {
|
||||
|
||||
Set<String> excluded = (excludedProperties.length == 0 ? Collections.emptySet() :
|
||||
new HashSet<>(Arrays.asList(excludedProperties)));
|
||||
Method[] annotationProperties = ann.annotationType().getDeclaredMethods();
|
||||
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean);
|
||||
for (Method annotationProperty : annotationProperties) {
|
||||
String propertyName = annotationProperty.getName();
|
||||
if (!excluded.contains(propertyName) && bw.isWritableProperty(propertyName)) {
|
||||
Object value = ReflectionUtils.invokeMethod(annotationProperty, ann);
|
||||
if (valueResolver != null && value instanceof String) {
|
||||
value = valueResolver.resolveStringValue((String) value);
|
||||
}
|
||||
bw.setPropertyValue(propertyName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -161,8 +161,7 @@ public abstract class BeanFactoryUtils {
|
||||
public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, ResolvableType type) {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForType(type);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
@@ -199,8 +198,7 @@ public abstract class BeanFactoryUtils {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
|
||||
@@ -226,8 +224,7 @@ public abstract class BeanFactoryUtils {
|
||||
public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type) {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForType(type);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
@@ -263,8 +260,7 @@ public abstract class BeanFactoryUtils {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
|
||||
@@ -289,8 +285,7 @@ public abstract class BeanFactoryUtils {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForAnnotation(annotationType);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForAnnotationIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), annotationType);
|
||||
@@ -327,8 +322,7 @@ public abstract class BeanFactoryUtils {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
Map<String, T> result = new LinkedHashMap<>(4);
|
||||
result.putAll(lbf.getBeansOfType(type));
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
Map<String, T> parentResult = beansOfTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
@@ -376,8 +370,7 @@ public abstract class BeanFactoryUtils {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
Map<String, T> result = new LinkedHashMap<>(4);
|
||||
result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (lbf instanceof HierarchicalBeanFactory hbf) {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
Map<String, T> parentResult = beansOfTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
|
||||
|
||||
+2
-2
@@ -70,8 +70,8 @@ public class AnnotatedGenericBeanDefinition extends GenericBeanDefinition implem
|
||||
*/
|
||||
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
|
||||
Assert.notNull(metadata, "AnnotationMetadata must not be null");
|
||||
if (metadata instanceof StandardAnnotationMetadata) {
|
||||
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
|
||||
if (metadata instanceof StandardAnnotationMetadata sam) {
|
||||
setBeanClass(sam.getIntrospectedClass());
|
||||
}
|
||||
else {
|
||||
setBeanClassName(metadata.getClassName());
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Marks a constructor, field, setter method, or config method as to be autowired by
|
||||
* Spring's dependency injection facilities. This is an alternative to the JSR-330
|
||||
* {@link javax.inject.Inject} annotation, adding required-vs-optional semantics.
|
||||
* {@link jakarta.inject.Inject} annotation, adding required-vs-optional semantics.
|
||||
*
|
||||
* <h3>Autowired Constructors</h3>
|
||||
* <p>Only one constructor of any given bean class may declare this annotation with the
|
||||
|
||||
+92
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2022 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,10 +22,12 @@ import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -37,6 +39,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.generator.CodeContribution;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
@@ -48,9 +52,13 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.AotContributingBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.generator.InjectionGenerator;
|
||||
import org.springframework.beans.factory.support.LookupOverride;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -65,6 +73,7 @@ import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -75,8 +84,10 @@ import org.springframework.util.StringUtils;
|
||||
* by default, Spring's {@link Autowired @Autowired} and {@link Value @Value}
|
||||
* annotations.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
|
||||
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
|
||||
* if available, as a direct alternative to Spring's own {@code @Autowired}.
|
||||
* Additionally, it retains support for the {@code javax.inject.Inject} variant
|
||||
* dating back to the original JSR-330 specification (as known from Java EE 6-8).
|
||||
*
|
||||
* <h3>Autowired Constructors</h3>
|
||||
* <p>Only one constructor of any given bean class may declare this annotation with
|
||||
@@ -129,7 +140,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see Value
|
||||
*/
|
||||
public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
|
||||
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
|
||||
MergedBeanDefinitionPostProcessor, AotContributingBeanPostProcessor, PriorityOrdered, BeanFactoryAware {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -154,20 +165,30 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
/**
|
||||
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
|
||||
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
|
||||
* if available.
|
||||
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
|
||||
* if available, as well as the original {@code javax.inject.Inject} variant.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public AutowiredAnnotationBeanPostProcessor() {
|
||||
this.autowiredAnnotationTypes.add(Autowired.class);
|
||||
this.autowiredAnnotationTypes.add(Value.class);
|
||||
|
||||
try {
|
||||
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
|
||||
ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
|
||||
logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// jakarta.inject API not available - simply skip.
|
||||
}
|
||||
|
||||
try {
|
||||
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
|
||||
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
|
||||
logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
|
||||
logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - simply skip.
|
||||
// javax.inject API not available - simply skip.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +198,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
* setter methods, and arbitrary config methods.
|
||||
* <p>The default autowired annotation types are the Spring-provided
|
||||
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
|
||||
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
|
||||
* as the common {@code @Inject} annotation, if available.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation type to indicate that a member is supposed
|
||||
* to be autowired.
|
||||
@@ -193,7 +214,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
* setter methods, and arbitrary config methods.
|
||||
* <p>The default autowired annotation types are the Spring-provided
|
||||
* {@link Autowired @Autowired} and {@link Value @Value} annotations as well
|
||||
* as JSR-330's {@link javax.inject.Inject @Inject} annotation, if available.
|
||||
* as the common {@code @Inject} annotation, if available.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation types to indicate that a member is supposed
|
||||
* to be autowired.
|
||||
@@ -243,8 +264,22 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
|
||||
@Override
|
||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
findInjectionMetadata(beanName, beanType, beanDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanInstantiationContribution contribute(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, beanDefinition);
|
||||
Collection<InjectedElement> injectedElements = metadata.getInjectedElements();
|
||||
return (!ObjectUtils.isEmpty(injectedElements)
|
||||
? new AutowiredAnnotationBeanInstantiationContribution(injectedElements)
|
||||
: null);
|
||||
}
|
||||
|
||||
private InjectionMetadata findInjectionMetadata(String beanName, Class<?> beanType, RootBeanDefinition beanDefinition) {
|
||||
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
|
||||
metadata.checkConfigMembers(beanDefinition);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -407,14 +442,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
return pvs;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
|
||||
|
||||
return postProcessProperties(pvs, bean, beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Native' processing method for direct calls with an arbitrary target instance,
|
||||
* resolving all of its fields and methods which are annotated with one of the
|
||||
@@ -537,10 +564,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
* @param ann the Autowired annotation
|
||||
* @return whether the annotation indicates that a dependency is required
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected boolean determineRequiredStatus(MergedAnnotation<?> ann) {
|
||||
return determineRequiredStatus(ann.<AnnotationAttributes> asMap(
|
||||
mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
|
||||
mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,8 +620,7 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
*/
|
||||
@Nullable
|
||||
private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
|
||||
if (cachedArgument instanceof DependencyDescriptor) {
|
||||
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
|
||||
if (cachedArgument instanceof DependencyDescriptor descriptor) {
|
||||
Assert.state(this.beanFactory != null, "No BeanFactory available");
|
||||
return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
|
||||
}
|
||||
@@ -796,6 +821,52 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AutowiredAnnotationBeanInstantiationContribution implements BeanInstantiationContribution {
|
||||
|
||||
private final Collection<InjectedElement> injectedElements;
|
||||
|
||||
private final InjectionGenerator generator;
|
||||
|
||||
AutowiredAnnotationBeanInstantiationContribution(Collection<InjectedElement> injectedElements) {
|
||||
this.injectedElements = injectedElements;
|
||||
this.generator = new InjectionGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(CodeContribution contribution) {
|
||||
this.injectedElements.forEach(element -> {
|
||||
boolean isRequired = isRequired(element);
|
||||
Member member = element.getMember();
|
||||
analyzeMember(contribution, member);
|
||||
contribution.statements().addStatement(this.generator.generateInjection(member, isRequired));
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isRequired(InjectedElement element) {
|
||||
if (element instanceof AutowiredMethodElement injectedMethod) {
|
||||
return injectedMethod.required;
|
||||
}
|
||||
else if (element instanceof AutowiredFieldElement injectedField) {
|
||||
return injectedField.required;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void analyzeMember(CodeContribution contribution, Member member) {
|
||||
if (member instanceof Method method) {
|
||||
contribution.runtimeHints().reflection().registerMethod(method,
|
||||
hint -> hint.setModes(ExecutableMode.INTROSPECT));
|
||||
contribution.protectedAccess().analyze(member,
|
||||
this.generator.getProtectedAccessInjectionOptions(member));
|
||||
}
|
||||
else if (member instanceof Field field) {
|
||||
contribution.runtimeHints().reflection().registerField(field);
|
||||
contribution.protectedAccess().analyze(member,
|
||||
this.generator.getProtectedAccessInjectionOptions(member));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* DependencyDescriptor variant with a pre-resolved target bean name.
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 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,7 +48,7 @@ import org.springframework.util.Assert;
|
||||
public abstract class BeanFactoryAnnotationUtils {
|
||||
|
||||
/**
|
||||
* Retrieve all bean of type {@code T} from the given {@code BeanFactory} declaring a
|
||||
* Retrieve all beans of type {@code T} from the given {@code BeanFactory} declaring a
|
||||
* qualifier (e.g. via {@code <qualifier>} or {@code @Qualifier}) matching the given
|
||||
* qualifier, or having a bean name matching the given qualifier.
|
||||
* @param beanFactory the factory to get the target beans from (also searching ancestors)
|
||||
@@ -90,9 +90,9 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
|
||||
if (beanFactory instanceof ListableBeanFactory) {
|
||||
if (beanFactory instanceof ListableBeanFactory lbf) {
|
||||
// Full qualifier matching supported.
|
||||
return qualifiedBeanOfType((ListableBeanFactory) beanFactory, beanType, qualifier);
|
||||
return qualifiedBeanOfType(lbf, beanType, qualifier);
|
||||
}
|
||||
else if (beanFactory.containsBean(qualifier)) {
|
||||
// Fallback: target bean at least found by bean name.
|
||||
@@ -163,11 +163,10 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
}
|
||||
try {
|
||||
Class<?> beanType = beanFactory.getType(beanName);
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
BeanDefinition bd = ((ConfigurableBeanFactory) beanFactory).getMergedBeanDefinition(beanName);
|
||||
if (beanFactory instanceof ConfigurableBeanFactory cbf) {
|
||||
BeanDefinition bd = cbf.getMergedBeanDefinition(beanName);
|
||||
// Explicit qualifier metadata on bean definition? (typically in XML definition)
|
||||
if (bd instanceof AbstractBeanDefinition) {
|
||||
AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
|
||||
if (bd instanceof AbstractBeanDefinition abd) {
|
||||
AutowireCandidateQualifier candidate = abd.getQualifier(Qualifier.class.getName());
|
||||
if (candidate != null) {
|
||||
Object value = candidate.getAttribute(AutowireCandidateQualifier.VALUE_KEY);
|
||||
@@ -177,8 +176,8 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
}
|
||||
}
|
||||
// Corresponding qualifier on factory method? (typically in configuration class)
|
||||
if (bd instanceof RootBeanDefinition) {
|
||||
Method factoryMethod = ((RootBeanDefinition) bd).getResolvedFactoryMethod();
|
||||
if (bd instanceof RootBeanDefinition rbd) {
|
||||
Method factoryMethod = rbd.getResolvedFactoryMethod();
|
||||
if (factoryMethod != null) {
|
||||
Qualifier targetAnnotation = AnnotationUtils.getAnnotation(factoryMethod, Qualifier.class);
|
||||
if (targetAnnotation != null) {
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,11 +91,10 @@ public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanC
|
||||
@SuppressWarnings("unchecked")
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (this.customQualifierTypes != null) {
|
||||
if (!(beanFactory instanceof DefaultListableBeanFactory)) {
|
||||
if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
|
||||
throw new IllegalStateException(
|
||||
"CustomAutowireConfigurer needs to operate on a DefaultListableBeanFactory");
|
||||
}
|
||||
DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
|
||||
if (!(dlbf.getAutowireCandidateResolver() instanceof QualifierAnnotationAutowireCandidateResolver)) {
|
||||
dlbf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
}
|
||||
@@ -106,8 +105,7 @@ public class CustomAutowireConfigurer implements BeanFactoryPostProcessor, BeanC
|
||||
if (value instanceof Class) {
|
||||
customType = (Class<? extends Annotation>) value;
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
String className = (String) value;
|
||||
else if (value instanceof String className) {
|
||||
customType = (Class<? extends Annotation>) ClassUtils.resolveClassName(className, this.beanClassLoader);
|
||||
}
|
||||
else {
|
||||
|
||||
+40
-8
@@ -32,6 +32,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -39,6 +40,8 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.AotContributingBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -46,6 +49,7 @@ import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -66,19 +70,20 @@ import org.springframework.util.ReflectionUtils;
|
||||
* init method and destroy method, respectively.
|
||||
*
|
||||
* <p>Spring's {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor}
|
||||
* supports the JSR-250 {@link javax.annotation.PostConstruct} and {@link javax.annotation.PreDestroy}
|
||||
* supports the {@link jakarta.annotation.PostConstruct} and {@link jakarta.annotation.PreDestroy}
|
||||
* annotations out of the box, as init annotation and destroy annotation, respectively.
|
||||
* Furthermore, it also supports the {@link javax.annotation.Resource} annotation
|
||||
* Furthermore, it also supports the {@link jakarta.annotation.Resource} annotation
|
||||
* for annotation-driven injection of named beans.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.5
|
||||
* @see #setInitAnnotationType
|
||||
* @see #setDestroyAnnotationType
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InitDestroyAnnotationBeanPostProcessor
|
||||
implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
|
||||
public class InitDestroyAnnotationBeanPostProcessor implements DestructionAwareBeanPostProcessor,
|
||||
MergedBeanDefinitionPostProcessor, AotContributingBeanPostProcessor, PriorityOrdered, Serializable {
|
||||
|
||||
private final transient LifecycleMetadata emptyLifecycleMetadata =
|
||||
new LifecycleMetadata(Object.class, Collections.emptyList(), Collections.emptyList()) {
|
||||
@@ -117,7 +122,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
* methods to call after configuration of a bean.
|
||||
* <p>Any custom annotation can be used, since there are no required
|
||||
* annotation attributes. There is no default, although a typical choice
|
||||
* is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
|
||||
* is the {@link jakarta.annotation.PostConstruct} annotation.
|
||||
*/
|
||||
public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
|
||||
this.initAnnotationType = initAnnotationType;
|
||||
@@ -128,7 +133,7 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
* methods to call when the context is shutting down.
|
||||
* <p>Any custom annotation can be used, since there are no required
|
||||
* annotation attributes. There is no default, although a typical choice
|
||||
* is the JSR-250 {@link javax.annotation.PreDestroy} annotation.
|
||||
* is the {@link jakarta.annotation.PreDestroy} annotation.
|
||||
*/
|
||||
public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
|
||||
this.destroyAnnotationType = destroyAnnotationType;
|
||||
@@ -146,8 +151,36 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
|
||||
@Override
|
||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
findInjectionMetadata(beanDefinition, beanType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanInstantiationContribution contribute(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
LifecycleMetadata metadata = findInjectionMetadata(beanDefinition, beanType);
|
||||
if (!CollectionUtils.isEmpty(metadata.initMethods)) {
|
||||
String[] initMethodNames = safeMerge(
|
||||
beanDefinition.getInitMethodNames(), metadata.initMethods);
|
||||
beanDefinition.setInitMethodNames(initMethodNames);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(metadata.destroyMethods)) {
|
||||
String[] destroyMethodNames = safeMerge(
|
||||
beanDefinition.getDestroyMethodNames(), metadata.destroyMethods);
|
||||
beanDefinition.setDestroyMethodNames(destroyMethodNames);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LifecycleMetadata findInjectionMetadata(RootBeanDefinition beanDefinition, Class<?> beanType) {
|
||||
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
|
||||
metadata.checkConfigMembers(beanDefinition);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private String[] safeMerge(@Nullable String[] existingNames, Collection<LifecycleElement> detectedElements) {
|
||||
Stream<String> detectedNames = detectedElements.stream().map(LifecycleElement::getIdentifier);
|
||||
Stream<String> mergedNames = (existingNames != null
|
||||
? Stream.concat(Stream.of(existingNames), detectedNames) : detectedNames);
|
||||
return mergedNames.distinct().toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,10 +427,9 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof LifecycleElement)) {
|
||||
if (!(other instanceof LifecycleElement otherElement)) {
|
||||
return false;
|
||||
}
|
||||
LifecycleElement otherElement = (LifecycleElement) other;
|
||||
return (this.identifier.equals(otherElement.identifier));
|
||||
}
|
||||
|
||||
|
||||
+10
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -88,6 +88,14 @@ public class InjectionMetadata {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the {@link InjectedElement elements} to inject.
|
||||
* @return the elements to inject
|
||||
*/
|
||||
public Collection<InjectedElement> getInjectedElements() {
|
||||
return Collections.unmodifiableCollection(this.injectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this metadata instance needs to be refreshed.
|
||||
* @param clazz the current target class
|
||||
@@ -304,10 +312,9 @@ public class InjectionMetadata {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof InjectedElement)) {
|
||||
if (!(other instanceof InjectedElement otherElement)) {
|
||||
return false;
|
||||
}
|
||||
InjectedElement otherElement = (InjectedElement) other;
|
||||
return this.member.equals(otherElement.member);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -140,6 +140,8 @@ public final class ParameterResolutionDelegate {
|
||||
* Due to a bug in {@code javac} on JDK versions prior to JDK 9, looking up
|
||||
* annotations directly on a {@link Parameter} will fail for inner class
|
||||
* constructors.
|
||||
* <p>Note: Since Spring 6 may still encounter user code compiled with
|
||||
* {@code javac 8}, this workaround is kept in place for the time being.
|
||||
* <h4>Bug in javac in JDK < 9</h4>
|
||||
* <p>The parameter annotations array in the compiled byte code excludes an entry
|
||||
* for the implicit <em>enclosing instance</em> parameter for an inner class
|
||||
|
||||
+3
-3
@@ -46,7 +46,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* against {@link Qualifier qualifier annotations} on the field or parameter to be autowired.
|
||||
* Also supports suggested expression values through a {@link Value value} annotation.
|
||||
*
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
|
||||
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation, if available.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
@@ -66,13 +66,13 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
/**
|
||||
* Create a new QualifierAnnotationAutowireCandidateResolver
|
||||
* for Spring's standard {@link Qualifier} annotation.
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Qualifier} annotation, if available.
|
||||
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation, if available.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public QualifierAnnotationAutowireCandidateResolver() {
|
||||
this.qualifierTypes.add(Qualifier.class);
|
||||
try {
|
||||
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
|
||||
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Qualifier",
|
||||
QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.beans.factory.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a method (typically a JavaBean setter method) as being 'required': that is,
|
||||
* the setter method must be configured to be dependency-injected with a value.
|
||||
*
|
||||
* <p>Please do consult the javadoc for the {@link RequiredAnnotationBeanPostProcessor}
|
||||
* class (which, by default, checks for the presence of this annotation).
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
* @see RequiredAnnotationBeanPostProcessor
|
||||
* @deprecated as of 5.1, in favor of using constructor injection for required settings
|
||||
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Required {
|
||||
|
||||
}
|
||||
-230
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2021 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
|
||||
*
|
||||
* https://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.beans.factory.annotation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
* that enforces required JavaBean properties to have been configured.
|
||||
* Required bean properties are detected through a Java 5 annotation:
|
||||
* by default, Spring's {@link Required} annotation.
|
||||
*
|
||||
* <p>The motivation for the existence of this BeanPostProcessor is to allow
|
||||
* developers to annotate the setter properties of their own classes with an
|
||||
* arbitrary JDK 1.5 annotation to indicate that the container must check
|
||||
* for the configuration of a dependency injected value. This neatly pushes
|
||||
* responsibility for such checking onto the container (where it arguably belongs),
|
||||
* and obviates the need (<b>in part</b>) for a developer to code a method that
|
||||
* simply checks that all required properties have actually been set.
|
||||
*
|
||||
* <p>Please note that an 'init' method may still need to be implemented (and may
|
||||
* still be desirable), because all that this class does is enforcing that a
|
||||
* 'required' property has actually been configured with a value. It does
|
||||
* <b>not</b> check anything else... In particular, it does not check that a
|
||||
* configured value is not {@code null}.
|
||||
*
|
||||
* <p>Note: A default RequiredAnnotationBeanPostProcessor will be registered
|
||||
* by the "context:annotation-config" and "context:component-scan" XML tags.
|
||||
* Remove or turn off the default annotation configuration there if you intend
|
||||
* to specify a custom RequiredAnnotationBeanPostProcessor bean definition.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #setRequiredAnnotationType
|
||||
* @see Required
|
||||
* @deprecated as of 5.1, in favor of using constructor injection for required settings
|
||||
* (or a custom {@link org.springframework.beans.factory.InitializingBean} implementation)
|
||||
*/
|
||||
@Deprecated
|
||||
public class RequiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
|
||||
MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Bean definition attribute that may indicate whether a given bean is supposed
|
||||
* to be skipped when performing this post-processor's required property check.
|
||||
* @see #shouldSkip
|
||||
*/
|
||||
public static final String SKIP_REQUIRED_CHECK_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(RequiredAnnotationBeanPostProcessor.class, "skipRequiredCheck");
|
||||
|
||||
|
||||
private Class<? extends Annotation> requiredAnnotationType = Required.class;
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE - 1;
|
||||
|
||||
@Nullable
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* Cache for validated bean names, skipping re-validation for the same bean.
|
||||
*/
|
||||
private final Set<String> validatedBeanNames = Collections.newSetFromMap(new ConcurrentHashMap<>(64));
|
||||
|
||||
|
||||
/**
|
||||
* Set the 'required' annotation type, to be used on bean property
|
||||
* setter methods.
|
||||
* <p>The default required annotation type is the Spring-provided
|
||||
* {@link Required} annotation.
|
||||
* <p>This setter property exists so that developers can provide their own
|
||||
* (non-Spring-specific) annotation type to indicate that a property value
|
||||
* is required.
|
||||
*/
|
||||
public void setRequiredAnnotationType(Class<? extends Annotation> requiredAnnotationType) {
|
||||
Assert.notNull(requiredAnnotationType, "'requiredAnnotationType' must not be null");
|
||||
this.requiredAnnotationType = requiredAnnotationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'required' annotation type.
|
||||
*/
|
||||
protected Class<? extends Annotation> getRequiredAnnotationType() {
|
||||
return this.requiredAnnotationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(
|
||||
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
|
||||
|
||||
if (!this.validatedBeanNames.contains(beanName)) {
|
||||
if (!shouldSkip(this.beanFactory, beanName)) {
|
||||
List<String> invalidProperties = new ArrayList<>();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) {
|
||||
invalidProperties.add(pd.getName());
|
||||
}
|
||||
}
|
||||
if (!invalidProperties.isEmpty()) {
|
||||
throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName));
|
||||
}
|
||||
}
|
||||
this.validatedBeanNames.add(beanName);
|
||||
}
|
||||
return pvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given bean definition is not subject to the annotation-based
|
||||
* required property check as performed by this post-processor.
|
||||
* <p>The default implementations check for the presence of the
|
||||
* {@link #SKIP_REQUIRED_CHECK_ATTRIBUTE} attribute in the bean definition, if any.
|
||||
* It also suggests skipping in case of a bean definition with a "factory-bean"
|
||||
* reference set, assuming that instance-based factories pre-populate the bean.
|
||||
* @param beanFactory the BeanFactory to check against
|
||||
* @param beanName the name of the bean to check against
|
||||
* @return {@code true} to skip the bean; {@code false} to process it
|
||||
*/
|
||||
protected boolean shouldSkip(@Nullable ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) {
|
||||
return false;
|
||||
}
|
||||
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
|
||||
if (beanDefinition.getFactoryBeanName() != null) {
|
||||
return true;
|
||||
}
|
||||
Object value = beanDefinition.getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE);
|
||||
return (value != null && (Boolean.TRUE.equals(value) || Boolean.parseBoolean(value.toString())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the supplied property required to have a value (that is, to be dependency-injected)?
|
||||
* <p>This implementation looks for the existence of a
|
||||
* {@link #setRequiredAnnotationType "required" annotation}
|
||||
* on the supplied {@link PropertyDescriptor property}.
|
||||
* @param propertyDescriptor the target PropertyDescriptor (never {@code null})
|
||||
* @return {@code true} if the supplied property has been marked as being required;
|
||||
* {@code false} if not, or if the supplied property does not have a setter method
|
||||
*/
|
||||
protected boolean isRequiredProperty(PropertyDescriptor propertyDescriptor) {
|
||||
Method setter = propertyDescriptor.getWriteMethod();
|
||||
return (setter != null && AnnotationUtils.getAnnotation(setter, getRequiredAnnotationType()) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an exception message for the given list of invalid properties.
|
||||
* @param invalidProperties the list of names of invalid properties
|
||||
* @param beanName the name of the bean
|
||||
* @return the exception message
|
||||
*/
|
||||
private String buildExceptionMessage(List<String> invalidProperties, String beanName) {
|
||||
int size = invalidProperties.size();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(size == 1 ? "Property" : "Properties");
|
||||
for (int i = 0; i < size; i++) {
|
||||
String propertyName = invalidProperties.get(i);
|
||||
if (i > 0) {
|
||||
if (i == (size - 1)) {
|
||||
sb.append(" and");
|
||||
}
|
||||
else {
|
||||
sb.append(',');
|
||||
}
|
||||
}
|
||||
sb.append(" '").append(propertyName).append('\'');
|
||||
}
|
||||
sb.append(size == 1 ? " is" : " are");
|
||||
sb.append(" required for bean '").append(beanName).append('\'');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user