mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-19 19:29:03 +00:00
Compare commits
779
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45eb23bd21 | ||
|
|
d703ca95d7 | ||
|
|
106a757098 | ||
|
|
8637540678 | ||
|
|
5bb1c3e1e3 | ||
|
|
2a0a002bd3 | ||
|
|
514f7e3328 | ||
|
|
cdd0456aa4 | ||
|
|
9f03d158ce | ||
|
|
ba0c48b933 | ||
|
|
82dbde13b6 | ||
|
|
a698adf125 | ||
|
|
50e4308779 | ||
|
|
07bac70c09 | ||
|
|
cc740dfd93 | ||
|
|
15af0d9787 | ||
|
|
2b974da395 | ||
|
|
e7c038f2d2 | ||
|
|
b8e663c531 | ||
|
|
0f73a69033 | ||
|
|
e9626779ee | ||
|
|
5f4c461d4f | ||
|
|
ef8652615c | ||
|
|
d1e5a3af9f | ||
|
|
9895e44d73 | ||
|
|
643a68f81b | ||
|
|
ac4525ddf8 | ||
|
|
17caac8f1f | ||
|
|
165d2511b9 | ||
|
|
d27bae245a | ||
|
|
0ebc020b21 | ||
|
|
59a9c8e004 | ||
|
|
ca7634dfe8 | ||
|
|
5eca512c46 | ||
|
|
99da6e9723 | ||
|
|
1241c3b2d1 | ||
|
|
7c62d7cfe2 | ||
|
|
6507b09c7f | ||
|
|
229f354df1 | ||
|
|
43ea25e413 | ||
|
|
4560dc2818 | ||
|
|
d0033f12d0 | ||
|
|
85ec9b9df2 | ||
|
|
4732f83d70 | ||
|
|
7cc700435b | ||
|
|
493e9c1ff0 | ||
|
|
edadb9efb6 | ||
|
|
810b615471 | ||
|
|
51f9e0aaca | ||
|
|
d6aa589c50 | ||
|
|
fc6cff53bb | ||
|
|
20f4022e7b | ||
|
|
020c537c03 | ||
|
|
e373b46660 | ||
|
|
5dcde9e7d7 | ||
|
|
ef72ef54fa | ||
|
|
a77eee899a | ||
|
|
9837ec5904 | ||
|
|
bdac937a43 | ||
|
|
6ca3884759 | ||
|
|
189e1afc6e | ||
|
|
d1862a26dd | ||
|
|
2b65d0e51f | ||
|
|
86fb43900e | ||
|
|
e1e6224acb | ||
|
|
cf565067fe | ||
|
|
2159518252 | ||
|
|
754ad4d0d3 | ||
|
|
72dddfbc7b | ||
|
|
dc3f953f4b | ||
|
|
4058361e84 | ||
|
|
952045c216 | ||
|
|
815f151448 | ||
|
|
605e2477b9 | ||
|
|
304c85ec70 | ||
|
|
f56fa91430 | ||
|
|
9cb5369cb9 | ||
|
|
a82f049083 | ||
|
|
b219c6ce15 | ||
|
|
17a4193810 | ||
|
|
29ab38acb2 | ||
|
|
4938dab0ae | ||
|
|
b94e8c4bef | ||
|
|
abc68ef8ea | ||
|
|
d37a18ff03 | ||
|
|
11976fa949 | ||
|
|
6e3f974951 | ||
|
|
1faeeaea14 | ||
|
|
dc2535516c | ||
|
|
673a20cb10 | ||
|
|
f52f3a2f35 | ||
|
|
77129f5a2b | ||
|
|
d289befa2b | ||
|
|
b802c28d27 | ||
|
|
556656b35a | ||
|
|
74630a1b0c | ||
|
|
63984800e4 | ||
|
|
4b24bcb799 | ||
|
|
1cb9f2c7b2 | ||
|
|
72fbbb2403 | ||
|
|
d459e1ad61 | ||
|
|
78a6429c32 | ||
|
|
bd6432cb79 | ||
|
|
fced4e1f9c | ||
|
|
56d93bac89 | ||
|
|
8d1de75b60 | ||
|
|
b2756f5bd2 | ||
|
|
31a24720a6 | ||
|
|
7a7958f275 | ||
|
|
ca9c34710f | ||
|
|
9cbd585c30 | ||
|
|
a218bf40cd | ||
|
|
93e7a0a59d | ||
|
|
b83ceab88a | ||
|
|
c15bbd675f | ||
|
|
5a8b8b11e4 | ||
|
|
a00be62b04 | ||
|
|
4955d08f28 | ||
|
|
6361b0cb23 | ||
|
|
5e4a8966ee | ||
|
|
09da10cc6c | ||
|
|
44f39d4ce0 | ||
|
|
1d593a970a | ||
|
|
e42cf9dc56 | ||
|
|
65cb935333 | ||
|
|
0e8ed5931d | ||
|
|
a240cfcf2f | ||
|
|
199be6aec5 | ||
|
|
99da8e1477 | ||
|
|
2f04cbba51 | ||
|
|
fc9d1760be | ||
|
|
aab421167b | ||
|
|
112cc70231 | ||
|
|
93189a6733 | ||
|
|
81d77b9872 | ||
|
|
ee95a110bd | ||
|
|
c48672c4c7 | ||
|
|
ef72baad3a | ||
|
|
14e87d2733 | ||
|
|
388ce92861 | ||
|
|
38ae282c3b | ||
|
|
05d616240a | ||
|
|
8eef97da33 | ||
|
|
270099383b | ||
|
|
0ad35053fb | ||
|
|
058608021e | ||
|
|
106ae0cc5b | ||
|
|
7b7a8196f5 | ||
|
|
2c98c1b81a | ||
|
|
7b9c30f26e | ||
|
|
474ac2d975 | ||
|
|
6eb0a60df9 | ||
|
|
5bbbc82e19 | ||
|
|
4b4503085a | ||
|
|
73a96c5152 | ||
|
|
9a13d93a6b | ||
|
|
894044cea0 | ||
|
|
0550c08f86 | ||
|
|
073f304db9 | ||
|
|
58a99e3983 | ||
|
|
62f2a6352f | ||
|
|
528b9c17ec | ||
|
|
31318652ea | ||
|
|
f15bd88211 | ||
|
|
220951707b | ||
|
|
18ac86ae16 | ||
|
|
3258ac1ec4 | ||
|
|
54f5b7d0ee | ||
|
|
aaaf81ed99 | ||
|
|
6a012147c4 | ||
|
|
9abd4ed33d | ||
|
|
cf7ee0739f | ||
|
|
db63f7dd4a | ||
|
|
7a5f8e03bc | ||
|
|
50e5bdb813 | ||
|
|
9efea7eb73 | ||
|
|
d3cdecc621 | ||
|
|
c024bdcc6f | ||
|
|
6d7827e36b | ||
|
|
d5dab12909 | ||
|
|
7854b7ac40 | ||
|
|
26b1c848b8 | ||
|
|
5e153e4a77 | ||
|
|
16e9b83d43 | ||
|
|
516c01c438 | ||
|
|
43077072ad | ||
|
|
0841dc5f99 | ||
|
|
15f8863f19 | ||
|
|
bc3b95db92 | ||
|
|
66f822e600 | ||
|
|
dfc193b85e | ||
|
|
029101c79a | ||
|
|
3eee118b44 | ||
|
|
959cf61647 | ||
|
|
82eb82a040 | ||
|
|
80b8382f00 | ||
|
|
ebbe14c363 | ||
|
|
c2e545776d | ||
|
|
97ac1c22c5 | ||
|
|
a528407d0c | ||
|
|
58cde3c2e6 | ||
|
|
fedbb09ad9 | ||
|
|
81fde5ec41 | ||
|
|
aa7f69a5d1 | ||
|
|
91de8d265e | ||
|
|
77ab88b144 | ||
|
|
738097def2 | ||
|
|
b90553db5c | ||
|
|
56234fe877 | ||
|
|
c16f36b537 | ||
|
|
ae8f680d2e | ||
|
|
bf272b0b21 | ||
|
|
b1b28d4641 | ||
|
|
17b2b8af86 | ||
|
|
262c702da4 | ||
|
|
548126ddd8 | ||
|
|
7e9857a663 | ||
|
|
0134c9d608 | ||
|
|
5fe628a811 | ||
|
|
759013eb17 | ||
|
|
a55ca56e34 | ||
|
|
d6a5c3428b | ||
|
|
24848ec1bc | ||
|
|
fef0e21d8b | ||
|
|
8c7579eba8 | ||
|
|
a3d763d137 | ||
|
|
2a5d7690b6 | ||
|
|
f5aeb81473 | ||
|
|
02d3cfa42d | ||
|
|
12f168290d | ||
|
|
88cb126511 | ||
|
|
f3c29fe2e6 | ||
|
|
abf9ce8a34 | ||
|
|
63275ae2b7 | ||
|
|
3203d39821 | ||
|
|
ce5c65c0b0 | ||
|
|
afa38f5f97 | ||
|
|
7b6f2f8fb3 | ||
|
|
bfb49c7249 | ||
|
|
729ce4108d | ||
|
|
1a37345e84 | ||
|
|
c89e6c616a | ||
|
|
539cfc24c6 | ||
|
|
39ce989d1a | ||
|
|
0f2d9df79f | ||
|
|
b9603680bc | ||
|
|
7bbd4c681f | ||
|
|
ba3fef3e8a | ||
|
|
f4b05dc2e7 | ||
|
|
46a5fb7a91 | ||
|
|
093254b2b3 | ||
|
|
9f857c1f16 | ||
|
|
75b1396768 | ||
|
|
4182935b7a | ||
|
|
445b76bbe8 | ||
|
|
3bab3515b1 | ||
|
|
0c0de851f4 | ||
|
|
e31914bada | ||
|
|
40148c0560 | ||
|
|
3a66927bd2 | ||
|
|
c58da71006 | ||
|
|
818c2aa3b9 | ||
|
|
d96a7b4bfc | ||
|
|
b3aad549c9 | ||
|
|
865f1f692a | ||
|
|
93df24af16 | ||
|
|
a5339d71ea | ||
|
|
e4c84ec757 | ||
|
|
f5da737bd4 | ||
|
|
c187cb2fa1 | ||
|
|
ed1d63dcc3 | ||
|
|
e26ae9853e | ||
|
|
362c59c310 | ||
|
|
b6e8674700 | ||
|
|
db8a94ce5f | ||
|
|
3232825a55 | ||
|
|
e71ff2901a | ||
|
|
d9c1811d21 | ||
|
|
5e7a8b275d | ||
|
|
ea3250c8d6 | ||
|
|
b1f5f51503 | ||
|
|
2ce03f34d9 | ||
|
|
9280e32d5d | ||
|
|
5cd525a2b0 | ||
|
|
2ac4355ec0 | ||
|
|
a3cd7af72d | ||
|
|
6a9f91081e | ||
|
|
f65408f646 | ||
|
|
59fa647e2d | ||
|
|
0a7dcf14f9 | ||
|
|
86846507e2 | ||
|
|
133b8b0b5a | ||
|
|
dc8f6f7177 | ||
|
|
c2b55e60cd | ||
|
|
48654c6483 | ||
|
|
47aec50917 | ||
|
|
6f36514369 | ||
|
|
9da9bb9652 | ||
|
|
3f42e16172 | ||
|
|
7c36549e3a | ||
|
|
991e9f4269 | ||
|
|
2a41067a17 | ||
|
|
42a95b8f35 | ||
|
|
76d203fc61 | ||
|
|
9fc7bfde99 | ||
|
|
a999c4aa7e | ||
|
|
a82d726f76 | ||
|
|
5fb8dec50e | ||
|
|
dc1e3b4628 | ||
|
|
fa096dc60f | ||
|
|
fc957e95bb | ||
|
|
3fee8cb625 | ||
|
|
e68bf010da | ||
|
|
f32e1bcbe3 | ||
|
|
8df3fd3f1d | ||
|
|
4faee165db | ||
|
|
8223ed38c8 | ||
|
|
3681d58e98 | ||
|
|
2146e13787 | ||
|
|
a61d107606 | ||
|
|
67bd3f670f | ||
|
|
95542778ad | ||
|
|
7a8a2d9608 | ||
|
|
256a6fe6cb | ||
|
|
d28b73ad22 | ||
|
|
56a8526f3c | ||
|
|
fb2565f2fe | ||
|
|
50a4769162 | ||
|
|
ffa032e78f | ||
|
|
f0f1979fc5 | ||
|
|
488a1d4561 | ||
|
|
611019b73c | ||
|
|
11a017d8b7 | ||
|
|
2439f87a48 | ||
|
|
2ba5ded306 | ||
|
|
2eae37dde0 | ||
|
|
42b7c5a79b | ||
|
|
1cb08f5782 | ||
|
|
feeec344e5 | ||
|
|
51bb96db47 | ||
|
|
eac9e66c46 | ||
|
|
28cf7b728f | ||
|
|
f68b1e0bce | ||
|
|
c3c2383b0d | ||
|
|
41e6aa6de2 | ||
|
|
de453ace86 | ||
|
|
0176d362be | ||
|
|
946ec7e22e | ||
|
|
a64e85fcc6 | ||
|
|
47fe05066d | ||
|
|
a37efc9881 | ||
|
|
f738273486 | ||
|
|
1c67ef4bed | ||
|
|
dd2ce20687 | ||
|
|
83a54dba7e | ||
|
|
85262a7932 | ||
|
|
862dd23975 | ||
|
|
149d416e8e | ||
|
|
1621125ccf | ||
|
|
a0b42a3dfd | ||
|
|
5b5f7190bf | ||
|
|
7ff938b3ef | ||
|
|
da23505e94 | ||
|
|
00b7782b5f | ||
|
|
6f0c869afe | ||
|
|
857b600675 | ||
|
|
d303c8a20f | ||
|
|
ab8310b5f3 | ||
|
|
fdaceeb6c9 | ||
|
|
2c5a1af236 | ||
|
|
f885910887 | ||
|
|
e14cf699c8 | ||
|
|
93bb78ec23 | ||
|
|
b2bf5fe0f3 | ||
|
|
423aa28ed5 | ||
|
|
50949415d7 | ||
|
|
608fd766cb | ||
|
|
58b3af9475 | ||
|
|
5f2d47a17e | ||
|
|
2255d222e3 | ||
|
|
ecd0d7f0f6 | ||
|
|
309e70a48e | ||
|
|
658c7f99d7 | ||
|
|
c5ca56bd50 | ||
|
|
05830912a5 | ||
|
|
864d7eaf11 | ||
|
|
bfc5ad890e | ||
|
|
b7e4a56e5c | ||
|
|
0b2c482e29 | ||
|
|
dcf2861db5 | ||
|
|
5474995288 | ||
|
|
a2ae5f6972 | ||
|
|
4ee704cedf | ||
|
|
8df0bc88d2 | ||
|
|
c567e65eea | ||
|
|
050f44d75b | ||
|
|
60b5161fbe | ||
|
|
10d5de7d63 | ||
|
|
8de5c05af0 | ||
|
|
f12c28e402 | ||
|
|
ce7278aaf4 | ||
|
|
61403e3bd3 | ||
|
|
cc172bcedc | ||
|
|
e18149878c | ||
|
|
c89e3e6e0d | ||
|
|
d05924165b | ||
|
|
82a211fa96 | ||
|
|
062805fcb3 | ||
|
|
053820c4ff | ||
|
|
f662e3b85e | ||
|
|
44afed426a | ||
|
|
83909e6e1e | ||
|
|
fdf340306d | ||
|
|
d9e7253532 | ||
|
|
2b986af310 | ||
|
|
c8c0737ce7 | ||
|
|
19f3347932 | ||
|
|
efdbddd358 | ||
|
|
cf3635b42d | ||
|
|
1e0de072f9 | ||
|
|
bb5c8ed4e8 | ||
|
|
c01f350abe | ||
|
|
928c541401 | ||
|
|
bef22ec9b5 | ||
|
|
29ff8a8d12 | ||
|
|
af6a5566a3 | ||
|
|
635d2146db | ||
|
|
ccce61e2b2 | ||
|
|
9630445253 | ||
|
|
1c90d481d5 | ||
|
|
d16a710d13 | ||
|
|
4d24503317 | ||
|
|
1489457025 | ||
|
|
9064ef59f9 | ||
|
|
983bce125f | ||
|
|
80e7819d6f | ||
|
|
cb4fa3795a | ||
|
|
9d5aced8c5 | ||
|
|
ff7ccf0d4e | ||
|
|
9975646ffb | ||
|
|
38e5c01c3c | ||
|
|
3ff5731429 | ||
|
|
1320fed7fe | ||
|
|
e63bffcfa0 | ||
|
|
77205ca165 | ||
|
|
31095f1d4e | ||
|
|
49bc746640 | ||
|
|
1b8421c7fe | ||
|
|
00353a073c | ||
|
|
9fed4d0375 | ||
|
|
fc03707445 | ||
|
|
7aa933437c | ||
|
|
a8f4c596fd | ||
|
|
058f027c5b | ||
|
|
2ec41c8153 | ||
|
|
ad29f97a05 | ||
|
|
9063e66c5d | ||
|
|
d6dfde3e5b | ||
|
|
333e327289 | ||
|
|
255015fc6b | ||
|
|
6ff8cd8a9f | ||
|
|
18c9e3e812 | ||
|
|
a76b8deda5 | ||
|
|
7ca6b9f7d2 | ||
|
|
51ba322947 | ||
|
|
9e2912e1dd | ||
|
|
6d226326c9 | ||
|
|
45ecfc6df9 | ||
|
|
59e87f950b | ||
|
|
917bb53718 | ||
|
|
f7263abbf0 | ||
|
|
2a6da6a623 | ||
|
|
92b3f2aee7 | ||
|
|
80e52de231 | ||
|
|
75627617c9 | ||
|
|
3f5a7bbf04 | ||
|
|
093a863906 | ||
|
|
90c29b3af3 | ||
|
|
f7839675f6 | ||
|
|
47d6e91227 | ||
|
|
b6b880ce27 | ||
|
|
7481d73456 | ||
|
|
288a9ecd18 | ||
|
|
a278e878e8 | ||
|
|
082c524cbe | ||
|
|
d3c08552e9 | ||
|
|
50c9542796 | ||
|
|
a6f9c4c599 | ||
|
|
af58263744 | ||
|
|
8a4835368d | ||
|
|
1756f83701 | ||
|
|
d94e9225f4 | ||
|
|
65ca7f4909 | ||
|
|
0204b082b1 | ||
|
|
5b25aaacb6 | ||
|
|
6431b25045 | ||
|
|
745aeda581 | ||
|
|
c634b2fae7 | ||
|
|
00a3afcda8 | ||
|
|
b29a278b2a | ||
|
|
95ff22cb7e | ||
|
|
395e3d008c | ||
|
|
d0ada5653f | ||
|
|
0948edb39d | ||
|
|
c8869d99f5 | ||
|
|
69e8bcdf40 | ||
|
|
c385a1de83 | ||
|
|
88ab911cf1 | ||
|
|
51f7a3e40f | ||
|
|
34663300a6 | ||
|
|
cc87fbcb7f | ||
|
|
c4aea626fe | ||
|
|
a680880a9b | ||
|
|
8e83f140d4 | ||
|
|
db8e9eafb2 | ||
|
|
41d4cb5cbf | ||
|
|
12240c7524 | ||
|
|
e62298eaad | ||
|
|
66c66baa8f | ||
|
|
cf9641686b | ||
|
|
97cea7f36e | ||
|
|
77887ef739 | ||
|
|
cbc0fad961 | ||
|
|
65c8fa400f | ||
|
|
068565172e | ||
|
|
cde677a1f4 | ||
|
|
184340ff8e | ||
|
|
9cb8b4bb0a | ||
|
|
b6d32ef55f | ||
|
|
b83bc39ecd | ||
|
|
45936f0ddd | ||
|
|
43a814b070 | ||
|
|
bffa4b88af | ||
|
|
dcac30c41c | ||
|
|
f35f7db29b | ||
|
|
09af706af6 | ||
|
|
1a0522b805 | ||
|
|
1da4d504c4 | ||
|
|
e47355078c | ||
|
|
28208310dc | ||
|
|
c06b9525ac | ||
|
|
e49896d95f | ||
|
|
6c487f7799 | ||
|
|
aa848d54ff | ||
|
|
3abebb3799 | ||
|
|
87fac79b90 | ||
|
|
90a4740279 | ||
|
|
c803ad7998 | ||
|
|
84ec382201 | ||
|
|
8d45e3e7ef | ||
|
|
c8627c05ed | ||
|
|
f30d19b724 | ||
|
|
2163fa94a7 | ||
|
|
f55a6051df | ||
|
|
c450f8dd82 | ||
|
|
fd352b84b3 | ||
|
|
8658a357c8 | ||
|
|
d537a1cfb4 | ||
|
|
3302798e2f | ||
|
|
d570f82456 | ||
|
|
f87a37fd0d | ||
|
|
48c660fa41 | ||
|
|
f8a0e3d084 | ||
|
|
259b2ca5f4 | ||
|
|
196c0adf47 | ||
|
|
3067682347 | ||
|
|
7041e5e8e3 | ||
|
|
1bdbc7bdef | ||
|
|
bff2d2cc85 | ||
|
|
ab086f4225 | ||
|
|
326895246d | ||
|
|
2c1dca5b5e | ||
|
|
454cd933d4 | ||
|
|
dcdf9c09f5 | ||
|
|
c2585073ba | ||
|
|
95a56cd28d | ||
|
|
51cee658d5 | ||
|
|
8c6f3505c4 | ||
|
|
78cad0fdd3 | ||
|
|
a689daadf9 | ||
|
|
fb3c1881ca | ||
|
|
280da61d5c | ||
|
|
1dac0df38b | ||
|
|
7dba79c7c1 | ||
|
|
4883b8aa03 | ||
|
|
08ba53dd0e | ||
|
|
52c91910b2 | ||
|
|
4b86d42890 | ||
|
|
03f1920106 | ||
|
|
7056808716 | ||
|
|
9614817e88 | ||
|
|
f6ee2508ef | ||
|
|
2bb15f7ed2 | ||
|
|
482115f3ce | ||
|
|
35c847a708 | ||
|
|
253ffd719d | ||
|
|
62cb8ba6ba | ||
|
|
7fdd1372ae | ||
|
|
4db5d28894 | ||
|
|
f13f041fae | ||
|
|
6ef0938a92 | ||
|
|
c55a9072aa | ||
|
|
709b185177 | ||
|
|
89e2caa4f3 | ||
|
|
8848e6ab9f | ||
|
|
a8fbac8472 | ||
|
|
1d59e52f11 | ||
|
|
a6a6cf7d97 | ||
|
|
2ac23badee | ||
|
|
ad88c02bc3 | ||
|
|
498984324d | ||
|
|
0dd9e8ce02 | ||
|
|
6bcb454a0d | ||
|
|
84300b796c | ||
|
|
1eb06fcd90 | ||
|
|
50b6f9da1d | ||
|
|
31c7807ac9 | ||
|
|
04d2d1da0d | ||
|
|
dc55da0988 | ||
|
|
5d7fb1a1c2 | ||
|
|
2ec8fa9cac | ||
|
|
446a604ad0 | ||
|
|
cd403f4180 | ||
|
|
23fc6f6b1d | ||
|
|
432cdd7802 | ||
|
|
d3be1cc6cb | ||
|
|
69e4f21f90 | ||
|
|
109a2b49e5 | ||
|
|
50dc8c2358 | ||
|
|
d20d95b7ac | ||
|
|
4d7b265258 | ||
|
|
f2506ca7a1 | ||
|
|
1b54d2119d | ||
|
|
a87b319a6f | ||
|
|
7e91733502 | ||
|
|
04141dee65 | ||
|
|
6027cf2255 | ||
|
|
c0c9e08bf9 | ||
|
|
de38af6843 | ||
|
|
3e4d305291 | ||
|
|
7a0c03e05e | ||
|
|
2f732a8dea | ||
|
|
1bc08c61e1 | ||
|
|
bdac39150f | ||
|
|
24ed6de6aa | ||
|
|
ac544924c8 | ||
|
|
04a7f0884b | ||
|
|
999c7809a7 | ||
|
|
347852e86a | ||
|
|
777bd0d022 | ||
|
|
aebbd949a8 | ||
|
|
8126ffbc8c | ||
|
|
13c090b41d | ||
|
|
1dcb6236a6 | ||
|
|
99f0129711 | ||
|
|
430065c31d | ||
|
|
5322fa0fb7 | ||
|
|
20d0221d4f | ||
|
|
df51ff0386 | ||
|
|
cfb1ed1009 | ||
|
|
c4a7567a5e | ||
|
|
8d08935c49 | ||
|
|
30b8d47814 | ||
|
|
71d4dbea13 | ||
|
|
8bf8092740 | ||
|
|
fc16b2d3fb | ||
|
|
2b2a5a414b | ||
|
|
f931a3fb59 | ||
|
|
aef39e8954 | ||
|
|
aebb2d52e0 | ||
|
|
def6fbba89 | ||
|
|
c437a0d1c3 | ||
|
|
309ffc6d0d | ||
|
|
61c52d64c5 | ||
|
|
282a4ad2f6 | ||
|
|
8a1588ae29 | ||
|
|
85ad2a566d | ||
|
|
4d86779648 | ||
|
|
20f2e23bfb | ||
|
|
8ea913392c | ||
|
|
b3ca2d50a2 | ||
|
|
3a5def047f | ||
|
|
eddbf13d5d | ||
|
|
6b6384a09e | ||
|
|
8e571decc1 | ||
|
|
8f513f8561 | ||
|
|
57ded51de0 | ||
|
|
915afa77f4 | ||
|
|
58e9706991 | ||
|
|
65f29a39ca | ||
|
|
7cf98261ce | ||
|
|
247ec572b2 | ||
|
|
3f7d4b107e | ||
|
|
4521a79b2d | ||
|
|
fa72186e28 | ||
|
|
b8b6367f9b | ||
|
|
7077af14f1 | ||
|
|
1c628293a2 | ||
|
|
a06e63f619 | ||
|
|
eacf1d35ee | ||
|
|
a0dfdfcac3 | ||
|
|
c90ab5fb0a | ||
|
|
52f6dcf525 | ||
|
|
7b608ab995 | ||
|
|
be211ceead | ||
|
|
896eb5687a | ||
|
|
7e9b7102b7 | ||
|
|
b325c74216 | ||
|
|
2b051b8b32 | ||
|
|
34ddb88851 | ||
|
|
a4c750e94c | ||
|
|
2d05f2ed47 | ||
|
|
4a18488f30 | ||
|
|
6b82a6c38c | ||
|
|
2938a95435 | ||
|
|
d72d376f03 | ||
|
|
f155d21c95 | ||
|
|
28565e25fa | ||
|
|
943b394992 | ||
|
|
8a9d042320 | ||
|
|
e64c6dfa3d | ||
|
|
69c6a40c50 | ||
|
|
a9a38fe67e | ||
|
|
2216964b54 | ||
|
|
7f0e3481a5 | ||
|
|
2054fa2191 | ||
|
|
821ab62492 | ||
|
|
c55c9eb029 | ||
|
|
bb2db87c2f | ||
|
|
a8a1fc6de5 | ||
|
|
0878e438e5 | ||
|
|
aec98268fe | ||
|
|
5095ec40b5 | ||
|
|
542ed81d5c | ||
|
|
217aa38cbb | ||
|
|
2474c48749 | ||
|
|
dc36bb34c7 | ||
|
|
6735e2387c | ||
|
|
50550717d6 | ||
|
|
c46dacc209 | ||
|
|
fa97aab8be | ||
|
|
b5c691bdac | ||
|
|
29ce6685ca | ||
|
|
78eda961f2 | ||
|
|
70dbaf9751 | ||
|
|
0001f87d59 | ||
|
|
589b7048ec | ||
|
|
9b671f8408 | ||
|
|
65d5cb3663 | ||
|
|
31024b1f93 | ||
|
|
92eaf99067 | ||
|
|
6cd9060183 | ||
|
|
f8340838b3 | ||
|
|
487e14d549 | ||
|
|
9b1eb397ee | ||
|
|
f74a631ea1 | ||
|
|
4a147d26fc | ||
|
|
457d586859 | ||
|
|
aa656c47b8 | ||
|
|
109552d868 | ||
|
|
1c40e36839 | ||
|
|
1fd6248d84 | ||
|
|
c037e75f26 | ||
|
|
23bda9a5a7 | ||
|
|
91d17cf628 | ||
|
|
fcbf06f050 | ||
|
|
f5ff1dc3f9 | ||
|
|
025fd2962e | ||
|
|
7c9ba80f85 | ||
|
|
e82efbc7e3 | ||
|
|
bcb485b5ed | ||
|
|
c022f7c19d | ||
|
|
ee95f171c8 | ||
|
|
8277ea5794 | ||
|
|
e366b20037 | ||
|
|
38525ceff6 | ||
|
|
964467d269 | ||
|
|
e458777925 | ||
|
|
142530874b |
+8
-8
@@ -29,7 +29,7 @@ If you have a question, check StackOverflow using
|
||||
Find an existing discussion or start a new one if necessary.
|
||||
|
||||
If you suspect an issue, perform a search in the
|
||||
[JIRA issue tracker](https://jira.spring.io/browse/SPR), using a few different keywords.
|
||||
[Github issue tracker](https://github.com/spring-projects/spring-framework/issues), using a few different keywords.
|
||||
When you find related issues and discussions, prior or current, it helps you to learn and
|
||||
it helps us to make a decision.
|
||||
|
||||
@@ -42,7 +42,7 @@ Before you create a ticket, please take the time to [research first](#discuss).
|
||||
|
||||
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
|
||||
|
||||
When ready create a ticket in the [JIRA issue tracker](https://jira.spring.io/browse/SPR).
|
||||
When ready create a ticket in the [Github issue tracker](https://github.com/spring-projects/spring-framework/issues).
|
||||
|
||||
#### Ticket Lifecycle
|
||||
|
||||
@@ -66,7 +66,7 @@ automatically when you submit a pull request.
|
||||
|
||||
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
|
||||
The purpose of the ticket is to understand and discuss the underlying issue or feature.
|
||||
We use the JIRA issue tracker as the preferred place of record for conversations and
|
||||
We use the GitHub issue tracker as the preferred place of record for conversations and
|
||||
conclusions. In that sense discussions directly under a PR are more implementation detail
|
||||
oriented and transient in nature.
|
||||
|
||||
@@ -75,8 +75,8 @@ oriented and transient in nature.
|
||||
Backports to prior versions will be considered on a case-by-case basis and reflected as
|
||||
the fix version in the issue tracker.
|
||||
|
||||
1. Use short branch names, preferably based on the JIRA issue (e.g. `SPR-1234`), or
|
||||
otherwise using succinct, lower-case, dash (-) delimited names, such as `fix-warnings'.
|
||||
1. Use short branch names, preferably based on the GitHub issue (e.g. `22276`), or
|
||||
otherwise using succinct, lower-case, dash (-) delimited names, such as `fix-warnings`.
|
||||
|
||||
1. Choose the granularity of your commits consciously and squash commits that represent
|
||||
multiple edits or corrections of the same logical change. See
|
||||
@@ -84,12 +84,12 @@ multiple edits or corrections of the same logical change. See
|
||||
for an overview of streamlining commit history.
|
||||
|
||||
1. Format commit messages using 55 characters for the subject line, 72 lines for the
|
||||
description, followed by related issues, e.g. `Issues: SPR-1234, SPR-1235`.
|
||||
description, followed by the issue fixed, e.g. `Fixes #22276`.
|
||||
See the
|
||||
[Commit Guidelines section of Pro Git](http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
|
||||
for best practices around commit messages and use `git log` to see some examples.
|
||||
|
||||
1. List the JIRA issue number in the PR description.
|
||||
1. List the GitHub issue number in the PR description.
|
||||
|
||||
If accepted, your contribution may be heavily modified as needed prior to merging.
|
||||
You will likely retain author attribution for your Git commits granted that the bulk of
|
||||
@@ -116,7 +116,7 @@ defines the source file coding standards we use along with some IDEA editor sett
|
||||
|
||||
The reference documentation is in the [src/docs/asciidoc](src/docs/asciidoc) directory and, in
|
||||
[Asciidoctor](http://asciidoctor.org/) format. For trivial changes, you may be able to browse,
|
||||
edit source files, and submit directly from Github.
|
||||
edit source files, and submit directly from GitHub.
|
||||
|
||||
When making changes locally, use `./gradlew asciidoctor` and then browse the result under
|
||||
`build/asciidoc/html5/index.html`.
|
||||
|
||||
@@ -1,48 +1,30 @@
|
||||
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework
|
||||
|
||||
This is the home of the Spring Framework, the foundation for all
|
||||
[Spring projects](https://spring.io/projects). Together the Spring Framework and the family of Spring projects make up what we call "Spring".
|
||||
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects is often referred to simply as "Spring".
|
||||
|
||||
Spring provides everything you need beyond the Java language to create enterprise
|
||||
applications in a wide range of scenarios and architectures. Please read the
|
||||
[Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction)
|
||||
section in the reference for a more complete introduction.
|
||||
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating you are expected to uphold this code.
|
||||
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Access to Binaries
|
||||
|
||||
For access to artifacts or a distribution zip, see the
|
||||
[Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts)
|
||||
wiki page.
|
||||
For access to artifacts or a distribution zip, see the [Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts) wiki page.
|
||||
|
||||
## Documentation
|
||||
|
||||
The Spring Frameworks maintains reference documentation
|
||||
([published](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and
|
||||
[source](src/docs/asciidoc)),
|
||||
Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
|
||||
[API reference](http://docs.spring.io/spring-framework/docs/current/javadoc-api/).
|
||||
There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
|
||||
The Spring Framework maintains reference documentation ([published](http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](src/docs/asciidoc)), Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
|
||||
[API reference](http://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
|
||||
|
||||
## Build from Source
|
||||
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
|
||||
wiki page and also [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) Wikipedia page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
|
||||
|
||||
## Stay in Touch
|
||||
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral),
|
||||
[@SpringFramework](https://twitter.com/springframework), and its
|
||||
[team members](https://twitter.com/springframework/lists/team/members) on Twitter.
|
||||
In-depth articles can be found at [The Spring Blog](http://spring.io/blog/),
|
||||
and releases are announced via our [news feed](http://spring.io/blog/category/news).
|
||||
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](http://spring.io/blog/), and releases are announced via our [news feed](http://spring.io/blog/category/news).
|
||||
|
||||
## License
|
||||
|
||||
The Spring Framework is released under version 2.0 of the
|
||||
[Apache License](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
The Spring Framework is released under version 2.0 of the [Apache License](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
+72
-75
@@ -11,43 +11,41 @@ buildscript {
|
||||
// 3rd party plugin repositories can be configured in settings.gradle
|
||||
plugins {
|
||||
id "io.spring.dependency-management" version "1.0.5.RELEASE" apply false
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.51" apply false
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.71" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.17"
|
||||
id "org.asciidoctor.convert" version "1.5.7"
|
||||
id "org.asciidoctor.convert" version "1.5.8"
|
||||
}
|
||||
|
||||
ext {
|
||||
linkHomepage = 'https://projects.spring.io/spring-framework'
|
||||
linkCi = 'https://build.spring.io/browse/SPR'
|
||||
linkIssue = 'https://jira.spring.io/browse/SPR'
|
||||
linkScmUrl = 'https://github.com/spring-projects/spring-framework'
|
||||
linkScmConnection = 'scm:git:git://github.com/spring-projects/spring-framework.git'
|
||||
linkScmDevConnection = 'scm:git:ssh://git@github.com:spring-projects/spring-framework.git'
|
||||
linkHomepage = "https://projects.spring.io/spring-framework"
|
||||
linkCi = "https://build.spring.io/browse/SPR"
|
||||
linkIssue = "https://github.com/spring-projects/spring-framework/issues"
|
||||
linkScmUrl = "https://github.com/spring-projects/spring-framework"
|
||||
linkScmConnection = "scm:git:git://github.com/spring-projects/spring-framework.git"
|
||||
linkScmDevConnection = "scm:git:ssh://git@github.com:spring-projects/spring-framework.git"
|
||||
|
||||
moduleProjects = subprojects.findAll {
|
||||
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
|
||||
!it.name.equals("spring-build-src") && !it.name.equals("spring-framework-bom")
|
||||
}
|
||||
|
||||
aspectjVersion = "1.9.1"
|
||||
aspectjVersion = "1.9.2"
|
||||
freemarkerVersion = "2.3.28"
|
||||
groovyVersion = "2.5.1"
|
||||
groovyVersion = "2.5.6"
|
||||
hsqldbVersion = "2.4.1"
|
||||
jackson2Version = "2.9.6"
|
||||
jettyVersion = "9.4.11.v20180605"
|
||||
junitPlatformVersion = "1.2.0"
|
||||
junitJupiterVersion = "5.2.0"
|
||||
junitVintageVersion = "5.2.0"
|
||||
kotlinVersion = "1.2.51"
|
||||
log4jVersion = "2.11.0"
|
||||
nettyVersion = "4.1.27.Final"
|
||||
reactorVersion = "Californium-M1"
|
||||
jackson2Version = "2.9.8"
|
||||
jettyVersion = "9.4.14.v20181114"
|
||||
junit5Version = "5.3.2"
|
||||
kotlinVersion = "1.2.71"
|
||||
log4jVersion = "2.11.2"
|
||||
nettyVersion = "4.1.33.Final"
|
||||
reactorVersion = "Californium-SR5"
|
||||
rxjavaVersion = "1.3.8"
|
||||
rxjavaAdapterVersion = "1.2.1"
|
||||
rxjava2Version = "2.1.17"
|
||||
rxjava2Version = "2.2.6"
|
||||
slf4jVersion = "1.7.25" // spring-jcl + consistent 3rd party deps
|
||||
tiles3Version = "3.0.8"
|
||||
tomcatVersion = "9.0.10"
|
||||
undertowVersion = "2.0.11.Final"
|
||||
tomcatVersion = "9.0.16"
|
||||
undertowVersion = "2.0.17.Final"
|
||||
|
||||
gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
withoutJclOverSlf4J = {
|
||||
@@ -59,16 +57,17 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "java"
|
||||
apply plugin: "kotlin"
|
||||
apply plugin: "checkstyle"
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "test-source-set-dependencies"
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply from: "${gradleScriptDir}/ide.gradle"
|
||||
apply plugin: "checkstyle"
|
||||
|
||||
dependencyManagement {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
cacheChangingModulesFor 0, "seconds"
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
generatedPomCustomization {
|
||||
@@ -76,38 +75,16 @@ configure(allprojects) { project ->
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.10.1"
|
||||
configDir = rootProject.file("src/checkstyle")
|
||||
}
|
||||
|
||||
apply plugin: "kotlin"
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
apiVersion = "1.1"
|
||||
languageVersion = "1.1"
|
||||
}
|
||||
}
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
// Check for updates every build
|
||||
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
|
||||
resolutionStrategy.cacheChangingModulesFor 0, "seconds"
|
||||
|
||||
// Consistent slf4j version (e.g. clashes between slf4j versions)
|
||||
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
||||
if (details.requested.group == 'org.slf4j') {
|
||||
if (details.requested.group == "org.slf4j") {
|
||||
details.useVersion slf4jVersion
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def commonCompilerArgs =
|
||||
@@ -120,25 +97,42 @@ configure(allprojects) { project ->
|
||||
"-Xlint:deprecation", "-Xlint:unchecked", "-Werror"]
|
||||
|
||||
compileTestJava.options*.compilerArgs = commonCompilerArgs +
|
||||
["-Xlint:-varargs", "-Xlint:-fallthrough","-Xlint:-rawtypes",
|
||||
["-Xlint:-varargs", "-Xlint:-fallthrough", "-Xlint:-rawtypes",
|
||||
"-Xlint:-deprecation", "-Xlint:-unchecked"]
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = 1.8 // can be switched to 10 for testing
|
||||
sourceCompatibility = 1.8 // can be switched to 11 for testing
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = 1.8 // can be switched to 10 for testing
|
||||
sourceCompatibility = 1.8 // can be switched to 11 for testing
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.encoding = "UTF-8"
|
||||
options.compilerArgs += "-parameters"
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
apiVersion = "1.1"
|
||||
languageVersion = "1.1"
|
||||
}
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = ["-Xjsr305=strict"]
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
systemProperty("java.awt.headless", "true")
|
||||
systemProperty("testGroups", project.properties.get("testGroups"))
|
||||
systemProperty("io.netty.leakDetection.level", "paranoid")
|
||||
scanForTestClasses = false
|
||||
include(["**/*Tests.class", "**/*Test.class"])
|
||||
// Since we set scanForTestClasses to false, we need to filter out inner
|
||||
@@ -148,22 +142,27 @@ configure(allprojects) { project ->
|
||||
reports.junitXml.setDestination(file("$buildDir/test-results"))
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion = "8.17"
|
||||
configDir = rootProject.file("src/checkstyle")
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-release" }
|
||||
maven { url "https://repo.spring.io/milestone" } // for Reactor
|
||||
maven { url "https://repo.spring.io/snapshot" } // Reactor
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile("junit:junit:4.12") {
|
||||
exclude group:'org.hamcrest', module:'hamcrest-core'
|
||||
exclude group: "org.hamcrest", module: "hamcrest-core"
|
||||
}
|
||||
testCompile("org.mockito:mockito-core:2.20.0") {
|
||||
exclude group:'org.hamcrest', module:'hamcrest-core'
|
||||
testCompile("org.mockito:mockito-core:2.24.0") {
|
||||
exclude group: "org.hamcrest", module: "hamcrest-core"
|
||||
}
|
||||
testCompile("com.nhaarman:mockito-kotlin:1.6.0") {
|
||||
exclude module:'kotlin-stdlib'
|
||||
exclude module:'kotlin-reflect'
|
||||
exclude module:'mockito-core'
|
||||
exclude module: "kotlin-stdlib"
|
||||
exclude module: "kotlin-reflect"
|
||||
exclude module: "mockito-core"
|
||||
}
|
||||
testCompile("org.hamcrest:hamcrest-all:1.3")
|
||||
testRuntime("org.apache.logging.log4j:log4j-core:${log4jVersion}")
|
||||
@@ -188,10 +187,12 @@ configure(allprojects) { project ->
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/2.10.4",
|
||||
"http://quartz-scheduler.org/api/2.2.1/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
|
||||
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/"
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.9/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.9/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.9/",
|
||||
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/",
|
||||
"https://junit.org/junit4/javadoc/4.12/",
|
||||
"https://junit.org/junit5/docs/${junit5Version}/api/"
|
||||
] as String[]
|
||||
}
|
||||
|
||||
@@ -221,7 +222,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
options.header = project.name
|
||||
options.use = true
|
||||
options.links(project.ext.javadocLinks)
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.addStringOption("Xdoclint:none", "-quiet")
|
||||
|
||||
// Suppress warnings due to cross-module @see and @link references.
|
||||
// Note that global 'api' task does display all warnings.
|
||||
@@ -231,7 +232,7 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
classifier = 'sources'
|
||||
classifier = "sources"
|
||||
from sourceSets.main.allSource
|
||||
// Don't include or exclude anything explicitly by default. See SPR-12085.
|
||||
}
|
||||
@@ -260,7 +261,7 @@ configure(rootProject) {
|
||||
}
|
||||
}
|
||||
|
||||
// don't publish the default jar for the root project
|
||||
// Don't publish the default jar for the root project
|
||||
configurations.archives.artifacts.clear()
|
||||
|
||||
dependencies { // for integration tests
|
||||
@@ -279,7 +280,7 @@ configure(rootProject) {
|
||||
testCompile("javax.servlet:javax.servlet-api:3.1.0")
|
||||
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.15.Final")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.17.Final")
|
||||
}
|
||||
|
||||
artifacts {
|
||||
@@ -289,9 +290,6 @@ configure(rootProject) {
|
||||
}
|
||||
|
||||
wrapper {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = '4.8.1'
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
def gradleBatOpts = "$gradleOpts -XX:MaxHeapSize=256m"
|
||||
@@ -303,7 +301,6 @@ configure(rootProject) {
|
||||
"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -317,7 +314,7 @@ def qualifyVersionIfNecessary(version) {
|
||||
if (rootProject.hasProperty("BRANCH_NAME")) {
|
||||
def qualifier = rootProject.getProperty("BRANCH_NAME")
|
||||
if (qualifier.startsWith("SPR-")) {
|
||||
return version.replace('BUILD', qualifier)
|
||||
return version.replace("BUILD", qualifier)
|
||||
}
|
||||
}
|
||||
return version
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.1.0.RC1
|
||||
version=5.1.5.RELEASE
|
||||
|
||||
@@ -27,6 +27,7 @@ task api(type: Javadoc) {
|
||||
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
|
||||
options.author = true
|
||||
options.header = rootProject.description
|
||||
options.use = true
|
||||
options.overview = "src/docs/api/overview.html"
|
||||
options.stylesheetFile = file("src/docs/api/stylesheet.css")
|
||||
options.splitIndex = true
|
||||
|
||||
@@ -52,8 +52,8 @@ def customizePom(pom, gradleProject) {
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
system = "Jira"
|
||||
url = "https://jira.springsource.org/browse/SPR"
|
||||
system = "GitHub"
|
||||
url = "https://github.com/spring-projects/spring-framework/issues"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ include "spring-framework-bom"
|
||||
include "buildSrc"
|
||||
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
|
||||
|
||||
rootProject.name = 'spring'
|
||||
rootProject.name = "spring"
|
||||
rootProject.children.each {project ->
|
||||
project.buildFileName = "${project.name}.gradle"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ description = "Spring AOP"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(':spring-core'))
|
||||
compile(project(":spring-core"))
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.apache.commons:commons-pool2:2.6.0")
|
||||
optional("com.jamonapi:jamon:2.81")
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.aopalliance.intercept;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* Description of an invocation to a constuctor, given to an
|
||||
* Description of an invocation to a constructor, given to an
|
||||
* interceptor upon constructor-call.
|
||||
*
|
||||
* <p>A constructor invocation is a joinpoint and can be intercepted
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface MethodInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the method being called.
|
||||
* <p>This method is a frienly implementation of the
|
||||
* <p>This method is a friendly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the method being called
|
||||
*/
|
||||
|
||||
@@ -63,7 +63,7 @@ import org.springframework.util.StringUtils;
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
|
||||
|
||||
/**
|
||||
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
|
||||
* Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
|
||||
*/
|
||||
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
|
||||
|
||||
|
||||
+1
-9
@@ -272,15 +272,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (AmbiguousBindingException ambigEx) {
|
||||
if (this.raiseExceptions) {
|
||||
throw ambigEx;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
catch (AmbiguousBindingException | IllegalArgumentException ex) {
|
||||
if (this.raiseExceptions) {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
+34
-47
@@ -42,7 +42,6 @@ import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for factories that can create Spring AOP Advisors
|
||||
@@ -60,6 +59,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
|
||||
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
|
||||
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
@@ -128,10 +130,8 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
Class<?>[] classesToLookFor = new Class<?>[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<?> c : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
|
||||
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
@@ -152,16 +152,12 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
|
||||
/**
|
||||
* AspectJ annotation types.
|
||||
* Enum for AspectJ annotation types.
|
||||
* @see AspectJAnnotation#getAnnotationType()
|
||||
*/
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
AtAfterReturning,
|
||||
AtAfterThrowing,
|
||||
AtAround
|
||||
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
|
||||
}
|
||||
|
||||
|
||||
@@ -172,17 +168,17 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
*/
|
||||
protected static class AspectJAnnotation<A extends Annotation> {
|
||||
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
|
||||
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
|
||||
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypes = new HashMap<>();
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);
|
||||
|
||||
static {
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
|
||||
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
|
||||
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
|
||||
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
|
||||
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
|
||||
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
|
||||
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
|
||||
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
|
||||
}
|
||||
|
||||
private final A annotation;
|
||||
@@ -196,40 +192,31 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
public AspectJAnnotation(A annotation) {
|
||||
this.annotation = annotation;
|
||||
this.annotationType = determineAnnotationType(annotation);
|
||||
// We know these methods exist with the same name on each object,
|
||||
// but need to invoke them reflectively as there isn't a common interface.
|
||||
try {
|
||||
this.pointcutExpression = resolveExpression(annotation);
|
||||
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
|
||||
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
|
||||
this.argumentNames = (argNames instanceof String ? (String) argNames : "");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
|
||||
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private AspectJAnnotationType determineAnnotationType(A annotation) {
|
||||
for (Map.Entry<Class<?>, AspectJAnnotationType> typeEntry : annotationTypes.entrySet()) {
|
||||
Class<?> type = typeEntry.getKey();
|
||||
if (type.isInstance(annotation)) {
|
||||
return typeEntry.getValue();
|
||||
}
|
||||
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation);
|
||||
}
|
||||
|
||||
private String resolveExpression(A annotation) throws Exception {
|
||||
for (String methodName : EXPRESSION_PROPERTIES) {
|
||||
Method method;
|
||||
try {
|
||||
method = annotation.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
method = null;
|
||||
}
|
||||
if (method != null) {
|
||||
String candidate = (String) method.invoke(annotation);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
return candidate;
|
||||
private String resolveExpression(A annotation) {
|
||||
for (String attributeName : EXPRESSION_ATTRIBUTES) {
|
||||
Object val = AnnotationUtils.getValue(annotation, attributeName);
|
||||
if (val instanceof String) {
|
||||
String str = (String) val;
|
||||
if (!str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,11 +262,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (strTok.countTokens() > 0) {
|
||||
String[] names = new String[strTok.countTokens()];
|
||||
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (nameTokens.countTokens() > 0) {
|
||||
String[] names = new String[nameTokens.countTokens()];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = strTok.nextToken();
|
||||
names[i] = nameTokens.nextToken();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
+51
-51
@@ -116,14 +116,41 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
|
||||
/**
|
||||
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
|
||||
* depending on the state of the advice.
|
||||
* The pointcut for Spring AOP to use.
|
||||
* Actual behaviour of the pointcut will change depending on the state of the advice.
|
||||
*/
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
|
||||
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return (advice != null ? advice : EMPTY_ADVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only of interest for Spring AOP: AspectJ instantiation semantics
|
||||
* are much richer. In AspectJ terminology, all a return of {@code true}
|
||||
@@ -141,34 +168,6 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.aspectInstanceFactory.getAspectMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
|
||||
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return (advice != null ? advice : EMPTY_ADVICE);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
return this.aspectInstanceFactory;
|
||||
}
|
||||
@@ -221,33 +220,26 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
else {
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
case AtAround:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isBeforeAdvice = true;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtAfter:
|
||||
case AtAfterReturning:
|
||||
case AtAfterThrowing:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = true;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtAround:
|
||||
case AtPointcut:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
@@ -258,11 +250,18 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
|
||||
* be optimized out if it does not at first match statically.
|
||||
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
|
||||
* if it does not at first match statically.
|
||||
*/
|
||||
private final class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
|
||||
|
||||
@@ -273,7 +272,7 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
@Nullable
|
||||
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
|
||||
|
||||
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
@@ -285,7 +284,8 @@ final class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
||||
// We're either instantiated and matching on declared pointcut,
|
||||
// or uninstantiated matching on either pointcut...
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
|
||||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
|
||||
}
|
||||
|
||||
+9
-9
@@ -246,6 +246,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
AbstractAspectJAdvice springAdvice;
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
@@ -270,15 +279,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,11 +32,10 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* Utility class for handling registration of AOP auto-proxy creators.
|
||||
*
|
||||
* <p>Only a single auto-proxy creator can be registered yet multiple concrete
|
||||
* implementations are available. Therefore this class wraps a simple escalation
|
||||
* protocol, allowing classes to request a particular auto-proxy creator and know
|
||||
* that class, {@code or a subclass thereof}, will eventually be resident
|
||||
* in the application context.
|
||||
* <p>Only a single auto-proxy creator should be registered yet multiple concrete
|
||||
* implementations are available. This class provides a simple escalation protocol,
|
||||
* allowing a caller to request a particular auto-proxy creator and know that creator,
|
||||
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -55,12 +54,10 @@ public abstract class AopConfigUtils {
|
||||
/**
|
||||
* Stores the auto proxy creator classes in escalation order.
|
||||
*/
|
||||
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();
|
||||
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
|
||||
|
||||
/**
|
||||
* Setup the escalation list.
|
||||
*/
|
||||
static {
|
||||
// Set up the escalation list...
|
||||
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
|
||||
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
|
||||
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
|
||||
@@ -73,8 +70,8 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
|
||||
@Nullable Object source) {
|
||||
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
@@ -85,8 +82,8 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
|
||||
@Nullable Object source) {
|
||||
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
@@ -97,8 +94,8 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
|
||||
@Nullable Object source) {
|
||||
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
|
||||
BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
|
||||
}
|
||||
@@ -118,8 +115,8 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
|
||||
@Nullable Object source) {
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(
|
||||
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
|
||||
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,11 +28,11 @@ import org.springframework.lang.Nullable;
|
||||
* Utility class for handling registration of auto-proxy creators used internally
|
||||
* by the '{@code aop}' namespace tags.
|
||||
*
|
||||
* <p>Only a single auto-proxy creator can be registered and multiple tags may wish
|
||||
* to register different concrete implementations. As such this class delegates to
|
||||
* {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
|
||||
* may request a particular auto-proxy creator and know that class, <i>or a subclass
|
||||
* thereof</i>, will eventually be resident in the application context.
|
||||
* <p>Only a single auto-proxy creator should be registered and multiple configuration
|
||||
* elements may wish to register different concrete implementations. As such this class
|
||||
* delegates to {@link AopConfigUtils} which provides a simple escalation protocol.
|
||||
* Callers may request a particular auto-proxy creator and know that creator,
|
||||
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -95,9 +95,8 @@ public abstract class AopNamespaceUtils {
|
||||
|
||||
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
|
||||
if (beanDefinition != null) {
|
||||
BeanComponentDefinition componentDefinition =
|
||||
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
parserContext.registerComponent(componentDefinition);
|
||||
parserContext.registerComponent(
|
||||
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -63,7 +63,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof AopInfrastructureBean || this.advisor == null) {
|
||||
if (this.advisor == null || bean instanceof AopInfrastructureBean) {
|
||||
// Ignore AOP infrastructure such as scoped proxies.
|
||||
return bean;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
}
|
||||
|
||||
// No async proxy needed.
|
||||
// No proxy needed.
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,8 +157,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
@Override
|
||||
public Object getProxy(@Nullable ClassLoader classLoader) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -723,17 +723,20 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
|
||||
|
||||
@Nullable
|
||||
private final MethodProxy methodProxy;
|
||||
|
||||
private final boolean publicMethod;
|
||||
|
||||
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
|
||||
Object[] arguments, @Nullable Class<?> targetClass,
|
||||
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
|
||||
|
||||
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
|
||||
this.methodProxy = methodProxy;
|
||||
this.publicMethod = Modifier.isPublic(method.getModifiers());
|
||||
|
||||
// Only use method proxy for public methods not derived from java.lang.Object
|
||||
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
|
||||
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
|
||||
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
|
||||
methodProxy : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -742,7 +745,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeJoinpoint() throws Throwable {
|
||||
if (this.publicMethod && getMethod().getDeclaringClass() != Object.class) {
|
||||
if (this.methodProxy != null) {
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
}
|
||||
else {
|
||||
@@ -795,7 +798,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* <dt>For advised methods:</dt>
|
||||
* <dd>If the target is static and the advice chain is frozen then a
|
||||
* FixedChainStaticTargetInterceptor specific to the method is used to
|
||||
* invoke the advice chain. Otherwise a DyanmicAdvisedInterceptor is
|
||||
* invoke the advice chain. Otherwise a DynamicAdvisedInterceptor is
|
||||
* used.</dd>
|
||||
* <dt>For non-advised methods:</dt>
|
||||
* <dd>Where it can be determined that the method will not return {@code this}
|
||||
@@ -810,24 +813,28 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
@Override
|
||||
public int accept(Method method) {
|
||||
if (AopUtils.isFinalizeMethod(method)) {
|
||||
logger.debug("Found finalize() method - using NO_OVERRIDE");
|
||||
logger.trace("Found finalize() method - using NO_OVERRIDE");
|
||||
return NO_OVERRIDE;
|
||||
}
|
||||
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
|
||||
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method is declared on Advised interface: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Method is declared on Advised interface: " + method);
|
||||
}
|
||||
return DISPATCH_ADVISED;
|
||||
}
|
||||
// We must always proxy equals, to direct calls to this.
|
||||
if (AopUtils.isEqualsMethod(method)) {
|
||||
logger.debug("Found 'equals' method: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found 'equals' method: " + method);
|
||||
}
|
||||
return INVOKE_EQUALS;
|
||||
}
|
||||
// We must always calculate hashCode based on the proxy.
|
||||
if (AopUtils.isHashCodeMethod(method)) {
|
||||
logger.debug("Found 'hashCode' method: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found 'hashCode' method: " + method);
|
||||
}
|
||||
return INVOKE_HASHCODE;
|
||||
}
|
||||
Class<?> targetClass = this.advised.getTargetClass();
|
||||
@@ -840,8 +847,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (haveAdvice || !isFrozen) {
|
||||
// If exposing the proxy, then AOP_PROXY must be used.
|
||||
if (exposeProxy) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Must expose proxy on advised method: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Must expose proxy on advised method: " + method);
|
||||
}
|
||||
return AOP_PROXY;
|
||||
}
|
||||
@@ -849,16 +856,16 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// Check to see if we have fixed interceptor to serve this method.
|
||||
// Else use the AOP_PROXY.
|
||||
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method has advice and optimizations are enabled: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Method has advice and optimizations are enabled: " + method);
|
||||
}
|
||||
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
|
||||
int index = this.fixedInterceptorMap.get(key);
|
||||
return (index + this.fixedInterceptorOffset);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unable to apply any optimizations to advised method: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Unable to apply any optimizations to advised method: " + method);
|
||||
}
|
||||
return AOP_PROXY;
|
||||
}
|
||||
@@ -874,15 +881,15 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method return type is assignable from target type and " +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Method return type is assignable from target type and " +
|
||||
"may therefore return 'this' - using INVOKE_TARGET: " + method);
|
||||
}
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method return type ensures 'this' cannot be returned - " +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Method return type ensures 'this' cannot be returned - " +
|
||||
"using DISPATCH_TARGET: " + method);
|
||||
}
|
||||
return DISPATCH_TARGET;
|
||||
|
||||
@@ -115,8 +115,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
|
||||
@Override
|
||||
public Object getProxy(@Nullable ClassLoader classLoader) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
|
||||
}
|
||||
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
|
||||
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
|
||||
|
||||
+2
-2
@@ -136,8 +136,8 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
|
||||
exceptionClass = exceptionClass.getSuperclass();
|
||||
handler = this.exceptionHandlerMap.get(exceptionClass);
|
||||
}
|
||||
if (handler != null && logger.isDebugEnabled()) {
|
||||
logger.debug("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
|
||||
if (handler != null && logger.isTraceEnabled()) {
|
||||
logger.trace("Found handler for exception of type [" + exceptionClass.getName() + "]: " + handler);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
+15
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -133,7 +133,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
|
||||
|
||||
private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
|
||||
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);
|
||||
|
||||
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
|
||||
|
||||
@@ -236,9 +236,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
@Override
|
||||
public Object getEarlyBeanReference(Object bean, String beanName) {
|
||||
Object cacheKey = getCacheKey(bean.getClass(), beanName);
|
||||
if (!this.earlyProxyReferences.contains(cacheKey)) {
|
||||
this.earlyProxyReferences.add(cacheKey);
|
||||
}
|
||||
this.earlyProxyReferences.put(cacheKey, bean);
|
||||
return wrapIfNecessary(bean, beanName, cacheKey);
|
||||
}
|
||||
|
||||
@@ -297,7 +295,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
|
||||
if (bean != null) {
|
||||
Object cacheKey = getCacheKey(bean.getClass(), beanName);
|
||||
if (!this.earlyProxyReferences.contains(cacheKey)) {
|
||||
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
|
||||
return wrapIfNecessary(bean, beanName, cacheKey);
|
||||
}
|
||||
}
|
||||
@@ -385,14 +383,17 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
/**
|
||||
* Subclasses should override this method to return {@code true} if the
|
||||
* given bean should not be considered for auto-proxying by this post-processor.
|
||||
* <p>Sometimes we need to be able to avoid this happening if it will lead to
|
||||
* a circular reference. This implementation returns {@code false}.
|
||||
* <p>Sometimes we need to be able to avoid this happening, e.g. if it will lead to
|
||||
* a circular reference or if the existing target instance needs to be preserved.
|
||||
* This implementation returns {@code false} unless the bean name indicates an
|
||||
* "original instance" according to {@code AutowireCapableBeanFactory} conventions.
|
||||
* @param beanClass the class of the bean
|
||||
* @param beanName the name of the bean
|
||||
* @return whether to skip the given bean
|
||||
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
|
||||
*/
|
||||
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
|
||||
return false;
|
||||
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,9 +415,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
TargetSource ts = tsc.getTargetSource(beanClass, beanName);
|
||||
if (ts != null) {
|
||||
// Found a matching TargetSource.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("TargetSourceCreator [" + tsc +
|
||||
" found custom TargetSource for bean with name '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("TargetSourceCreator [" + tsc +
|
||||
"] found custom TargetSource for bean with name '" + beanName + "'");
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
@@ -522,10 +523,10 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
int nrOfCommonInterceptors = commonInterceptors.length;
|
||||
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
|
||||
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
|
||||
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
|
||||
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,4 +64,10 @@ public abstract class AbstractBeanFactoryAwareAdvisingPostProcessor extends Abst
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEligible(Object bean, String beanName) {
|
||||
return (!AutoProxyUtils.isOriginalInstance(beanName, bean.getClass()) &&
|
||||
super.isEligible(bean, beanName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+29
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Utilities for auto-proxy aware components.
|
||||
@@ -63,7 +65,9 @@ public abstract class AutoProxyUtils {
|
||||
* @param beanName the name of the bean
|
||||
* @return whether the given bean should be proxied with its target class
|
||||
*/
|
||||
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
|
||||
public static boolean shouldProxyTargetClass(
|
||||
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
|
||||
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
|
||||
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
|
||||
@@ -81,7 +85,9 @@ public abstract class AutoProxyUtils {
|
||||
* @see org.springframework.beans.factory.BeanFactory#getType(String)
|
||||
*/
|
||||
@Nullable
|
||||
public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
|
||||
public static Class<?> determineTargetClass(
|
||||
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
|
||||
|
||||
if (beanName == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -102,12 +108,30 @@ public abstract class AutoProxyUtils {
|
||||
* @param targetClass the corresponding target class
|
||||
* @since 4.2.3
|
||||
*/
|
||||
static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName,
|
||||
Class<?> targetClass) {
|
||||
static void exposeTargetClass(
|
||||
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {
|
||||
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given bean name indicates an "original instance"
|
||||
* according to {@link AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX},
|
||||
* skipping any proxy attempts for it.
|
||||
* @param beanName the name of the bean
|
||||
* @param beanClass the corresponding bean class
|
||||
* @since 5.1
|
||||
* @see AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
|
||||
*/
|
||||
static boolean isOriginalInstance(String beanName, Class<?> beanClass) {
|
||||
if (!StringUtils.hasLength(beanName) || beanName.length() !=
|
||||
beanClass.getName().length() + AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX.length()) {
|
||||
return false;
|
||||
}
|
||||
return (beanName.startsWith(beanClass.getName()) &&
|
||||
beanName.endsWith(AutowireCapableBeanFactory.ORIGINAL_INSTANCE_SUFFIX));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -82,8 +82,8 @@ public class BeanFactoryAdvisorRetrievalHelper {
|
||||
for (String name : advisorNames) {
|
||||
if (isEligibleBean(name)) {
|
||||
if (this.beanFactory.isCurrentlyInCreation(name)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping currently created advisor '" + name + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Skipping currently created advisor '" + name + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -96,8 +96,8 @@ public class BeanFactoryAdvisorRetrievalHelper {
|
||||
BeanCreationException bce = (BeanCreationException) rootCause;
|
||||
String bceBeanName = bce.getBeanName();
|
||||
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Skipping advisor '" + name +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Skipping advisor '" + name +
|
||||
"' with dependency on currently created bean: " + ex.getMessage());
|
||||
}
|
||||
// Ignore: indicates a reference back to the bean we're trying to advise.
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
|
||||
/**
|
||||
* The {@code $[targetClassName]} placeholder.
|
||||
* Replaced with the fully-qualifed name of the {@code Class}
|
||||
* Replaced with the fully-qualified name of the {@code Class}
|
||||
* of the method invocation target.
|
||||
*/
|
||||
public static final String PLACEHOLDER_TARGET_CLASS_NAME = "$[targetClassName]";
|
||||
|
||||
@@ -52,7 +52,8 @@ import org.springframework.util.ClassUtils;
|
||||
* @see #setProxyTargetClass
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<Object>, BeanFactoryAware {
|
||||
public class ScopedProxyFactoryBean extends ProxyConfig
|
||||
implements FactoryBean<Object>, BeanFactoryAware, AopInfrastructureBean {
|
||||
|
||||
/** The TargetSource that manages scoping. */
|
||||
private final SimpleBeanTargetSource scopedTargetSource = new SimpleBeanTargetSource();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -77,8 +77,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this if it's possible to filter out
|
||||
* some candidate classes.
|
||||
* Subclasses can override this if it's possible to filter out some candidate classes.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import org.springframework.aop.Pointcut;
|
||||
* Convenient superclass when we want to force subclasses to
|
||||
* implement MethodMatcher interface, but subclasses
|
||||
* will want to be pointcuts. The getClassFilter() method can
|
||||
* be overriden to customize ClassFilter behaviour as well.
|
||||
* be overridden to customize ClassFilter behaviour as well.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.aop.support.annotation;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -50,7 +50,7 @@ public class AnnotationClassFilter implements ClassFilter {
|
||||
* @param annotationType the annotation type to look for
|
||||
* @param checkInherited whether to also check the superclasses and
|
||||
* interfaces as well as meta-annotations for the annotation type
|
||||
* (i.e. whether to use {@link AnnotationUtils#findAnnotation(Class, Class)}
|
||||
* (i.e. whether to use {@link AnnotatedElementUtils#hasAnnotation}
|
||||
* semantics instead of standard Java {@link Class#isAnnotationPresent})
|
||||
*/
|
||||
public AnnotationClassFilter(Class<? extends Annotation> annotationType, boolean checkInherited) {
|
||||
@@ -62,8 +62,7 @@ public class AnnotationClassFilter implements ClassFilter {
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
return (this.checkInherited ?
|
||||
(AnnotationUtils.findAnnotation(clazz, this.annotationType) != null) :
|
||||
return (this.checkInherited ? AnnotatedElementUtils.hasAnnotation(clazz, this.annotationType) :
|
||||
clazz.isAnnotationPresent(this.annotationType));
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -22,7 +22,7 @@ import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -54,7 +54,7 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
|
||||
* @param annotationType the annotation type to look for
|
||||
* @param checkInherited whether to also check the superclasses and
|
||||
* interfaces as well as meta-annotations for the annotation type
|
||||
* (i.e. whether to use {@link AnnotationUtils#findAnnotation(Method, Class)}
|
||||
* (i.e. whether to use {@link AnnotatedElementUtils#hasAnnotation}
|
||||
* semantics instead of standard Java {@link Method#isAnnotationPresent})
|
||||
* @since 5.0
|
||||
*/
|
||||
@@ -81,8 +81,7 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
|
||||
}
|
||||
|
||||
private boolean matchesMethod(Method method) {
|
||||
return (this.checkInherited ?
|
||||
(AnnotationUtils.findAnnotation(method, this.annotationType) != null) :
|
||||
return (this.checkInherited ? AnnotatedElementUtils.hasAnnotation(method, this.annotationType) :
|
||||
method.isAnnotationPresent(this.annotationType));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -218,7 +218,7 @@ public class MethodInvocationProceedingJoinPointTests {
|
||||
itb.unreliableFileOperation();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// we don't realy care...
|
||||
// we don't really care...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -758,7 +758,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around(value="setAge(age)",argNames="age")
|
||||
// @ArgNames({"age"}) // AMC needs more work here? ignoring pjp arg... ok??
|
||||
// argNames should be suported in Around as it is in Pointcut
|
||||
// argNames should be supported in Around as it is in Pointcut
|
||||
public void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
|
||||
pjp.proceed(new Object[] {age*2});
|
||||
}
|
||||
@@ -884,12 +884,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Aspect
|
||||
abstract class AbstractMakeModifiable {
|
||||
|
||||
public interface MutableModifable extends Modifiable {
|
||||
public interface MutableModifiable extends Modifiable {
|
||||
|
||||
void markDirty();
|
||||
}
|
||||
|
||||
public static class ModifiableImpl implements MutableModifable {
|
||||
public static class ModifiableImpl implements MutableModifiable {
|
||||
|
||||
private boolean modified;
|
||||
|
||||
@@ -911,7 +911,7 @@ abstract class AbstractMakeModifiable {
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)", argNames="modifiable,newValue")
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(
|
||||
JoinPoint jp, MutableModifable mixin, Object newValue) {
|
||||
JoinPoint jp, MutableModifiable mixin, Object newValue) {
|
||||
|
||||
/*
|
||||
* We use the mixin to check and, if necessary, change,
|
||||
@@ -972,7 +972,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
|
||||
@DeclareParents(value = "org.springframework.tests.sample.beans.ITestBean+",
|
||||
defaultImpl=ModifiableImpl.class)
|
||||
public static MutableModifable mixin;
|
||||
public static MutableModifiable mixin;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -157,7 +157,7 @@ public class DelegatingIntroductionInterceptorTests {
|
||||
TimeStamped ts = (TimeStamped) pf.getProxy();
|
||||
|
||||
assertThat(ts, instanceOf(TimeStamped.class));
|
||||
// Shoulnd't proxy framework interfaces
|
||||
// Shouldn't proxy framework interfaces
|
||||
assertTrue(!(ts instanceof MethodInterceptor));
|
||||
assertTrue(!(ts instanceof IntroductionInterceptor));
|
||||
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ public class HotSwappableTargetSourceTests {
|
||||
@Test
|
||||
public void testRejectsSwapToNull() {
|
||||
IllegalArgumentException ex = testRejectsSwapToInvalidValue(null);
|
||||
assertTrue(ex.getMessage().indexOf("null") != -1);
|
||||
assertTrue(ex.getMessage().contains("null"));
|
||||
}
|
||||
|
||||
// TODO test reject swap to wrong interface or class?
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{1.} - %msg%n" />
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
|
||||
@@ -93,7 +93,7 @@ dependencies {
|
||||
optional("javax.transaction:javax.transaction-api:1.3") // for @javax.transaction.Transactional support
|
||||
testCompile(project(":spring-core")) // for CodeStyleAspect
|
||||
testCompile(project(":spring-test"))
|
||||
testCompile("javax.mail:javax.mail-api:1.6.1")
|
||||
testCompile("javax.mail:javax.mail-api:1.6.2")
|
||||
}
|
||||
|
||||
eclipse.project {
|
||||
|
||||
+2
@@ -55,6 +55,7 @@ public class AnnotationDrivenBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void asyncPostProcessorExecutorReference() {
|
||||
Object executor = context.getBean("testExecutor");
|
||||
Object aspect = context.getBean(TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME);
|
||||
@@ -62,6 +63,7 @@ public class AnnotationDrivenBeanDefinitionParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void asyncPostProcessorExceptionHandlerReference() {
|
||||
Object exceptionHandler = context.getBean("testExceptionHandler");
|
||||
Object aspect = context.getBean(TaskManagementConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{1.} - %msg%n" />
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
|
||||
@@ -3,17 +3,16 @@ description = "Spring Beans"
|
||||
apply plugin: "groovy"
|
||||
|
||||
dependencies {
|
||||
compile(project(':spring-core'))
|
||||
compile(project(":spring-core"))
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("org.yaml:snakeyaml:1.21")
|
||||
optional("org.yaml:snakeyaml:1.23")
|
||||
optional("org.codehaus.groovy:groovy-xml:${groovyVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
}
|
||||
|
||||
// This modules does joint compilation for Java and Groovy code,
|
||||
// with the compileGroovy task.
|
||||
// This module does joint compilation for Java and Groovy code with the compileGroovy task.
|
||||
sourceSets {
|
||||
main.groovy.srcDirs += "src/main/java"
|
||||
main.java.srcDirs = []
|
||||
@@ -24,10 +23,9 @@ compileGroovy {
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
// This module also builds Kotlin code and the compileKotlin task
|
||||
// naturally depends on compileJava.
|
||||
// We need to redefine dependencies to break task cycles.
|
||||
// This module also builds Kotlin code and the compileKotlin task naturally depends on
|
||||
// compileJava. We need to redefine dependencies to break task cycles.
|
||||
def deps = compileGroovy.taskDependencies.immutableValues + compileGroovy.taskDependencies.mutableValues
|
||||
compileGroovy.dependsOn = deps - 'compileJava'
|
||||
compileGroovy.dependsOn = deps - "compileJava"
|
||||
compileKotlin.dependsOn(compileGroovy)
|
||||
compileKotlin.classpath += files(compileGroovy.destinationDir)
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
|
||||
this.wrappedObject = ObjectUtils.unwrapOptional(object);
|
||||
Assert.notNull(this.wrappedObject, "Target object must not be null");
|
||||
this.nestedPath = (nestedPath != null ? nestedPath : "");
|
||||
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : this.wrappedObject);
|
||||
this.rootObject = (!this.nestedPath.isEmpty() ? rootObject : this.wrappedObject);
|
||||
this.nestedPropertyAccessors = null;
|
||||
this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
|
||||
}
|
||||
|
||||
@@ -122,11 +122,9 @@ public abstract class BeanUtils {
|
||||
return instantiateClass(clazz.getDeclaredConstructor());
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(clazz)) {
|
||||
Constructor<T> ctor = findPrimaryConstructor(clazz);
|
||||
if (ctor != null) {
|
||||
return instantiateClass(ctor);
|
||||
}
|
||||
Constructor<T> ctor = findPrimaryConstructor(clazz);
|
||||
if (ctor != null) {
|
||||
return instantiateClass(ctor);
|
||||
}
|
||||
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
|
||||
}
|
||||
@@ -405,8 +403,7 @@ public abstract class BeanUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the JavaBeans {@code PropertyDescriptor}s of a given
|
||||
* class.
|
||||
* Retrieve the JavaBeans {@code PropertyDescriptor}s of a given class.
|
||||
* @param clazz the Class to retrieve the PropertyDescriptors for
|
||||
* @return an array of {@code PropertyDescriptors} for the given class
|
||||
* @throws BeansException if PropertyDescriptor look fails
|
||||
@@ -511,8 +508,8 @@ public abstract class BeanUtils {
|
||||
return (PropertyEditor) instantiateClass(editorClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No property editor [" + editorName + "] found for type " +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No property editor [" + editorName + "] found for type " +
|
||||
targetType.getName() + " according to 'Editor' suffix convention");
|
||||
}
|
||||
unknownEditorTypes.add(targetType);
|
||||
|
||||
@@ -166,7 +166,7 @@ public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a lazily initializted CachedIntrospectionResults instance
|
||||
* Obtain a lazily initialized CachedIntrospectionResults instance
|
||||
* for the wrapped object.
|
||||
*/
|
||||
private CachedIntrospectionResults getCachedIntrospectionResults() {
|
||||
|
||||
@@ -314,6 +314,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getPropertyType() {
|
||||
if (this.propertyType == null) {
|
||||
try {
|
||||
@@ -425,6 +426,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getPropertyType() {
|
||||
if (this.propertyType == null) {
|
||||
try {
|
||||
@@ -460,6 +462,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?> getIndexedPropertyType() {
|
||||
if (this.indexedPropertyType == null) {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.beans;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@@ -93,4 +94,27 @@ public interface TypeConverter {
|
||||
<T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
|
||||
throws TypeMismatchException;
|
||||
|
||||
/**
|
||||
* Convert the value to the required type (if necessary from a String).
|
||||
* <p>Conversions from String to any type will typically use the {@code setAsText}
|
||||
* method of the PropertyEditor class, or a Spring Converter in a ConversionService.
|
||||
* @param value the value to convert
|
||||
* @param requiredType the type we must convert to
|
||||
* (or {@code null} if not known, for example in case of a collection element)
|
||||
* @param typeDescriptor the type descriptor to use (may be {@code null}))
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws TypeMismatchException if type conversion failed
|
||||
* @since 5.1.4
|
||||
* @see java.beans.PropertyEditor#setAsText(String)
|
||||
* @see java.beans.PropertyEditor#getValue()
|
||||
* @see org.springframework.core.convert.ConversionService
|
||||
* @see org.springframework.core.convert.converter.Converter
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
|
||||
@Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
|
||||
|
||||
throw new UnsupportedOperationException("TypeDescriptor resolution not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -30,7 +30,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -82,42 +81,6 @@ class TypeConverterDelegate {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the value to the specified required type.
|
||||
* @param newValue the proposed new value
|
||||
* @param requiredType the type we must convert to
|
||||
* (or {@code null} if not known, for example in case of a collection element)
|
||||
* @param methodParam the method parameter that is the target of the conversion
|
||||
* (may be {@code null})
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
@Nullable
|
||||
public <T> T convertIfNecessary(@Nullable Object newValue, @Nullable Class<T> requiredType,
|
||||
@Nullable MethodParameter methodParam) throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(null, null, newValue, requiredType,
|
||||
(methodParam != null ? new TypeDescriptor(methodParam) : TypeDescriptor.valueOf(requiredType)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the specified required type.
|
||||
* @param newValue the proposed new value
|
||||
* @param requiredType the type we must convert to
|
||||
* (or {@code null} if not known, for example in case of a collection element)
|
||||
* @param field the reflective field that is the target of the conversion
|
||||
* (may be {@code null})
|
||||
* @return the new value, possibly the result of type conversion
|
||||
* @throws IllegalArgumentException if type conversion failed
|
||||
*/
|
||||
@Nullable
|
||||
public <T> T convertIfNecessary(@Nullable Object newValue, @Nullable Class<T> requiredType, @Nullable Field field)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
return convertIfNecessary(null, null, newValue, requiredType,
|
||||
(field != null ? new TypeDescriptor(field) : TypeDescriptor.valueOf(requiredType)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value to the required type for the specified property.
|
||||
* @param propertyName name of the property
|
||||
@@ -247,7 +210,7 @@ class TypeConverterDelegate {
|
||||
}
|
||||
}
|
||||
String trimmedValue = ((String) convertedValue).trim();
|
||||
if (requiredType.isEnum() && "".equals(trimmedValue)) {
|
||||
if (requiredType.isEnum() && trimmedValue.isEmpty()) {
|
||||
// It's an empty enum identifier: reset the enum value to null.
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -21,6 +21,7 @@ import java.lang.reflect.Field;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConverterNotFoundException;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -41,15 +42,16 @@ public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException {
|
||||
return doConvert(value, requiredType, null, null);
|
||||
return convertIfNecessary(value, requiredType, TypeDescriptor.valueOf(requiredType));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable MethodParameter methodParam)
|
||||
throws TypeMismatchException {
|
||||
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
|
||||
@Nullable MethodParameter methodParam) throws TypeMismatchException {
|
||||
|
||||
return doConvert(value, requiredType, methodParam, null);
|
||||
return convertIfNecessary(value, requiredType,
|
||||
(methodParam != null ? new TypeDescriptor(methodParam) : TypeDescriptor.valueOf(requiredType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,21 +59,18 @@ public abstract class TypeConverterSupport extends PropertyEditorRegistrySupport
|
||||
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType, @Nullable Field field)
|
||||
throws TypeMismatchException {
|
||||
|
||||
return doConvert(value, requiredType, null, field);
|
||||
return convertIfNecessary(value, requiredType,
|
||||
(field != null ? new TypeDescriptor(field) : TypeDescriptor.valueOf(requiredType)));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T doConvert(@Nullable Object value,@Nullable Class<T> requiredType,
|
||||
@Nullable MethodParameter methodParam, @Nullable Field field) throws TypeMismatchException {
|
||||
@Override
|
||||
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
|
||||
@Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
|
||||
|
||||
Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
|
||||
try {
|
||||
if (field != null) {
|
||||
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, field);
|
||||
}
|
||||
else {
|
||||
return this.typeConverterDelegate.convertIfNecessary(value, requiredType, methodParam);
|
||||
}
|
||||
return this.typeConverterDelegate.convertIfNecessary(null, null, value, requiredType, typeDescriptor);
|
||||
}
|
||||
catch (ConverterNotFoundException | IllegalStateException ex) {
|
||||
throw new ConversionNotSupportedException(value, requiredType, ex);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,21 +17,19 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
/**
|
||||
* Marker superinterface indicating that a bean is eligible to be
|
||||
* notified by the Spring container of a particular framework object
|
||||
* through a callback-style method. Actual method signature is
|
||||
* determined by individual subinterfaces, but should typically
|
||||
* consist of just one void-returning method that accepts a single
|
||||
* argument.
|
||||
* A marker superinterface indicating that a bean is eligible to be notified by the
|
||||
* Spring container of a particular framework object through a callback-style method.
|
||||
* The actual method signature is determined by individual subinterfaces but should
|
||||
* typically consist of just one void-returning method that accepts a single argument.
|
||||
*
|
||||
* <p>Note that merely implementing {@link Aware} provides no default
|
||||
* functionality. Rather, processing must be done explicitly, for example
|
||||
* in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
|
||||
* <p>Note that merely implementing {@link Aware} provides no default functionality.
|
||||
* Rather, processing must be done explicitly, for example in a
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}.
|
||||
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
|
||||
* and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
|
||||
* for examples of processing {@code *Aware} interface callbacks.
|
||||
* for an example of processing specific {@code *Aware} interface callbacks.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public interface Aware {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -133,8 +133,7 @@ public interface BeanFactory {
|
||||
* Will ask the parent factory if the bean cannot be found in this factory instance.
|
||||
* @param name the name of the bean to retrieve
|
||||
* @return an instance of the bean
|
||||
* @throws NoSuchBeanDefinitionException if there is no bean definition
|
||||
* with the specified name
|
||||
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
|
||||
* @throws BeansException if the bean could not be obtained
|
||||
*/
|
||||
Object getBean(String name) throws BeansException;
|
||||
@@ -214,15 +213,23 @@ public interface BeanFactory {
|
||||
* @param requiredType type the bean must match; can be an interface or superclass
|
||||
* @return a corresponding provider handle
|
||||
* @since 5.1
|
||||
* @see #getBeanProvider(ResolvableType)
|
||||
*/
|
||||
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
|
||||
|
||||
/**
|
||||
* Return an provider for the specified bean, allowing for lazy on-demand retrieval
|
||||
* of instances, including availability and uniqueness options.
|
||||
* @param requiredType type the bean must match; can be a generic type declaration
|
||||
* @param requiredType type the bean must match; can be a generic type declaration.
|
||||
* Note that collection types are not supported here, in contrast to reflective
|
||||
* injection points. For programmatically retrieving a list of beans matching a
|
||||
* specific type, specify the actual bean type as an argument here and subsequently
|
||||
* use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
|
||||
* @return a corresponding provider handle
|
||||
* @since 5.1
|
||||
* @see ObjectProvider#iterator()
|
||||
* @see ObjectProvider#stream()
|
||||
* @see ObjectProvider#orderedStream()
|
||||
*/
|
||||
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
|
||||
|
||||
|
||||
+62
-34
@@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.core.ResolvableType;
|
||||
@@ -51,6 +52,13 @@ public abstract class BeanFactoryUtils {
|
||||
*/
|
||||
public static final String GENERATED_BEAN_NAME_SEPARATOR = "#";
|
||||
|
||||
/**
|
||||
* Cache from name with factory bean prefix to stripped name without dereference.
|
||||
* @since 5.1
|
||||
* @see BeanFactory#FACTORY_BEAN_PREFIX
|
||||
*/
|
||||
private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Return whether the given name is a factory dereference
|
||||
@@ -72,11 +80,16 @@ public abstract class BeanFactoryUtils {
|
||||
*/
|
||||
public static String transformedBeanName(String name) {
|
||||
Assert.notNull(name, "'name' must not be null");
|
||||
String beanName = name;
|
||||
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
|
||||
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
|
||||
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
|
||||
return name;
|
||||
}
|
||||
return beanName;
|
||||
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
|
||||
do {
|
||||
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
|
||||
}
|
||||
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
|
||||
return beanName;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,6 +119,8 @@ public abstract class BeanFactoryUtils {
|
||||
}
|
||||
|
||||
|
||||
// Retrieval of bean names
|
||||
|
||||
/**
|
||||
* Count all beans in any hierarchy in which this factory participates.
|
||||
* Includes counts of ancestor bean factories.
|
||||
@@ -113,6 +128,7 @@ public abstract class BeanFactoryUtils {
|
||||
* with the same name) are only counted once.
|
||||
* @param lbf the bean factory
|
||||
* @return count of beans including those defined in ancestor factories
|
||||
* @see #beanNamesIncludingAncestors
|
||||
*/
|
||||
public static int countBeansIncludingAncestors(ListableBeanFactory lbf) {
|
||||
return beanNamesIncludingAncestors(lbf).length;
|
||||
@@ -140,6 +156,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @param type the type that beans must match (as a {@code ResolvableType})
|
||||
* @return the array of matching bean names, or an empty array if none
|
||||
* @since 4.2
|
||||
* @see ListableBeanFactory#getBeanNamesForType(ResolvableType)
|
||||
*/
|
||||
public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, ResolvableType type) {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
@@ -166,6 +183,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @param lbf the bean factory
|
||||
* @param type the type that beans must match (as a {@code Class})
|
||||
* @return the array of matching bean names, or an empty array if none
|
||||
* @see ListableBeanFactory#getBeanNamesForType(Class)
|
||||
*/
|
||||
public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type) {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
@@ -200,6 +218,7 @@ public abstract class BeanFactoryUtils {
|
||||
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
||||
* @param type the type that beans must match
|
||||
* @return the array of matching bean names, or an empty array if none
|
||||
* @see ListableBeanFactory#getBeanNamesForType(Class, boolean, boolean)
|
||||
*/
|
||||
public static String[] beanNamesForTypeIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||
@@ -217,6 +236,35 @@ public abstract class BeanFactoryUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all bean names whose {@code Class} has the supplied {@link Annotation}
|
||||
* type, including those defined in ancestor factories, without creating any bean
|
||||
* instances yet. Will return unique names in case of overridden bean definitions.
|
||||
* @param lbf the bean factory
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the array of matching bean names, or an empty array if none
|
||||
* @since 5.0
|
||||
* @see ListableBeanFactory#getBeanNamesForAnnotation(Class)
|
||||
*/
|
||||
public static String[] beanNamesForAnnotationIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<? extends Annotation> annotationType) {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForAnnotation(annotationType);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForAnnotationIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), annotationType);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Retrieval of bean instances
|
||||
|
||||
/**
|
||||
* Return all beans of the given type or subtypes, also picking up beans defined in
|
||||
* ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
|
||||
@@ -233,6 +281,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @param type type of bean to match
|
||||
* @return the Map of matching bean instances, or an empty Map if none
|
||||
* @throws BeansException if a bean could not be created
|
||||
* @see ListableBeanFactory#getBeansOfType(Class)
|
||||
*/
|
||||
public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
|
||||
throws BeansException {
|
||||
@@ -245,9 +294,9 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
Map<String, T> parentResult = beansOfTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type);
|
||||
parentResult.forEach((beanName, beanType) -> {
|
||||
parentResult.forEach((beanName, beanInstance) -> {
|
||||
if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
result.put(beanName, beanType);
|
||||
result.put(beanName, beanInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -280,6 +329,7 @@ public abstract class BeanFactoryUtils {
|
||||
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
||||
* @return the Map of matching bean instances, or an empty Map if none
|
||||
* @throws BeansException if a bean could not be created
|
||||
* @see ListableBeanFactory#getBeansOfType(Class, boolean, boolean)
|
||||
*/
|
||||
public static <T> Map<String, T> beansOfTypeIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
|
||||
@@ -293,9 +343,9 @@ public abstract class BeanFactoryUtils {
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
Map<String, T> parentResult = beansOfTypeIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
|
||||
parentResult.forEach((beanName, beanType) -> {
|
||||
parentResult.forEach((beanName, beanInstance) -> {
|
||||
if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
|
||||
result.put(beanName, beanType);
|
||||
result.put(beanName, beanInstance);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -303,7 +353,6 @@ public abstract class BeanFactoryUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a single bean of the given type or subtypes, also picking up beans
|
||||
* defined in ancestor bean factories if the current bean factory is a
|
||||
@@ -325,6 +374,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see #beansOfTypeIncludingAncestors(ListableBeanFactory, Class)
|
||||
*/
|
||||
public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
|
||||
throws BeansException {
|
||||
@@ -333,31 +383,6 @@ public abstract class BeanFactoryUtils {
|
||||
return uniqueBean(type, beansOfType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all bean names whose {@code Class} has the supplied {@link Annotation}
|
||||
* type, including those defined in ancestor factories, without creating any bean
|
||||
* instances yet. Will return unique names in case of overridden bean definitions.
|
||||
* @param lbf the bean factory
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the array of matching bean names, or an empty array if none
|
||||
* @since 5.0
|
||||
*/
|
||||
public static String[] beanNamesForAnnotationIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<? extends Annotation> annotationType) {
|
||||
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
String[] result = lbf.getBeanNamesForAnnotation(annotationType);
|
||||
if (lbf instanceof HierarchicalBeanFactory) {
|
||||
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
|
||||
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
|
||||
String[] parentResult = beanNamesForAnnotationIncludingAncestors(
|
||||
(ListableBeanFactory) hbf.getParentBeanFactory(), annotationType);
|
||||
result = mergeNamesWithParent(result, parentResult, hbf);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single bean of the given type or subtypes, also picking up beans
|
||||
* defined in ancestor bean factories if the current bean factory is a
|
||||
@@ -386,6 +411,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see #beansOfTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
|
||||
*/
|
||||
public static <T> T beanOfTypeIncludingAncestors(
|
||||
ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
|
||||
@@ -410,6 +436,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see ListableBeanFactory#getBeansOfType(Class)
|
||||
*/
|
||||
public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException {
|
||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||
@@ -440,6 +467,7 @@ public abstract class BeanFactoryUtils {
|
||||
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see ListableBeanFactory#getBeansOfType(Class, boolean, boolean)
|
||||
*/
|
||||
public static <T> T beanOfType(
|
||||
ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,28 +17,29 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by beans that want to release resources
|
||||
* on destruction. A BeanFactory is supposed to invoke the destroy
|
||||
* method if it disposes a cached singleton. An application context
|
||||
* is supposed to dispose all of its singletons on close.
|
||||
* Interface to be implemented by beans that want to release resources on destruction.
|
||||
* A {@link BeanFactory} will invoke the destroy method on individual destruction of a
|
||||
* scoped bean. An {@link org.springframework.context.ApplicationContext} is supposed
|
||||
* to dispose all of its singletons on shutdown, driven by the application lifecycle.
|
||||
*
|
||||
* <p>An alternative to implementing DisposableBean is specifying a custom
|
||||
* destroy-method, for example in an XML bean definition.
|
||||
* For a list of all bean lifecycle methods, see the
|
||||
* {@link BeanFactory BeanFactory javadocs}.
|
||||
* <p>A Spring-managed bean may also implement Java's {@link AutoCloseable} interface
|
||||
* for the same purpose. An alternative to implementing an interface is specifying a
|
||||
* custom destroy method, for example in an XML bean definition. For a list of all
|
||||
* bean lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 12.08.2003
|
||||
* @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#close
|
||||
* @see InitializingBean
|
||||
* @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName()
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#close()
|
||||
*/
|
||||
public interface DisposableBean {
|
||||
|
||||
/**
|
||||
* Invoked by a BeanFactory on destruction of a singleton.
|
||||
* @throws Exception in case of shutdown errors.
|
||||
* Exceptions will get logged but not rethrown to allow
|
||||
* other beans to release their resources too.
|
||||
* Invoked by the containing {@code BeanFactory} on destruction of a bean.
|
||||
* @throws Exception in case of shutdown errors. Exceptions will get logged
|
||||
* but not rethrown to allow other beans to release their resources as well.
|
||||
*/
|
||||
void destroy() throws Exception;
|
||||
|
||||
|
||||
+17
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,32 +17,29 @@
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by beans that need to react once all their
|
||||
* properties have been set by a BeanFactory: for example, to perform custom
|
||||
* initialization, or merely to check that all mandatory properties have been set.
|
||||
* Interface to be implemented by beans that need to react once all their properties
|
||||
* have been set by a {@link BeanFactory}: e.g. to perform custom initialization,
|
||||
* or merely to check that all mandatory properties have been set.
|
||||
*
|
||||
* <p>An alternative to implementing InitializingBean is specifying a custom
|
||||
* init-method, for example in an XML bean definition.
|
||||
* For a list of all bean lifecycle methods, see the
|
||||
* {@link BeanFactory BeanFactory javadocs}.
|
||||
* <p>An alternative to implementing {@code InitializingBean} is specifying a custom
|
||||
* init method, for example in an XML bean definition. For a list of all bean
|
||||
* lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see BeanNameAware
|
||||
* @see BeanFactoryAware
|
||||
* @see BeanFactory
|
||||
* @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
|
||||
* @see org.springframework.context.ApplicationContextAware
|
||||
* @author Juergen Hoeller
|
||||
* @see DisposableBean
|
||||
* @see org.springframework.beans.factory.config.BeanDefinition#getPropertyValues()
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#getInitMethodName()
|
||||
*/
|
||||
public interface InitializingBean {
|
||||
|
||||
/**
|
||||
* Invoked by a BeanFactory after it has set all bean properties supplied
|
||||
* (and satisfied BeanFactoryAware and ApplicationContextAware).
|
||||
* <p>This method allows the bean instance to perform initialization only
|
||||
* possible when all bean properties have been set and to throw an
|
||||
* exception in the event of misconfiguration.
|
||||
* @throws Exception in the event of misconfiguration (such
|
||||
* as failure to set an essential property) or if initialization fails.
|
||||
* Invoked by the containing {@code BeanFactory} after it has set all bean properties
|
||||
* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
|
||||
* <p>This method allows the bean instance to perform validation of its overall
|
||||
* configuration and final initialization when all bean properties have been set.
|
||||
* @throws Exception in the event of misconfiguration (such as failure to set an
|
||||
* essential property) or if initialization fails for any other reason
|
||||
*/
|
||||
void afterPropertiesSet() throws Exception;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -29,6 +29,8 @@ import org.springframework.util.ObjectUtils;
|
||||
/**
|
||||
* A simple descriptor for an injection point, pointing to a method/constructor
|
||||
* parameter or a field. Exposed by {@link UnsatisfiedDependencyException}.
|
||||
* Also available as an argument for factory methods, reacting to the
|
||||
* requesting injection point for building a customized bean instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3
|
||||
|
||||
+6
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -244,7 +244,9 @@ public interface ListableBeanFactory extends BeanFactory {
|
||||
|
||||
/**
|
||||
* Find all names of beans whose {@code Class} has the supplied {@link Annotation}
|
||||
* type, without creating any bean instances yet.
|
||||
* type, without creating corresponding bean instances yet.
|
||||
* <p>Note that this method considers objects created by FactoryBeans, which means
|
||||
* that FactoryBeans will get initialized in order to determine their object type.
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the names of all matching beans
|
||||
* @since 4.0
|
||||
@@ -254,6 +256,8 @@ public interface ListableBeanFactory extends BeanFactory {
|
||||
/**
|
||||
* Find all beans whose {@code Class} has the supplied {@link Annotation} type,
|
||||
* returning a Map of bean names with corresponding bean instances.
|
||||
* <p>Note that this method considers objects created by FactoryBeans, which means
|
||||
* that FactoryBeans will get initialized in order to determine their object type.
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return a Map with the matching beans, containing the bean names as
|
||||
* keys and the corresponding bean instances as values
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti
|
||||
public NoUniqueBeanDefinitionException(Class<?> type, Collection<String> beanNamesFound) {
|
||||
super(type, "expected single matching bean but found " + beanNamesFound.size() + ": " +
|
||||
StringUtils.collectionToCommaDelimitedString(beanNamesFound));
|
||||
this.numberOfBeansFound = beanNamesFound.size();
|
||||
this.numberOfBeansFound = beanNamesFound.size();
|
||||
this.beanNamesFound = beanNamesFound;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionExcepti
|
||||
public NoUniqueBeanDefinitionException(ResolvableType type, Collection<String> beanNamesFound) {
|
||||
super(type, "expected single matching bean but found " + beanNamesFound.size() + ": " +
|
||||
StringUtils.collectionToCommaDelimitedString(beanNamesFound));
|
||||
this.numberOfBeansFound = beanNamesFound.size();
|
||||
this.numberOfBeansFound = beanNamesFound.size();
|
||||
this.beanNamesFound = beanNamesFound;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ import org.springframework.lang.Nullable;
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3
|
||||
* @param <T> the object type
|
||||
* @see BeanFactory#getBeanProvider
|
||||
* @see org.springframework.beans.factory.annotation.Autowired
|
||||
*/
|
||||
public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
||||
|
||||
@@ -137,8 +139,8 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} over resolved object instances.
|
||||
* <p>The default implementation delegates to {@link #stream()}.
|
||||
* Return an {@link Iterator} over all matching object instances,
|
||||
* without specific ordering guarantees (but typically in registration order).
|
||||
* @since 5.1
|
||||
* @see #stream()
|
||||
*/
|
||||
@@ -148,15 +150,30 @@ public interface ObjectProvider<T> extends ObjectFactory<T>, Iterable<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a sequential {@link Stream} over resolved object instances.
|
||||
* <p>The default implementation returns a stream of one element or an
|
||||
* empty stream if not available, resolved via {@link #getIfAvailable()}.
|
||||
* Return a sequential {@link Stream} over all matching object instances,
|
||||
* without specific ordering guarantees (but typically in registration order).
|
||||
* @since 5.1
|
||||
* @see #iterator()
|
||||
* @see #orderedStream()
|
||||
*/
|
||||
default Stream<T> stream() {
|
||||
T instance = getIfAvailable();
|
||||
return (instance != null ? Stream.of(instance) : Stream.empty());
|
||||
throw new UnsupportedOperationException("Multi element access not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a sequential {@link Stream} over all matching object instances,
|
||||
* pre-ordered according to the factory's common order comparator.
|
||||
* <p>In a standard Spring application context, this will be ordered
|
||||
* according to {@link org.springframework.core.Ordered} conventions,
|
||||
* and in case of annotation-based configuration also considering the
|
||||
* {@link org.springframework.core.annotation.Order} annotation,
|
||||
* analogous to multi-element injection points of list/array type.
|
||||
* @since 5.1
|
||||
* @see #stream()
|
||||
* @see org.springframework.core.OrderComparator
|
||||
*/
|
||||
default Stream<T> orderedStream() {
|
||||
throw new UnsupportedOperationException("Ordered element access not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,24 +46,23 @@ public class AnnotationBeanWiringInfoResolver implements BeanWiringInfoResolver
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the BeanWiringInfo for the given Configurable annotation.
|
||||
* Build the {@link BeanWiringInfo} for the given {@link Configurable} annotation.
|
||||
* @param beanInstance the bean instance
|
||||
* @param annotation the Configurable annotation found on the bean class
|
||||
* @return the resolved BeanWiringInfo
|
||||
*/
|
||||
protected BeanWiringInfo buildWiringInfo(Object beanInstance, Configurable annotation) {
|
||||
if (!Autowire.NO.equals(annotation.autowire())) {
|
||||
// Autowiring by name or by type
|
||||
return new BeanWiringInfo(annotation.autowire().value(), annotation.dependencyCheck());
|
||||
}
|
||||
else if (!"".equals(annotation.value())) {
|
||||
// Explicitly specified bean name for bean definition to take property values from
|
||||
return new BeanWiringInfo(annotation.value(), false);
|
||||
}
|
||||
else {
|
||||
if (!"".equals(annotation.value())) {
|
||||
// explicitly specified bean name
|
||||
return new BeanWiringInfo(annotation.value(), false);
|
||||
}
|
||||
else {
|
||||
// default bean name
|
||||
return new BeanWiringInfo(getDefaultBeanName(beanInstance), true);
|
||||
}
|
||||
// Default bean name for bean definition to take property values from
|
||||
return new BeanWiringInfo(getDefaultBeanName(beanInstance), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,15 +23,22 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a constructor, field, setter method or config method as to be autowired
|
||||
* by Spring's dependency injection facilities.
|
||||
* 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.
|
||||
*
|
||||
* <p>Only one constructor (at max) of any given bean class may carry this annotation,
|
||||
* indicating the constructor to autowire when used as a Spring bean. Such a
|
||||
* constructor does not have to be public.
|
||||
* <p>Only one constructor (at max) of any given bean class may declare this annotation
|
||||
* with the 'required' parameter set to {@code true}, indicating <i>the</i> constructor
|
||||
* to autowire when used as a Spring bean. If multiple <i>non-required</i> constructors
|
||||
* declare the annotation, they will be considered as candidates for autowiring.
|
||||
* The constructor with the greatest number of dependencies that can be satisfied by
|
||||
* matching beans in the Spring container will be chosen. If none of the candidates
|
||||
* can be satisfied, then a primary/default constructor (if present) will be used.
|
||||
* If a class only declares a single constructor to begin with, it will always be used,
|
||||
* even if not annotated. An annotated constructor does not have to be public.
|
||||
*
|
||||
* <p>Fields are injected right after construction of a bean, before any config
|
||||
* methods are invoked. Such a config field does not have to be public.
|
||||
* <p>Fields are injected right after construction of a bean, before any config methods
|
||||
* are invoked. Such a config field does not have to be public.
|
||||
*
|
||||
* <p>Config methods may have an arbitrary name and any number of arguments; each of
|
||||
* those arguments will be autowired with a matching bean in the Spring container.
|
||||
|
||||
+42
-38
@@ -74,15 +74,15 @@ import org.springframework.util.StringUtils;
|
||||
* <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
|
||||
* if available, as a direct alternative to Spring's own {@code @Autowired}.
|
||||
*
|
||||
* <p>Only one constructor (at max) of any given bean class may carry this
|
||||
* annotation with the 'required' parameter set to {@code true},
|
||||
* indicating <i>the</i> constructor to autowire when used as a Spring bean.
|
||||
* If multiple <i>non-required</i> constructors carry the annotation, they
|
||||
* will be considered as candidates for autowiring. The constructor with
|
||||
* the greatest number of dependencies that can be satisfied by matching
|
||||
* beans in the Spring container will be chosen. If none of the candidates
|
||||
* can be satisfied, then a default constructor (if present) will be used.
|
||||
* An annotated constructor does not have to be public.
|
||||
* <p>Only one constructor (at max) of any given bean class may declare this annotation
|
||||
* with the 'required' parameter set to {@code true}, indicating <i>the</i> constructor
|
||||
* to autowire when used as a Spring bean. If multiple <i>non-required</i> constructors
|
||||
* declare the annotation, they will be considered as candidates for autowiring.
|
||||
* The constructor with the greatest number of dependencies that can be satisfied by
|
||||
* matching beans in the Spring container will be chosen. If none of the candidates
|
||||
* can be satisfied, then a primary/default constructor (if present) will be used.
|
||||
* If a class only declares a single constructor to begin with, it will always be used,
|
||||
* even if not annotated. An annotated constructor does not have to be public.
|
||||
*
|
||||
* <p>Fields are injected right after construction of a bean, before any
|
||||
* config methods are invoked. Such a config field does not have to be public.
|
||||
@@ -120,7 +120,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>();
|
||||
private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);
|
||||
|
||||
private String requiredParameterName = "required";
|
||||
|
||||
@@ -161,11 +161,11 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
/**
|
||||
* Set the 'autowired' annotation type, to be used on constructors, fields,
|
||||
* setter methods and arbitrary config methods.
|
||||
* <p>The default autowired annotation type is the Spring-provided
|
||||
* {@link Autowired} annotation, as well as {@link Value}.
|
||||
* <p>The default autowired annotation type is the Spring-provided {@link Autowired}
|
||||
* annotation, as well as {@link Value}.
|
||||
* <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.
|
||||
* (non-Spring-specific) annotation type to indicate that a member is supposed
|
||||
* to be autowired.
|
||||
*/
|
||||
public void setAutowiredAnnotationType(Class<? extends Annotation> autowiredAnnotationType) {
|
||||
Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null");
|
||||
@@ -176,11 +176,11 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
/**
|
||||
* Set the 'autowired' annotation types, to be used on constructors, fields,
|
||||
* setter methods and arbitrary config methods.
|
||||
* <p>The default autowired annotation type is the Spring-provided
|
||||
* {@link Autowired} annotation, as well as {@link Value}.
|
||||
* <p>The default autowired annotation type is the Spring-provided {@link Autowired}
|
||||
* annotation, as well as {@link Value}.
|
||||
* <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.
|
||||
* (non-Spring-specific) annotation types to indicate that a member is supposed
|
||||
* to be autowired.
|
||||
*/
|
||||
public void setAutowiredAnnotationTypes(Set<Class<? extends Annotation>> autowiredAnnotationTypes) {
|
||||
Assert.notEmpty(autowiredAnnotationTypes, "'autowiredAnnotationTypes' must not be empty");
|
||||
@@ -189,8 +189,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of a parameter of the annotation that specifies
|
||||
* whether it is required.
|
||||
* Set the name of a parameter of the annotation that specifies whether it is required.
|
||||
* @see #setRequiredParameterValue(boolean)
|
||||
*/
|
||||
public void setRequiredParameterName(String requiredParameterName) {
|
||||
@@ -199,9 +198,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
|
||||
/**
|
||||
* Set the boolean value that marks a dependency as required
|
||||
* <p>For example if using 'required=true' (the default),
|
||||
* this value should be {@code true}; but if using
|
||||
* 'optional=false', this value should be {@code false}.
|
||||
* <p>For example if using 'required=true' (the default), this value should be
|
||||
* {@code true}; but if using 'optional=false', this value should be {@code false}.
|
||||
* @see #setRequiredParameterName(String)
|
||||
*/
|
||||
public void setRequiredParameterValue(boolean requiredParameterValue) {
|
||||
@@ -233,6 +231,12 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
metadata.checkConfigMembers(beanDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBeanDefinition(String beanName) {
|
||||
this.lookupMethodsChecked.remove(beanName);
|
||||
this.injectionMetadataCache.remove(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
|
||||
@@ -252,7 +256,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Cannot apply @Lookup to beans without corresponding bean definition");
|
||||
"Cannot apply @Lookup to beans without corresponding bean definition");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -334,8 +338,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
if (defaultConstructor != null) {
|
||||
candidates.add(defaultConstructor);
|
||||
}
|
||||
else if (candidates.size() == 1 && logger.isWarnEnabled()) {
|
||||
logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
|
||||
else if (candidates.size() == 1 && logger.isInfoEnabled()) {
|
||||
logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
|
||||
"': single autowire-marked constructor flagged as optional - " +
|
||||
"this constructor is effectively required since there is no " +
|
||||
"default constructor to fall back to: " + candidates.get(0));
|
||||
@@ -346,8 +350,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
|
||||
candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
|
||||
}
|
||||
else if (nonSyntheticConstructors == 2 && primaryConstructor != null
|
||||
&& defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
|
||||
else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
|
||||
defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
|
||||
candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
|
||||
}
|
||||
else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
|
||||
@@ -439,8 +443,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
AnnotationAttributes ann = findAutowiredAnnotation(field);
|
||||
if (ann != null) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Autowired annotation is not supported on static fields: " + field);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Autowired annotation is not supported on static fields: " + field);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -457,14 +461,14 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
|
||||
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Autowired annotation is not supported on static methods: " + method);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Autowired annotation is not supported on static methods: " + method);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (method.getParameterCount() == 0) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Autowired annotation should only be used on methods with parameters: " +
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Autowired annotation should only be used on methods with parameters: " +
|
||||
method);
|
||||
}
|
||||
}
|
||||
@@ -484,7 +488,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
|
||||
@Nullable
|
||||
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
|
||||
if (ao.getAnnotations().length > 0) {
|
||||
if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
|
||||
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
|
||||
if (attributes != null) {
|
||||
@@ -531,8 +535,8 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
if (this.beanFactory != null && this.beanFactory.containsBean(autowiredBeanName)) {
|
||||
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Autowiring by type from bean name '" + beanName +
|
||||
"' to bean named '" + autowiredBeanName + "'");
|
||||
}
|
||||
}
|
||||
@@ -703,7 +707,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
method.invoke(bean, arguments);
|
||||
}
|
||||
catch (InvocationTargetException ex){
|
||||
catch (InvocationTargetException ex) {
|
||||
throw ex.getTargetException();
|
||||
}
|
||||
}
|
||||
|
||||
+41
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,16 +17,18 @@
|
||||
package org.springframework.beans.factory.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -35,8 +37,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Convenience methods performing bean lookups related to annotations, for example
|
||||
* Spring's {@link Qualifier @Qualifier} annotation.
|
||||
* Convenience methods performing bean lookups related to Spring-specific annotations,
|
||||
* for example Spring's {@link Qualifier @Qualifier} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -45,27 +47,52 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public abstract class BeanFactoryAnnotationUtils {
|
||||
|
||||
/**
|
||||
* Retrieve all bean 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)
|
||||
* @param beanType the type of beans to retrieve
|
||||
* @param qualifier the qualifier for selecting among all type matches
|
||||
* @return the matching beans of type {@code T}
|
||||
* @throws BeansException if any of the matching beans could not be created
|
||||
* @since 5.1.1
|
||||
* @see BeanFactoryUtils#beansOfTypeIncludingAncestors(ListableBeanFactory, Class)
|
||||
*/
|
||||
public static <T> Map<String, T> qualifiedBeansOfType(
|
||||
ListableBeanFactory beanFactory, Class<T> beanType, String qualifier) throws BeansException {
|
||||
|
||||
String[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, beanType);
|
||||
Map<String, T> result = new LinkedHashMap<>(4);
|
||||
for (String beanName : candidateBeans) {
|
||||
if (isQualifierMatch(qualifier::equals, beanName, beanFactory)) {
|
||||
result.put(beanName, beanFactory.getBean(beanName, beanType));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a bean 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 BeanFactory to get the target bean from
|
||||
* @param beanFactory the factory to get the target bean from (also searching ancestors)
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
* @throws NoUniqueBeanDefinitionException if multiple matching beans of type {@code T} found
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @see BeanFactory#getBean(Class)
|
||||
* @see BeanFactoryUtils#beanOfTypeIncludingAncestors(ListableBeanFactory, Class)
|
||||
*/
|
||||
public static <T> T qualifiedBeanOfType(BeanFactory beanFactory, Class<T> beanType, String qualifier)
|
||||
throws BeansException {
|
||||
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
if (beanFactory instanceof ListableBeanFactory) {
|
||||
// Full qualifier matching supported.
|
||||
return qualifiedBeanOfType((ConfigurableListableBeanFactory) beanFactory, beanType, qualifier);
|
||||
return qualifiedBeanOfType((ListableBeanFactory) beanFactory, beanType, qualifier);
|
||||
}
|
||||
else if (beanFactory.containsBean(qualifier)) {
|
||||
// Fallback: target bean at least found by bean name.
|
||||
@@ -82,12 +109,12 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
/**
|
||||
* Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a qualifier
|
||||
* (e.g. {@code <qualifier>} or {@code @Qualifier}) matching the given qualifier).
|
||||
* @param bf the BeanFactory to get the target bean from
|
||||
* @param bf the factory to get the target bean from
|
||||
* @param beanType the type of bean to retrieve
|
||||
* @param qualifier the qualifier for selecting between multiple bean matches
|
||||
* @return the matching bean of type {@code T} (never {@code null})
|
||||
*/
|
||||
private static <T> T qualifiedBeanOfType(ConfigurableListableBeanFactory bf, Class<T> beanType, String qualifier) {
|
||||
private static <T> T qualifiedBeanOfType(ListableBeanFactory bf, Class<T> beanType, String qualifier) {
|
||||
String[] candidateBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(bf, beanType);
|
||||
String matchingBean = null;
|
||||
for (String beanName : candidateBeans) {
|
||||
@@ -115,14 +142,14 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
* Check whether the named bean declares a qualifier of the given name.
|
||||
* @param qualifier the qualifier to match
|
||||
* @param beanName the name of the candidate bean
|
||||
* @param beanFactory the {@code BeanFactory} from which to retrieve the named bean
|
||||
* @param beanFactory the factory from which to retrieve the named bean
|
||||
* @return {@code true} if either the bean definition (in the XML case)
|
||||
* or the bean's factory method (in the {@code @Bean} case) defines a matching
|
||||
* qualifier value (through {@code <qualifier>} or {@code @Qualifier})
|
||||
* @since 5.0
|
||||
*/
|
||||
public static boolean isQualifierMatch(Predicate<String> qualifier, String beanName,
|
||||
@Nullable BeanFactory beanFactory) {
|
||||
public static boolean isQualifierMatch(
|
||||
Predicate<String> qualifier, String beanName, @Nullable BeanFactory beanFactory) {
|
||||
|
||||
// Try quick bean name or alias match first...
|
||||
if (qualifier.test(beanName)) {
|
||||
@@ -135,6 +162,7 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
}
|
||||
}
|
||||
try {
|
||||
Class<?> beanType = beanFactory.getType(beanName);
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
BeanDefinition bd = ((ConfigurableBeanFactory) beanFactory).getMergedBeanDefinition(beanName);
|
||||
// Explicit qualifier metadata on bean definition? (typically in XML definition)
|
||||
@@ -160,7 +188,6 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||
}
|
||||
}
|
||||
// Corresponding qualifier on bean implementation class? (for custom user types)
|
||||
Class<?> beanType = beanFactory.getType(beanName);
|
||||
if (beanType != null) {
|
||||
Qualifier targetAnnotation = AnnotationUtils.getAnnotation(beanType, Qualifier.class);
|
||||
if (targetAnnotation != null) {
|
||||
|
||||
+12
-15
@@ -196,7 +196,6 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
}
|
||||
|
||||
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
|
||||
final boolean debug = logger.isDebugEnabled();
|
||||
List<LifecycleElement> initMethods = new ArrayList<>();
|
||||
List<LifecycleElement> destroyMethods = new ArrayList<>();
|
||||
Class<?> targetClass = clazz;
|
||||
@@ -209,14 +208,14 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
|
||||
LifecycleElement element = new LifecycleElement(method);
|
||||
currInitMethods.add(element);
|
||||
if (debug) {
|
||||
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
}
|
||||
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
|
||||
currDestroyMethods.add(new LifecycleElement(method));
|
||||
if (debug) {
|
||||
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -276,8 +275,8 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
|
||||
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
|
||||
checkedInitMethods.add(element);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,8 +286,8 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
|
||||
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
|
||||
checkedDestroyMethods.add(element);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,10 +300,9 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
Collection<LifecycleElement> initMethodsToIterate =
|
||||
(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
|
||||
if (!initMethodsToIterate.isEmpty()) {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (LifecycleElement element : initMethodsToIterate) {
|
||||
if (debug) {
|
||||
logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
|
||||
}
|
||||
element.invoke(target);
|
||||
}
|
||||
@@ -316,10 +314,9 @@ public class InitDestroyAnnotationBeanPostProcessor
|
||||
Collection<LifecycleElement> destroyMethodsToUse =
|
||||
(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
|
||||
if (!destroyMethodsToUse.isEmpty()) {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (LifecycleElement element : destroyMethodsToUse) {
|
||||
if (debug) {
|
||||
logger.debug("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking destroy method on bean '" + beanName + "': " + element.getMethod());
|
||||
}
|
||||
element.invoke(target);
|
||||
}
|
||||
|
||||
+4
-5
@@ -70,8 +70,8 @@ public class InjectionMetadata {
|
||||
if (!beanDefinition.isExternallyManagedConfigMember(member)) {
|
||||
beanDefinition.registerExternallyManagedConfigMember(member);
|
||||
checkedElements.add(element);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registered injected element on class [" + this.targetClass.getName() + "]: " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,10 +83,9 @@ public class InjectionMetadata {
|
||||
Collection<InjectedElement> elementsToIterate =
|
||||
(checkedElements != null ? checkedElements : this.injectedElements);
|
||||
if (!elementsToIterate.isEmpty()) {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (InjectedElement element : elementsToIterate) {
|
||||
if (debug) {
|
||||
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
|
||||
}
|
||||
element.inject(target, beanName, pvs);
|
||||
}
|
||||
|
||||
+22
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -325,6 +325,21 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
return (autowired == null || autowired.required());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given dependency declares a qualifier annotation.
|
||||
* @see #isQualifier(Class)
|
||||
* @see Qualifier
|
||||
*/
|
||||
@Override
|
||||
public boolean hasQualifier(DependencyDescriptor descriptor) {
|
||||
for (Annotation ann : descriptor.getAnnotations()) {
|
||||
if (isQualifier(ann.annotationType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given dependency declares a value annotation.
|
||||
* @see Value
|
||||
@@ -347,10 +362,12 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
*/
|
||||
@Nullable
|
||||
protected Object findValue(Annotation[] annotationsToSearch) {
|
||||
AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
|
||||
if (attr != null) {
|
||||
return extractValue(attr);
|
||||
if (annotationsToSearch.length > 0) { // qualifier annotations have to be local
|
||||
AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
|
||||
if (attr != null) {
|
||||
return extractValue(attr);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* 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.
|
||||
@@ -30,7 +30,7 @@ import java.lang.annotation.Target;
|
||||
* for dynamic resolution of handler method parameters, e.g. in Spring MVC.
|
||||
*
|
||||
* <p>A common use case is to assign default field values using
|
||||
* "#{systemProperties.myProp}" style expressions.
|
||||
* {@code #{systemProperties.myProp}} style expressions.
|
||||
*
|
||||
* <p>Note that actual processing of the {@code @Value} annotation is performed
|
||||
* by a {@link org.springframework.beans.factory.config.BeanPostProcessor
|
||||
@@ -55,7 +55,7 @@ import java.lang.annotation.Target;
|
||||
public @interface Value {
|
||||
|
||||
/**
|
||||
* The actual value expression: e.g. "#{systemProperties.myProp}".
|
||||
* The actual value expression: for example {@code #{systemProperties.myProp}}.
|
||||
*/
|
||||
String value();
|
||||
|
||||
|
||||
+1
-1
@@ -161,7 +161,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine an 'eager singleton' instance, exposed in case of a
|
||||
* Determine an 'early singleton' instance, exposed in case of a
|
||||
* circular reference. Not called in a non-circular scenario.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
+46
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -107,6 +107,18 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
@Deprecated
|
||||
int AUTOWIRE_AUTODETECT = 4;
|
||||
|
||||
/**
|
||||
* Suffix for the "original instance" convention when initializing an existing
|
||||
* bean instance: to be appended to the fully-qualified bean class name,
|
||||
* e.g. "com.mypackage.MyClass.ORIGINAL", in order to enforce the given instance
|
||||
* to be returned, i.e. no proxies etc.
|
||||
* @since 5.1
|
||||
* @see #initializeBean(Object, String)
|
||||
* @see #applyBeanPostProcessorsBeforeInitialization(Object, String)
|
||||
* @see #applyBeanPostProcessorsAfterInitialization(Object, String)
|
||||
*/
|
||||
String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Typical methods for creating and populating external bean instances
|
||||
@@ -264,9 +276,12 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* for callbacks but not checked against the registered bean definitions.
|
||||
* @param existingBean the existing bean instance
|
||||
* @param beanName the name of the bean, to be passed to it if necessary
|
||||
* (only passed to {@link BeanPostProcessor BeanPostProcessors})
|
||||
* (only passed to {@link BeanPostProcessor BeanPostProcessors};
|
||||
* can follow the {@link #ORIGINAL_INSTANCE_SUFFIX} convention in order to
|
||||
* enforce the given instance to be returned, i.e. no proxies etc)
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @throws BeansException if the initialization failed
|
||||
* @see #ORIGINAL_INSTANCE_SUFFIX
|
||||
*/
|
||||
Object initializeBean(Object existingBean, String beanName) throws BeansException;
|
||||
|
||||
@@ -274,11 +289,15 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* Apply {@link BeanPostProcessor BeanPostProcessors} to the given existing bean
|
||||
* instance, invoking their {@code postProcessBeforeInitialization} methods.
|
||||
* The returned bean instance may be a wrapper around the original.
|
||||
* @param existingBean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @param existingBean the existing bean instance
|
||||
* @param beanName the name of the bean, to be passed to it if necessary
|
||||
* (only passed to {@link BeanPostProcessor BeanPostProcessors};
|
||||
* can follow the {@link #ORIGINAL_INSTANCE_SUFFIX} convention in order to
|
||||
* enforce the given instance to be returned, i.e. no proxies etc)
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see BeanPostProcessor#postProcessBeforeInitialization
|
||||
* @see #ORIGINAL_INSTANCE_SUFFIX
|
||||
*/
|
||||
Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
|
||||
throws BeansException;
|
||||
@@ -287,11 +306,15 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* Apply {@link BeanPostProcessor BeanPostProcessors} to the given existing bean
|
||||
* instance, invoking their {@code postProcessAfterInitialization} methods.
|
||||
* The returned bean instance may be a wrapper around the original.
|
||||
* @param existingBean the new bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @param existingBean the existing bean instance
|
||||
* @param beanName the name of the bean, to be passed to it if necessary
|
||||
* (only passed to {@link BeanPostProcessor BeanPostProcessors};
|
||||
* can follow the {@link #ORIGINAL_INSTANCE_SUFFIX} convention in order to
|
||||
* enforce the given instance to be returned, i.e. no proxies etc)
|
||||
* @return the bean instance to use, either the original or a wrapped one
|
||||
* @throws BeansException if any post-processing failed
|
||||
* @see BeanPostProcessor#postProcessAfterInitialization
|
||||
* @see #ORIGINAL_INSTANCE_SUFFIX
|
||||
*/
|
||||
Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
|
||||
throws BeansException;
|
||||
@@ -316,8 +339,7 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
* including its bean name.
|
||||
* <p>This is effectively a variant of {@link #getBean(Class)} which preserves the
|
||||
* bean name of the matching instance.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass.
|
||||
* {@code null} is disallowed.
|
||||
* @param requiredType type the bean must match; can be an interface or superclass
|
||||
* @return the bean name plus bean instance
|
||||
* @throws NoSuchBeanDefinitionException if no matching bean was found
|
||||
* @throws NoUniqueBeanDefinitionException if more than one matching bean was found
|
||||
@@ -327,6 +349,22 @@ public interface AutowireCapableBeanFactory extends BeanFactory {
|
||||
*/
|
||||
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve a bean instance for the given bean name, providing a dependency descriptor
|
||||
* for exposure to target factory methods.
|
||||
* <p>This is effectively a variant of {@link #getBean(String, Class)} which supports
|
||||
* factory methods with an {@link org.springframework.beans.factory.InjectionPoint}
|
||||
* argument.
|
||||
* @param name the name of the bean to look up
|
||||
* @param descriptor the dependency descriptor for the requesting injection point
|
||||
* @return the corresponding bean instance
|
||||
* @throws NoSuchBeanDefinitionException if there is no bean with the specified name
|
||||
* @throws BeansException if the bean could not be created
|
||||
* @since 5.1.5
|
||||
* @see #getBean(String, Class)
|
||||
*/
|
||||
Object resolveBeanByName(String name, DependencyDescriptor descriptor) throws BeansException;
|
||||
|
||||
/**
|
||||
* Resolve the specified dependency against the beans defined in this factory.
|
||||
* @param descriptor the descriptor for the dependency (field/method/constructor)
|
||||
|
||||
+60
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -242,6 +242,65 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
|
||||
return !getPropertyValues().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the initializer method.
|
||||
* @since 5.1
|
||||
*/
|
||||
void setInitMethodName(@Nullable String initMethodName);
|
||||
|
||||
/**
|
||||
* Return the name of the initializer method.
|
||||
* @since 5.1
|
||||
*/
|
||||
@Nullable
|
||||
String getInitMethodName();
|
||||
|
||||
/**
|
||||
* Set the name of the destroy method.
|
||||
* @since 5.1
|
||||
*/
|
||||
void setDestroyMethodName(@Nullable String destroyMethodName);
|
||||
|
||||
/**
|
||||
* Return the name of the destroy method.
|
||||
* @since 5.1
|
||||
*/
|
||||
@Nullable
|
||||
String getDestroyMethodName();
|
||||
|
||||
/**
|
||||
* Set the role hint for this {@code BeanDefinition}. The role hint
|
||||
* provides the frameworks as well as tools with an indication of
|
||||
* the role and importance of a particular {@code BeanDefinition}.
|
||||
* @since 5.1
|
||||
* @see #ROLE_APPLICATION
|
||||
* @see #ROLE_SUPPORT
|
||||
* @see #ROLE_INFRASTRUCTURE
|
||||
*/
|
||||
void setRole(int role);
|
||||
|
||||
/**
|
||||
* Get the role hint for this {@code BeanDefinition}. The role hint
|
||||
* provides the frameworks as well as tools with an indication of
|
||||
* the role and importance of a particular {@code BeanDefinition}.
|
||||
* @see #ROLE_APPLICATION
|
||||
* @see #ROLE_SUPPORT
|
||||
* @see #ROLE_INFRASTRUCTURE
|
||||
*/
|
||||
int getRole();
|
||||
|
||||
/**
|
||||
* Set a human-readable description of this bean definition.
|
||||
* @since 5.1
|
||||
*/
|
||||
void setDescription(@Nullable String description);
|
||||
|
||||
/**
|
||||
* Return a human-readable description of this bean definition.
|
||||
*/
|
||||
@Nullable
|
||||
String getDescription();
|
||||
|
||||
|
||||
// Read-only attributes
|
||||
|
||||
@@ -265,22 +324,6 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
|
||||
*/
|
||||
boolean isAbstract();
|
||||
|
||||
/**
|
||||
* Get the role hint for this {@code BeanDefinition}. The role hint
|
||||
* provides the frameworks as well as tools with an indication of
|
||||
* the role and importance of a particular {@code BeanDefinition}.
|
||||
* @see #ROLE_APPLICATION
|
||||
* @see #ROLE_SUPPORT
|
||||
* @see #ROLE_INFRASTRUCTURE
|
||||
*/
|
||||
int getRole();
|
||||
|
||||
/**
|
||||
* Return a human-readable description of this bean definition.
|
||||
*/
|
||||
@Nullable
|
||||
String getDescription();
|
||||
|
||||
/**
|
||||
* Return a description of the resource that this bean definition
|
||||
* came from (for the purpose of showing context in case of errors).
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,7 +59,7 @@ public class BeanExpressionContext {
|
||||
if (this.beanFactory.containsBean(key)) {
|
||||
return this.beanFactory.getBean(key);
|
||||
}
|
||||
else if (this.scope != null){
|
||||
else if (this.scope != null) {
|
||||
return this.scope.resolveContextualObject(key);
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public class ConstructorArgumentValues {
|
||||
|
||||
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<>(0);
|
||||
private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<>();
|
||||
|
||||
private final List<ValueHolder> genericArgumentValues = new ArrayList<>();
|
||||
|
||||
|
||||
+22
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -38,6 +38,7 @@ import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -77,6 +78,9 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
@Nullable
|
||||
private transient volatile ResolvableType resolvableType;
|
||||
|
||||
@Nullable
|
||||
private transient volatile TypeDescriptor typeDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new descriptor for a method or constructor parameter.
|
||||
@@ -199,23 +203,6 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
return this.eager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this descriptor allows for stream-style access to
|
||||
* result instances.
|
||||
* <p>By default, dependencies are strictly resolved to the declaration of
|
||||
* the injection point and therefore only resolve multiple entries if the
|
||||
* injection point is declared as an array, collection or map. This is
|
||||
* indicated by returning {@code false} here.
|
||||
* <p>Overriding this method to return {@code true} indicates that the
|
||||
* injection point declares the bean type but the resolution is meant to
|
||||
* end up in a {@link java.util.stream.Stream} for the declared bean type,
|
||||
* with the caller handling the multi-instance case for the injection point.
|
||||
* @since 5.1
|
||||
*/
|
||||
public boolean isStreamAccess() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the specified not-unique scenario: by default,
|
||||
* throwing a {@link NoUniqueBeanDefinitionException}.
|
||||
@@ -318,7 +305,7 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a ResolvableType object for the wrapped parameter/field.
|
||||
* Build a {@link ResolvableType} object for the wrapped parameter/field.
|
||||
* @since 4.0
|
||||
*/
|
||||
public ResolvableType getResolvableType() {
|
||||
@@ -332,10 +319,25 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
|
||||
return resolvableType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link TypeDescriptor} object for the wrapped parameter/field.
|
||||
* @since 5.1.4
|
||||
*/
|
||||
public TypeDescriptor getTypeDescriptor() {
|
||||
TypeDescriptor typeDescriptor = this.typeDescriptor;
|
||||
if (typeDescriptor == null) {
|
||||
typeDescriptor = (this.field != null ?
|
||||
new TypeDescriptor(getResolvableType(), getDependencyType(), getAnnotations()) :
|
||||
new TypeDescriptor(obtainMethodParameter()));
|
||||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
return typeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a fallback match is allowed.
|
||||
* <p>This is {@code false} by default but may be overridden to return {@code true} in order
|
||||
* to suggest to a {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
|
||||
* to suggest to an {@link org.springframework.beans.factory.support.AutowireCandidateResolver}
|
||||
* that a fallback match is acceptable as well.
|
||||
* @since 4.0
|
||||
*/
|
||||
|
||||
+11
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,32 +30,25 @@ import org.springframework.beans.BeansException;
|
||||
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
|
||||
|
||||
/**
|
||||
* Apply this BeanPostProcessor to the given bean instance before
|
||||
* its destruction. Can invoke custom destruction callbacks.
|
||||
* <p>Like DisposableBean's {@code destroy} and a custom destroy method,
|
||||
* this callback just applies to singleton beans in the factory (including
|
||||
* inner beans).
|
||||
* Apply this BeanPostProcessor to the given bean instance before its
|
||||
* destruction, e.g. invoking custom destruction callbacks.
|
||||
* <p>Like DisposableBean's {@code destroy} and a custom destroy method, this
|
||||
* callback will only apply to beans which the container fully manages the
|
||||
* lifecycle for. This is usually the case for singletons and scoped beans.
|
||||
* @param bean the bean instance to be destroyed
|
||||
* @param beanName the name of the bean
|
||||
* @throws org.springframework.beans.BeansException in case of errors
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
* @see org.springframework.beans.factory.support.AbstractBeanDefinition#setDestroyMethodName(String)
|
||||
*/
|
||||
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
|
||||
|
||||
/**
|
||||
* Determine whether the given bean instance requires destruction by this
|
||||
* post-processor.
|
||||
* <p><b>NOTE:</b> Even as a late addition, this method has been introduced on
|
||||
* {@code DestructionAwareBeanPostProcessor} itself instead of on a SmartDABPP
|
||||
* subinterface. This allows existing {@code DestructionAwareBeanPostProcessor}
|
||||
* implementations to easily provide {@code requiresDestruction} logic while
|
||||
* retaining compatibility with Spring <4.3, and it is also an easier onramp to
|
||||
* declaring {@code requiresDestruction} as a Java 8 default method in Spring 5.
|
||||
* <p>If an implementation of {@code DestructionAwareBeanPostProcessor} does
|
||||
* not provide a concrete implementation of this method, Spring's invocation
|
||||
* mechanism silently assumes a method returning {@code true} (the effective
|
||||
* default before 4.3, and the to-be-default in the Java 8 method in Spring 5).
|
||||
* <p>The default implementation returns {@code true}. If a pre-5 implementation
|
||||
* of {@code DestructionAwareBeanPostProcessor} does not provide a concrete
|
||||
* implementation of this method, Spring silently assumes {@code true} as well.
|
||||
* @param bean the bean instance to check
|
||||
* @return {@code true} if {@link #postProcessBeforeDestruction} is supposed to
|
||||
* be called for this bean instance eventually, or {@code false} if not needed
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -121,7 +121,7 @@ public class PreferencesPlaceholderConfigurer extends PropertyPlaceholderConfigu
|
||||
@Nullable
|
||||
protected String resolvePlaceholder(@Nullable String path, String key, Preferences preferences) {
|
||||
if (path != null) {
|
||||
// Do not create the node if it does not exist...
|
||||
// Do not create the node if it does not exist...
|
||||
try {
|
||||
if (preferences.nodeExists(path)) {
|
||||
return preferences.node(path).get(key, null);
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ public class PropertyOverrideConfigurer extends PropertyResourceConfigurer {
|
||||
"': expected 'beanName" + this.beanNameSeparator + "property'");
|
||||
}
|
||||
String beanName = key.substring(0, separatorIndex);
|
||||
String beanProperty = key.substring(separatorIndex+1);
|
||||
String beanProperty = key.substring(separatorIndex + 1);
|
||||
this.beanNames.add(beanName);
|
||||
applyPropertyValue(factory, beanName, beanProperty, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
+12
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -28,32 +28,26 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* {@link PlaceholderConfigurerSupport} subclass that resolves ${...} placeholders
|
||||
* against {@link #setLocation local} {@link #setProperties properties} and/or system properties
|
||||
* {@link PlaceholderConfigurerSupport} subclass that resolves ${...} placeholders against
|
||||
* {@link #setLocation local} {@link #setProperties properties} and/or system properties
|
||||
* and environment variables.
|
||||
*
|
||||
* <p>As of Spring 3.1, {@link org.springframework.context.support.PropertySourcesPlaceholderConfigurer
|
||||
* PropertySourcesPlaceholderConfigurer} should be used preferentially over this implementation; it is
|
||||
* more flexible through taking advantage of the {@link org.springframework.core.env.Environment Environment} and
|
||||
* {@link org.springframework.core.env.PropertySource PropertySource} mechanisms also made available in Spring 3.1.
|
||||
* more flexible through taking advantage of the {@link org.springframework.core.env.Environment} and
|
||||
* {@link org.springframework.core.env.PropertySource} mechanisms also made available in Spring 3.1.
|
||||
*
|
||||
* <p>{@link PropertyPlaceholderConfigurer} is still appropriate for use when:
|
||||
* <ul>
|
||||
* <li>the {@code spring-context} module is not available (i.e., one is using Spring's
|
||||
* {@code BeanFactory} API as opposed to {@code ApplicationContext}).
|
||||
* <li>existing configuration makes use of the {@link #setSystemPropertiesMode(int) "systemPropertiesMode"} and/or
|
||||
* {@link #setSystemPropertiesModeName(String) "systemPropertiesModeName"} properties. Users are encouraged to move
|
||||
* away from using these settings, and rather configure property source search order through the container's
|
||||
* {@code Environment}; however, exact preservation of functionality may be maintained by continuing to
|
||||
* use {@code PropertyPlaceholderConfigurer}.
|
||||
* <li>existing configuration makes use of the {@link #setSystemPropertiesMode(int) "systemPropertiesMode"}
|
||||
* and/or {@link #setSystemPropertiesModeName(String) "systemPropertiesModeName"} properties.
|
||||
* Users are encouraged to move away from using these settings, and rather configure property
|
||||
* source search order through the container's {@code Environment}; however, exact preservation
|
||||
* of functionality may be maintained by continuing to use {@code PropertyPlaceholderConfigurer}.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Prior to Spring 3.1, the {@code <context:property-placeholder/>} namespace element
|
||||
* registered an instance of {@code PropertyPlaceholderConfigurer}. It will still do so if
|
||||
* using the {@code spring-context-3.0.xsd} definition of the namespace. That is, you can preserve
|
||||
* registration of {@code PropertyPlaceholderConfigurer} through the namespace, even if using Spring 3.1;
|
||||
* simply do not update your {@code xsi:schemaLocation} and continue using the 3.0 XSD.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 02.10.2003
|
||||
@@ -92,7 +86,6 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
|
||||
* Set the system property mode by the name of the corresponding constant,
|
||||
* e.g. "SYSTEM_PROPERTIES_MODE_OVERRIDE".
|
||||
* @param constantName name of the constant
|
||||
* @throws java.lang.IllegalArgumentException if an invalid constant was specified
|
||||
* @see #setSystemPropertiesMode
|
||||
*/
|
||||
public void setSystemPropertiesModeName(String constantName) throws IllegalArgumentException {
|
||||
@@ -124,14 +117,9 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
|
||||
* against system environment variables. Note that it is generally recommended
|
||||
* to pass external values in as JVM system properties: This can easily be
|
||||
* achieved in a startup script, even for existing environment variables.
|
||||
* <p><b>NOTE:</b> Access to environment variables does not work on the
|
||||
* Sun VM 1.4, where the corresponding {@link System#getenv} support was
|
||||
* disabled - before it eventually got re-enabled for the Sun VM 1.5.
|
||||
* Please upgrade to 1.5 (or higher) if you intend to rely on the
|
||||
* environment variable support.
|
||||
* @see #setSystemPropertiesMode
|
||||
* @see java.lang.System#getProperty(String)
|
||||
* @see java.lang.System#getenv(String)
|
||||
* @see System#getProperty(String)
|
||||
* @see System#getenv(String)
|
||||
*/
|
||||
public void setSearchSystemEnvironment(boolean searchSystemEnvironment) {
|
||||
this.searchSystemEnvironment = searchSystemEnvironment;
|
||||
|
||||
+10
-1
@@ -236,6 +236,10 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
return this.standardXmlBeanDefinitionReader.loadBeanDefinitions(encodedResource);
|
||||
}
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loading Groovy bean definitions from " + encodedResource);
|
||||
}
|
||||
|
||||
Closure beans = new Closure(this) {
|
||||
@Override
|
||||
public Object call(Object[] args) {
|
||||
@@ -265,7 +269,12 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
|
||||
throw new BeanDefinitionParsingException(new Problem("Error evaluating Groovy script: " + ex.getMessage(),
|
||||
new Location(encodedResource.getResource()), null, ex));
|
||||
}
|
||||
return getRegistry().getBeanDefinitionCount() - countBefore;
|
||||
|
||||
int count = getRegistry().getBeanDefinitionCount() - countBefore;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded " + count + " bean definitions from " + encodedResource);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-5
@@ -24,7 +24,6 @@ import groovy.lang.GroovyObjectSupport;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
@@ -182,16 +181,16 @@ class GroovyBeanDefinitionWrapper extends GroovyObjectSupport {
|
||||
AbstractBeanDefinition bd = getBeanDefinition();
|
||||
if (AUTOWIRE.equals(property)) {
|
||||
if ("byName".equals(newValue)) {
|
||||
bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
|
||||
bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
|
||||
}
|
||||
else if ("byType".equals(newValue)) {
|
||||
bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE);
|
||||
bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
}
|
||||
else if ("constructor".equals(newValue)) {
|
||||
bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
|
||||
bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
}
|
||||
else if (Boolean.TRUE.equals(newValue)) {
|
||||
bd.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);
|
||||
bd.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
|
||||
}
|
||||
}
|
||||
// constructorArgs
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ import org.springframework.beans.factory.config.BeanReference;
|
||||
* all {@link BeanReference BeanReferences} that are required to validate the configuration of the
|
||||
* overall logical entity as well as those required to provide full user visualisation of the configuration.
|
||||
* It is expected that certain {@link BeanReference BeanReferences} will not be important to
|
||||
* validation or to the user view of the configuration and as such these may be ommitted. A tool may wish to
|
||||
* validation or to the user view of the configuration and as such these may be omitted. A tool may wish to
|
||||
* display any additional {@link BeanReference BeanReferences} sourced through the supplied
|
||||
* {@link BeanDefinition BeanDefinitions} but this is not considered to be a typical case.
|
||||
*
|
||||
|
||||
+63
-44
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -58,6 +58,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -337,12 +338,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
return initializeBean(beanName, existingBean, bd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
|
||||
return resolveDependency(descriptor, requestingBeanName, null, null);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Specialized methods for fine-grained control over the bean lifecycle
|
||||
@@ -415,8 +410,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
throws BeansException {
|
||||
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
|
||||
for (BeanPostProcessor processor : getBeanPostProcessors()) {
|
||||
Object current = processor.postProcessBeforeInitialization(result, beanName);
|
||||
if (current == null) {
|
||||
return result;
|
||||
}
|
||||
@@ -430,8 +425,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
throws BeansException {
|
||||
|
||||
Object result = existingBean;
|
||||
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
|
||||
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
|
||||
for (BeanPostProcessor processor : getBeanPostProcessors()) {
|
||||
Object current = processor.postProcessAfterInitialization(result, beanName);
|
||||
if (current == null) {
|
||||
return result;
|
||||
}
|
||||
@@ -446,6 +441,28 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Delegate methods for resolving injection points
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Object resolveBeanByName(String name, DependencyDescriptor descriptor) {
|
||||
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
|
||||
try {
|
||||
return getBean(name, descriptor.getDependencyType());
|
||||
}
|
||||
finally {
|
||||
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException {
|
||||
return resolveDependency(descriptor, requestingBeanName, null, null);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of relevant AbstractBeanFactory template methods
|
||||
//---------------------------------------------------------------------
|
||||
@@ -459,8 +476,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
|
||||
throws BeanCreationException {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating instance of bean '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Creating instance of bean '" + beanName + "'");
|
||||
}
|
||||
RootBeanDefinition mbdToUse = mbd;
|
||||
|
||||
@@ -496,8 +513,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
try {
|
||||
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Finished creating instance of bean '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Finished creating instance of bean '" + beanName + "'");
|
||||
}
|
||||
return beanInstance;
|
||||
}
|
||||
@@ -562,8 +579,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
|
||||
isSingletonCurrentlyInCreation(beanName));
|
||||
if (earlySingletonExposure) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Eagerly caching bean '" + beanName +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Eagerly caching bean '" + beanName +
|
||||
"' to allow for resolving potential circular references");
|
||||
}
|
||||
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
|
||||
@@ -775,6 +792,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
mbd.factoryMethodToIntrospect = uniqueCandidate;
|
||||
if (commonType == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -1122,7 +1140,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
return obtainFromSupplier(instanceSupplier, beanName);
|
||||
}
|
||||
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
return instantiateUsingFactoryMethod(beanName, mbd, args);
|
||||
}
|
||||
|
||||
@@ -1146,14 +1164,19 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
// Need to determine the constructor...
|
||||
// Candidate constructors for autowiring?
|
||||
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
|
||||
if (ctors != null ||
|
||||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
|
||||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
|
||||
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
|
||||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
|
||||
return autowireConstructor(beanName, mbd, ctors, args);
|
||||
}
|
||||
|
||||
// Preferred constructors for default construction?
|
||||
ctors = mbd.getPreferredConstructors();
|
||||
if (ctors != null) {
|
||||
return autowireConstructor(beanName, mbd, ctors, null);
|
||||
}
|
||||
|
||||
// No special handling: simply use no-arg constructor.
|
||||
return instantiateBean(beanName, mbd);
|
||||
}
|
||||
@@ -1345,25 +1368,21 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
|
||||
|
||||
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
|
||||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
|
||||
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
|
||||
|
||||
// Add property values based on autowire by name if applicable.
|
||||
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
|
||||
autowireByName(beanName, mbd, bw, newPvs);
|
||||
}
|
||||
|
||||
// Add property values based on autowire by type if applicable.
|
||||
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
|
||||
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
|
||||
autowireByType(beanName, mbd, bw, newPvs);
|
||||
}
|
||||
|
||||
pvs = newPvs;
|
||||
}
|
||||
|
||||
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
|
||||
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
|
||||
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
|
||||
|
||||
PropertyDescriptor[] filteredPds = null;
|
||||
if (hasInstAwareBpps) {
|
||||
@@ -1417,8 +1436,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
Object bean = getBean(propertyName);
|
||||
pvs.add(propertyName, bean);
|
||||
registerDependentBean(propertyName, beanName);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Added autowiring by name from bean name '" + beanName +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Added autowiring by name from bean name '" + beanName +
|
||||
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
|
||||
}
|
||||
}
|
||||
@@ -1468,8 +1487,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
for (String autowiredBeanName : autowiredBeanNames) {
|
||||
registerDependentBean(autowiredBeanName, beanName);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
|
||||
propertyName + "' to bean named '" + autowiredBeanName + "'");
|
||||
}
|
||||
}
|
||||
@@ -1576,9 +1595,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
|
||||
boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
|
||||
boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
|
||||
(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
|
||||
(!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
|
||||
(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
|
||||
(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
if (unsatisfied) {
|
||||
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
|
||||
"Set this property value or disable dependency checking for this bean.");
|
||||
@@ -1784,8 +1803,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
boolean isInitializingBean = (bean instanceof InitializingBean);
|
||||
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
|
||||
}
|
||||
if (System.getSecurityManager() != null) {
|
||||
try {
|
||||
@@ -1831,12 +1850,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
if (initMethod == null) {
|
||||
if (mbd.isEnforceInitMethod()) {
|
||||
throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
|
||||
throw new BeanDefinitionValidationException("Could not find an init method named '" +
|
||||
initMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No default init method named '" + initMethodName +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("No default init method named '" + initMethodName +
|
||||
"' found on bean with name '" + beanName + "'");
|
||||
}
|
||||
// Ignore non-existent default lifecycle methods.
|
||||
@@ -1844,8 +1863,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
|
||||
+7
-1
@@ -158,7 +158,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
|
||||
private boolean primary = false;
|
||||
|
||||
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);
|
||||
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private Supplier<?> instanceSupplier;
|
||||
@@ -878,6 +878,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
* Set the name of the initializer method.
|
||||
* <p>The default is {@code null} in which case there is no initializer method.
|
||||
*/
|
||||
@Override
|
||||
public void setInitMethodName(@Nullable String initMethodName) {
|
||||
this.initMethodName = initMethodName;
|
||||
}
|
||||
@@ -885,6 +886,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Return the name of the initializer method.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getInitMethodName() {
|
||||
return this.initMethodName;
|
||||
@@ -911,6 +913,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
* Set the name of the destroy method.
|
||||
* <p>The default is {@code null} in which case there is no destroy method.
|
||||
*/
|
||||
@Override
|
||||
public void setDestroyMethodName(@Nullable String destroyMethodName) {
|
||||
this.destroyMethodName = destroyMethodName;
|
||||
}
|
||||
@@ -918,6 +921,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Return the name of the destroy method.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public String getDestroyMethodName() {
|
||||
return this.destroyMethodName;
|
||||
@@ -960,6 +964,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Set the role hint for this {@code BeanDefinition}.
|
||||
*/
|
||||
@Override
|
||||
public void setRole(int role) {
|
||||
this.role = role;
|
||||
}
|
||||
@@ -975,6 +980,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Set a human-readable description of this bean definition.
|
||||
*/
|
||||
@Override
|
||||
public void setDescription(@Nullable String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
+18
-19
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -45,7 +46,7 @@ import org.springframework.util.Assert;
|
||||
* @since 11.12.2003
|
||||
* @see BeanDefinitionReaderUtils
|
||||
*/
|
||||
public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable, BeanDefinitionReader {
|
||||
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
@@ -182,11 +183,11 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
@Override
|
||||
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
|
||||
Assert.notNull(resources, "Resource array must not be null");
|
||||
int counter = 0;
|
||||
int count = 0;
|
||||
for (Resource resource : resources) {
|
||||
counter += loadBeanDefinitions(resource);
|
||||
count += loadBeanDefinitions(resource);
|
||||
}
|
||||
return counter;
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,23 +214,21 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
ResourceLoader resourceLoader = getResourceLoader();
|
||||
if (resourceLoader == null) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
|
||||
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
|
||||
}
|
||||
|
||||
if (resourceLoader instanceof ResourcePatternResolver) {
|
||||
// Resource pattern matching available.
|
||||
try {
|
||||
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
|
||||
int loadCount = loadBeanDefinitions(resources);
|
||||
int count = loadBeanDefinitions(resources);
|
||||
if (actualResources != null) {
|
||||
for (Resource resource : resources) {
|
||||
actualResources.add(resource);
|
||||
}
|
||||
Collections.addAll(actualResources, resources);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
|
||||
}
|
||||
return loadCount;
|
||||
return count;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new BeanDefinitionStoreException(
|
||||
@@ -239,25 +238,25 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable
|
||||
else {
|
||||
// Can only load single resources by absolute URL.
|
||||
Resource resource = resourceLoader.getResource(location);
|
||||
int loadCount = loadBeanDefinitions(resource);
|
||||
int count = loadBeanDefinitions(resource);
|
||||
if (actualResources != null) {
|
||||
actualResources.add(resource);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
|
||||
}
|
||||
return loadCount;
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
|
||||
Assert.notNull(locations, "Location array must not be null");
|
||||
int counter = 0;
|
||||
int count = 0;
|
||||
for (String location : locations) {
|
||||
counter += loadBeanDefinitions(location);
|
||||
count += loadBeanDefinitions(location);
|
||||
}
|
||||
return counter;
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+57
-31
@@ -29,11 +29,11 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
@@ -145,16 +145,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private TypeConverter typeConverter;
|
||||
|
||||
/** String resolvers to apply e.g. to annotation attribute values. */
|
||||
private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<>();
|
||||
private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>();
|
||||
|
||||
/** BeanPostProcessors to apply in createBean. */
|
||||
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
|
||||
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
|
||||
|
||||
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */
|
||||
private boolean hasInstantiationAwareBeanPostProcessors;
|
||||
private volatile boolean hasInstantiationAwareBeanPostProcessors;
|
||||
|
||||
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */
|
||||
private boolean hasDestructionAwareBeanPostProcessors;
|
||||
private volatile boolean hasDestructionAwareBeanPostProcessors;
|
||||
|
||||
/** Map from scope identifier String to corresponding Scope. */
|
||||
private final Map<String, Scope> scopes = new LinkedHashMap<>(8);
|
||||
@@ -245,13 +245,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
// Eagerly check singleton cache for manually registered singletons.
|
||||
Object sharedInstance = getSingleton(beanName);
|
||||
if (sharedInstance != null && args == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (isSingletonCurrentlyInCreation(beanName)) {
|
||||
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
|
||||
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
|
||||
"' that is not fully initialized yet - a consequence of a circular reference");
|
||||
}
|
||||
else {
|
||||
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
|
||||
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
|
||||
}
|
||||
}
|
||||
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
|
||||
@@ -385,8 +385,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return convertedBean;
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to convert bean '" + name + "' to required type '" +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Failed to convert bean '" + name + "' to required type '" +
|
||||
ClassUtils.getQualifiedName(requiredType) + "'", ex);
|
||||
}
|
||||
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
|
||||
@@ -510,12 +510,21 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
// Generics potentially only match on the target class, not on the proxy...
|
||||
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance) &&
|
||||
typeToMatch.isAssignableFrom(targetType)) {
|
||||
if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
|
||||
// Check raw class match as well, making sure it's exposed on the proxy.
|
||||
Class<?> classToMatch = typeToMatch.resolve();
|
||||
return (classToMatch == null || classToMatch.isInstance(beanInstance));
|
||||
if (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
|
||||
return false;
|
||||
}
|
||||
if (typeToMatch.isAssignableFrom(targetType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ResolvableType resolvableType = mbd.targetType;
|
||||
if (resolvableType == null) {
|
||||
resolvableType = mbd.factoryMethodReturnType;
|
||||
}
|
||||
return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -850,14 +859,17 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
@Override
|
||||
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
|
||||
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
|
||||
// Remove from old position, if any
|
||||
this.beanPostProcessors.remove(beanPostProcessor);
|
||||
this.beanPostProcessors.add(beanPostProcessor);
|
||||
// Track whether it is instantiation/destruction aware
|
||||
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
|
||||
this.hasInstantiationAwareBeanPostProcessors = true;
|
||||
}
|
||||
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
|
||||
this.hasDestructionAwareBeanPostProcessors = true;
|
||||
}
|
||||
// Add to end of list
|
||||
this.beanPostProcessors.add(beanPostProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -988,7 +1000,6 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
@Override
|
||||
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
|
||||
String beanName = transformedBeanName(name);
|
||||
|
||||
// Efficiently check whether bean definition exists in this factory.
|
||||
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
|
||||
@@ -1000,18 +1011,15 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
@Override
|
||||
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
|
||||
String beanName = transformedBeanName(name);
|
||||
|
||||
Object beanInstance = getSingleton(beanName, false);
|
||||
if (beanInstance != null) {
|
||||
return (beanInstance instanceof FactoryBean);
|
||||
}
|
||||
|
||||
// No singleton instance found -> check bean definition.
|
||||
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
|
||||
// No bean definition found in this factory -> delegate to parent.
|
||||
return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
|
||||
}
|
||||
|
||||
return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
|
||||
}
|
||||
|
||||
@@ -1363,6 +1371,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
@Nullable
|
||||
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
|
||||
throws CannotLoadBeanClassException {
|
||||
|
||||
try {
|
||||
if (mbd.hasBeanClass()) {
|
||||
return mbd.getBeanClass();
|
||||
@@ -1392,13 +1401,16 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
throws ClassNotFoundException {
|
||||
|
||||
ClassLoader beanClassLoader = getBeanClassLoader();
|
||||
ClassLoader classLoaderToUse = beanClassLoader;
|
||||
ClassLoader dynamicLoader = beanClassLoader;
|
||||
boolean freshResolve = false;
|
||||
|
||||
if (!ObjectUtils.isEmpty(typesToMatch)) {
|
||||
// When just doing type checks (i.e. not creating an actual instance yet),
|
||||
// use the specified temporary class loader (e.g. in a weaving scenario).
|
||||
ClassLoader tempClassLoader = getTempClassLoader();
|
||||
if (tempClassLoader != null) {
|
||||
classLoaderToUse = tempClassLoader;
|
||||
dynamicLoader = tempClassLoader;
|
||||
freshResolve = true;
|
||||
if (tempClassLoader instanceof DecoratingClassLoader) {
|
||||
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
|
||||
for (Class<?> typeToMatch : typesToMatch) {
|
||||
@@ -1407,6 +1419,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String className = mbd.getBeanClassName();
|
||||
if (className != null) {
|
||||
Object evaluated = evaluateBeanDefinitionString(className, mbd);
|
||||
@@ -1416,18 +1429,31 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
return (Class<?>) evaluated;
|
||||
}
|
||||
else if (evaluated instanceof String) {
|
||||
return ClassUtils.forName((String) evaluated, classLoaderToUse);
|
||||
className = (String) evaluated;
|
||||
freshResolve = true;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
|
||||
}
|
||||
}
|
||||
// When resolving against a temporary class loader, exit early in order
|
||||
// to avoid storing the resolved Class in the bean definition.
|
||||
if (classLoaderToUse != beanClassLoader) {
|
||||
return ClassUtils.forName(className, classLoaderToUse);
|
||||
if (freshResolve) {
|
||||
// When resolving against a temporary class loader, exit early in order
|
||||
// to avoid storing the resolved Class in the bean definition.
|
||||
if (dynamicLoader != null) {
|
||||
try {
|
||||
return dynamicLoader.loadClass(className);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ClassUtils.forName(className, dynamicLoader);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve regularly, caching the result in the BeanDefinition...
|
||||
return mbd.resolveBeanClass(beanClassLoader);
|
||||
}
|
||||
|
||||
@@ -1519,18 +1545,18 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
if (ex.contains(BeanCurrentlyInCreationException.class)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean currently in creation on FactoryBean type check: " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Bean currently in creation on FactoryBean type check: " + ex);
|
||||
}
|
||||
}
|
||||
else if (mbd.isLazyInit()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean creation exception on lazy FactoryBean type check: " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Bean creation exception on lazy FactoryBean type check: " + ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Bean creation exception on non-lazy FactoryBean type check: " + ex);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bean creation exception on non-lazy FactoryBean type check: " + ex);
|
||||
}
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,6 +57,20 @@ public interface AutowireCandidateResolver {
|
||||
return descriptor.isRequired();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given descriptor declares a qualifier beyond the type
|
||||
* (typically - but not necessarily - a specific kind of annotation).
|
||||
* <p>The default implementation returns {@code false}.
|
||||
* @param descriptor the descriptor for the target method parameter or field
|
||||
* @return whether the descriptor declares a qualifier, narrowing the candidate
|
||||
* status beyond the type match
|
||||
* @since 5.1
|
||||
* @see org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#hasQualifier
|
||||
*/
|
||||
default boolean hasQualifier(DependencyDescriptor descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a default value is suggested for the given dependency.
|
||||
* <p>The default implementation simply returns {@code null}.
|
||||
|
||||
+18
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.beans.factory.support;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -28,6 +29,7 @@ import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
@@ -49,6 +51,18 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
abstract class AutowireUtils {
|
||||
|
||||
private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {
|
||||
boolean p1 = Modifier.isPublic(e1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(e2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = e1.getParameterCount();
|
||||
int c2pl = e2.getParameterCount();
|
||||
return Integer.compare(c2pl, c1pl);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sort the given constructors, preferring public constructors and "greedy" ones with
|
||||
* a maximum number of arguments. The result will contain public constructors first,
|
||||
@@ -57,16 +71,7 @@ abstract class AutowireUtils {
|
||||
* @param constructors the constructor array to sort
|
||||
*/
|
||||
public static void sortConstructors(Constructor<?>[] constructors) {
|
||||
Arrays.sort(constructors, (c1, c2) -> {
|
||||
boolean p1 = Modifier.isPublic(c1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(c2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = c1.getParameterCount();
|
||||
int c2pl = c2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
});
|
||||
Arrays.sort(constructors, EXECUTABLE_COMPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,16 +82,7 @@ abstract class AutowireUtils {
|
||||
* @param factoryMethods the factory method array to sort
|
||||
*/
|
||||
public static void sortFactoryMethods(Method[] factoryMethods) {
|
||||
Arrays.sort(factoryMethods, (fm1, fm2) -> {
|
||||
boolean p1 = Modifier.isPublic(fm1.getModifiers());
|
||||
boolean p2 = Modifier.isPublic(fm2.getModifiers());
|
||||
if (p1 != p2) {
|
||||
return (p1 ? -1 : 1);
|
||||
}
|
||||
int c1pl = fm1.getParameterCount();
|
||||
int c2pl = fm2.getParameterCount();
|
||||
return (c1pl < c2pl ? 1 : (c1pl > c2pl ? -1 : 0));
|
||||
});
|
||||
Arrays.sort(factoryMethods, EXECUTABLE_COMPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +154,7 @@ abstract class AutowireUtils {
|
||||
* on the given method itself.
|
||||
* <p>For example, given a factory method with the following signature, if
|
||||
* {@code resolveReturnTypeForFactoryMethod()} is invoked with the reflected
|
||||
* method for {@code creatProxy()} and an {@code Object[]} array containing
|
||||
* method for {@code createProxy()} and an {@code Object[]} array containing
|
||||
* {@code MyService.class}, {@code resolveReturnTypeForFactoryMethod()} will
|
||||
* infer that the target return type is {@code MyService}.
|
||||
* <pre class="code">{@code public static <T> T createProxy(Class<T> clazz)}</pre>
|
||||
|
||||
+2
-4
@@ -69,9 +69,7 @@ public final class BeanDefinitionBuilder {
|
||||
* @param instanceSupplier a callback for creating an instance of the bean
|
||||
* @since 5.0
|
||||
*/
|
||||
public static <T> BeanDefinitionBuilder genericBeanDefinition(
|
||||
@Nullable Class<T> beanClass, Supplier<T> instanceSupplier) {
|
||||
|
||||
public static <T> BeanDefinitionBuilder genericBeanDefinition(Class<T> beanClass, Supplier<T> instanceSupplier) {
|
||||
BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());
|
||||
builder.beanDefinition.setBeanClass(beanClass);
|
||||
builder.beanDefinition.setInstanceSupplier(instanceSupplier);
|
||||
@@ -280,7 +278,7 @@ public final class BeanDefinitionBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the depency check mode for this definition.
|
||||
* Set the dependency check mode for this definition.
|
||||
*/
|
||||
public BeanDefinitionBuilder setDependencyCheck(int dependencyCheck) {
|
||||
this.beanDefinition.setDependencyCheck(dependencyCheck);
|
||||
|
||||
+23
-7
@@ -124,13 +124,29 @@ public abstract class BeanDefinitionReaderUtils {
|
||||
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
|
||||
}
|
||||
else {
|
||||
// Top-level bean: use plain class name.
|
||||
// Increase counter until the id is unique.
|
||||
int counter = -1;
|
||||
while (counter == -1 || registry.containsBeanDefinition(id)) {
|
||||
counter++;
|
||||
id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
|
||||
}
|
||||
// Top-level bean: use plain class name with unique suffix if necessary.
|
||||
return uniqueBeanName(generatedBeanName, registry);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the given bean name into a unique bean name for the given bean factory,
|
||||
* appending a unique counter as suffix if necessary.
|
||||
* @param beanName the original bean name
|
||||
* @param registry the bean factory that the definition is going to be
|
||||
* registered with (to check for existing bean names)
|
||||
* @return the unique bean name to use
|
||||
* @since 5.1
|
||||
*/
|
||||
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
|
||||
String id = beanName;
|
||||
int counter = -1;
|
||||
|
||||
// Increase counter until the id is unique.
|
||||
while (counter == -1 || registry.containsBeanDefinition(id)) {
|
||||
counter++;
|
||||
id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ class BeanDefinitionResource extends AbstractResource {
|
||||
|
||||
/**
|
||||
* Create a new BeanDefinitionResource.
|
||||
* @param beanDefinition the BeanDefinition objectto wrap
|
||||
* @param beanDefinition the BeanDefinition object to wrap
|
||||
*/
|
||||
public BeanDefinitionResource(BeanDefinition beanDefinition) {
|
||||
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -79,7 +79,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
|
||||
@Override
|
||||
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
|
||||
@Nullable Constructor<?> ctor, @Nullable Object... args) {
|
||||
@Nullable Constructor<?> ctor, Object... args) {
|
||||
|
||||
// Must generate CGLIB subclass...
|
||||
return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
|
||||
@@ -113,7 +113,7 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
* Ignored if the {@code ctor} parameter is {@code null}.
|
||||
* @return new instance of the dynamically generated subclass
|
||||
*/
|
||||
public Object instantiate(@Nullable Constructor<?> ctor, @Nullable Object... args) {
|
||||
public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {
|
||||
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
|
||||
Object instance;
|
||||
if (ctor == null) {
|
||||
|
||||
+87
-54
@@ -47,6 +47,7 @@ import org.springframework.beans.factory.InjectionPoint;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.UnsatisfiedDependencyException;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
@@ -79,6 +80,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class ConstructorResolver {
|
||||
|
||||
private static final Object[] EMPTY_ARGS = new Object[0];
|
||||
|
||||
private static final NamedThreadLocal<InjectionPoint> currentInjectionPoint =
|
||||
new NamedThreadLocal<>("Current injection point");
|
||||
|
||||
@@ -111,8 +114,8 @@ class ConstructorResolver {
|
||||
* or {@code null} if none (-> use constructor argument values from bean definition)
|
||||
* @return a BeanWrapper for the new instance
|
||||
*/
|
||||
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
|
||||
@Nullable Constructor<?>[] chosenCtors, @Nullable final Object[] explicitArgs) {
|
||||
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
|
||||
@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
|
||||
|
||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||
this.beanFactory.initBeanWrapper(bw);
|
||||
@@ -141,22 +144,7 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
if (constructorToUse == null) {
|
||||
// Need to resolve the constructor.
|
||||
boolean autowiring = (chosenCtors != null ||
|
||||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
ConstructorArgumentValues resolvedValues = null;
|
||||
|
||||
int minNrOfArgs;
|
||||
if (explicitArgs != null) {
|
||||
minNrOfArgs = explicitArgs.length;
|
||||
}
|
||||
else {
|
||||
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
|
||||
resolvedValues = new ConstructorArgumentValues();
|
||||
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
|
||||
}
|
||||
|
||||
if (constructorToUse == null || argsToUse == null) {
|
||||
// Take specified constructors, if any.
|
||||
Constructor<?>[] candidates = chosenCtors;
|
||||
if (candidates == null) {
|
||||
@@ -171,6 +159,35 @@ class ConstructorResolver {
|
||||
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
|
||||
Constructor<?> uniqueCandidate = candidates[0];
|
||||
if (uniqueCandidate.getParameterCount() == 0) {
|
||||
synchronized (mbd.constructorArgumentLock) {
|
||||
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
|
||||
mbd.constructorArgumentsResolved = true;
|
||||
mbd.resolvedConstructorArguments = EMPTY_ARGS;
|
||||
}
|
||||
bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
|
||||
return bw;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to resolve the constructor.
|
||||
boolean autowiring = (chosenCtors != null ||
|
||||
mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
|
||||
ConstructorArgumentValues resolvedValues = null;
|
||||
|
||||
int minNrOfArgs;
|
||||
if (explicitArgs != null) {
|
||||
minNrOfArgs = explicitArgs.length;
|
||||
}
|
||||
else {
|
||||
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
|
||||
resolvedValues = new ConstructorArgumentValues();
|
||||
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
|
||||
}
|
||||
|
||||
AutowireUtils.sortConstructors(candidates);
|
||||
int minTypeDiffWeight = Integer.MAX_VALUE;
|
||||
Set<Constructor<?>> ambiguousConstructors = null;
|
||||
@@ -179,7 +196,7 @@ class ConstructorResolver {
|
||||
for (Constructor<?> candidate : candidates) {
|
||||
Class<?>[] paramTypes = candidate.getParameterTypes();
|
||||
|
||||
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
|
||||
if (constructorToUse != null && argsToUse != null && argsToUse.length > paramTypes.length) {
|
||||
// Already found greedy constructor that can be satisfied ->
|
||||
// do not look any further, there are only less greedy constructors left.
|
||||
break;
|
||||
@@ -259,28 +276,29 @@ class ConstructorResolver {
|
||||
ambiguousConstructors);
|
||||
}
|
||||
|
||||
if (explicitArgs == null) {
|
||||
if (explicitArgs == null && argsHolderToUse != null) {
|
||||
argsHolderToUse.storeCache(mbd, constructorToUse);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
|
||||
Object beanInstance;
|
||||
Assert.state(argsToUse != null, "Unresolved constructor arguments");
|
||||
bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
|
||||
return bw;
|
||||
}
|
||||
|
||||
private Object instantiate(
|
||||
String beanName, RootBeanDefinition mbd, Constructor constructorToUse, Object[] argsToUse) {
|
||||
|
||||
try {
|
||||
InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
|
||||
if (System.getSecurityManager() != null) {
|
||||
final Constructor<?> ctorToUse = constructorToUse;
|
||||
final Object[] argumentsToUse = argsToUse;
|
||||
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
|
||||
strategy.instantiate(mbd, beanName, this.beanFactory, ctorToUse, argumentsToUse),
|
||||
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
|
||||
strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
|
||||
this.beanFactory.getAccessControlContext());
|
||||
}
|
||||
else {
|
||||
beanInstance = strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
|
||||
return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
|
||||
}
|
||||
|
||||
bw.setBeanInstance(beanInstance);
|
||||
return bw;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
@@ -320,9 +338,7 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (mbd.constructorArgumentLock) {
|
||||
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
|
||||
}
|
||||
mbd.factoryMethodToIntrospect = uniqueCandidate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,7 +346,7 @@ class ConstructorResolver {
|
||||
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
|
||||
* Called as the starting point for factory method determination.
|
||||
*/
|
||||
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
|
||||
private Method[] getCandidateMethods(Class<?> factoryClass, RootBeanDefinition mbd) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Method[]>) () ->
|
||||
(mbd.isNonPublicAccessAllowed() ?
|
||||
@@ -358,7 +374,7 @@ class ConstructorResolver {
|
||||
* @return a BeanWrapper for the new instance
|
||||
*/
|
||||
public BeanWrapper instantiateUsingFactoryMethod(
|
||||
final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {
|
||||
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
|
||||
|
||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||
this.beanFactory.initBeanWrapper(bw);
|
||||
@@ -421,17 +437,32 @@ class ConstructorResolver {
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
|
||||
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
|
||||
List<Method> candidateSet = new ArrayList<>();
|
||||
List<Method> candidateList = new ArrayList<>();
|
||||
for (Method candidate : rawCandidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
|
||||
candidateSet.add(candidate);
|
||||
candidateList.add(candidate);
|
||||
}
|
||||
}
|
||||
Method[] candidates = candidateSet.toArray(new Method[0]);
|
||||
|
||||
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
|
||||
Method uniqueCandidate = candidateList.get(0);
|
||||
if (uniqueCandidate.getParameterCount() == 0) {
|
||||
mbd.factoryMethodToIntrospect = uniqueCandidate;
|
||||
synchronized (mbd.constructorArgumentLock) {
|
||||
mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
|
||||
mbd.constructorArgumentsResolved = true;
|
||||
mbd.resolvedConstructorArguments = EMPTY_ARGS;
|
||||
}
|
||||
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
|
||||
return bw;
|
||||
}
|
||||
}
|
||||
|
||||
Method[] candidates = candidateList.toArray(new Method[0]);
|
||||
AutowireUtils.sortFactoryMethods(candidates);
|
||||
|
||||
ConstructorArgumentValues resolvedValues = null;
|
||||
boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
|
||||
boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
|
||||
int minTypeDiffWeight = Integer.MAX_VALUE;
|
||||
Set<Method> ambiguousFactoryMethods = null;
|
||||
|
||||
@@ -460,7 +491,7 @@ class ConstructorResolver {
|
||||
if (paramTypes.length >= minNrOfArgs) {
|
||||
ArgumentsHolder argsHolder;
|
||||
|
||||
if (explicitArgs != null){
|
||||
if (explicitArgs != null) {
|
||||
// Explicit arguments given -> arguments length must match exactly.
|
||||
if (paramTypes.length != explicitArgs.length) {
|
||||
continue;
|
||||
@@ -533,7 +564,7 @@ class ConstructorResolver {
|
||||
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
|
||||
}
|
||||
}
|
||||
else if (resolvedValues != null){
|
||||
else if (resolvedValues != null) {
|
||||
Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
|
||||
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
|
||||
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
|
||||
@@ -567,28 +598,30 @@ class ConstructorResolver {
|
||||
}
|
||||
|
||||
if (explicitArgs == null && argsHolderToUse != null) {
|
||||
mbd.factoryMethodToIntrospect = factoryMethodToUse;
|
||||
argsHolderToUse.storeCache(mbd, factoryMethodToUse);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Object beanInstance;
|
||||
Assert.state(argsToUse != null, "Unresolved factory method arguments");
|
||||
bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
|
||||
return bw;
|
||||
}
|
||||
|
||||
private Object instantiate(String beanName, RootBeanDefinition mbd,
|
||||
@Nullable Object factoryBean, Method factoryMethod, Object[] args) {
|
||||
|
||||
try {
|
||||
if (System.getSecurityManager() != null) {
|
||||
final Object fb = factoryBean;
|
||||
final Method factoryMethod = factoryMethodToUse;
|
||||
final Object[] args = argsToUse;
|
||||
beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
|
||||
this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, fb, factoryMethod, args),
|
||||
return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
|
||||
this.beanFactory.getInstantiationStrategy().instantiate(
|
||||
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
|
||||
this.beanFactory.getAccessControlContext());
|
||||
}
|
||||
else {
|
||||
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
|
||||
mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
|
||||
return this.beanFactory.getInstantiationStrategy().instantiate(
|
||||
mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
|
||||
}
|
||||
|
||||
bw.setBeanInstance(beanInstance);
|
||||
return bw;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
|
||||
+163
-87
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
@@ -65,6 +65,7 @@ import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
@@ -381,10 +382,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
@Override
|
||||
public Stream<T> stream() {
|
||||
return Arrays.stream(getBeanNamesForType(requiredType))
|
||||
return Arrays.stream(getBeanNamesForTypedStream(requiredType))
|
||||
.map(name -> (T) getBean(name))
|
||||
.filter(bean -> !(bean instanceof NullBean));
|
||||
}
|
||||
@Override
|
||||
public Stream<T> orderedStream() {
|
||||
String[] beanNames = getBeanNamesForTypedStream(requiredType);
|
||||
Map<String, T> matchingBeans = new LinkedHashMap<>(beanNames.length);
|
||||
for (String beanName : beanNames) {
|
||||
Object beanInstance = getBean(beanName);
|
||||
if (!(beanInstance instanceof NullBean)) {
|
||||
matchingBeans.put(beanName, (T) beanInstance);
|
||||
}
|
||||
}
|
||||
Stream<T> stream = matchingBeans.values().stream();
|
||||
return stream.sorted(adaptOrderComparator(matchingBeans));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -410,6 +424,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] getBeanNamesForTypedStream(ResolvableType requiredType) {
|
||||
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of ListableBeanFactory interface
|
||||
@@ -439,7 +457,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public String[] getBeanNamesForType(ResolvableType type) {
|
||||
return doGetBeanNamesForType(type, true, true);
|
||||
Class<?> resolved = type.resolve();
|
||||
if (resolved != null && !type.hasGenerics()) {
|
||||
return getBeanNamesForType(resolved, true, true);
|
||||
}
|
||||
else {
|
||||
return doGetBeanNamesForType(type, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -503,8 +527,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
throw ex;
|
||||
}
|
||||
// Probably a class name with a placeholder: let's ignore it for type matching purposes.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring bean class loading failure for bean '" + beanName + "'", ex);
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
}
|
||||
@@ -513,8 +537,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
throw ex;
|
||||
}
|
||||
// Probably some metadata with a placeholder: let's ignore it for type matching purposes.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
}
|
||||
@@ -541,8 +565,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// Shouldn't happen - probably a result of circular reference resolution...
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Failed to check manually registered singleton with name '" + beanName + "'", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -586,8 +610,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
BeanCreationException bce = (BeanCreationException) rootCause;
|
||||
String exBeanName = bce.getBeanName();
|
||||
if (exBeanName != null && isCurrentlyInCreation(exBeanName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring match to currently created bean '" + exBeanName + "': " +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring match to currently created bean '" + exBeanName + "': " +
|
||||
ex.getMessage());
|
||||
}
|
||||
onSuppressedException(ex);
|
||||
@@ -604,29 +628,32 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
|
||||
List<String> results = new ArrayList<>();
|
||||
List<String> result = new ArrayList<>();
|
||||
for (String beanName : this.beanDefinitionNames) {
|
||||
BeanDefinition beanDefinition = getBeanDefinition(beanName);
|
||||
if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.add(beanName);
|
||||
result.add(beanName);
|
||||
}
|
||||
}
|
||||
for (String beanName : this.manualSingletonNames) {
|
||||
if (!results.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
results.add(beanName);
|
||||
if (!result.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) {
|
||||
result.add(beanName);
|
||||
}
|
||||
}
|
||||
return StringUtils.toStringArray(results);
|
||||
return StringUtils.toStringArray(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) {
|
||||
String[] beanNames = getBeanNamesForAnnotation(annotationType);
|
||||
Map<String, Object> results = new LinkedHashMap<>(beanNames.length);
|
||||
Map<String, Object> result = new LinkedHashMap<>(beanNames.length);
|
||||
for (String beanName : beanNames) {
|
||||
results.put(beanName, getBean(beanName));
|
||||
Object beanInstance = getBean(beanName);
|
||||
if (!(beanInstance instanceof NullBean)) {
|
||||
result.put(beanName, beanInstance);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -638,7 +665,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
|
||||
throws NoSuchBeanDefinitionException{
|
||||
throws NoSuchBeanDefinitionException {
|
||||
|
||||
A ann = null;
|
||||
Class<?> beanType = getType(beanName);
|
||||
@@ -650,7 +677,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (bd instanceof AbstractBeanDefinition) {
|
||||
AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
|
||||
if (abd.hasBeanClass()) {
|
||||
ann = AnnotationUtils.findAnnotation(abd.getBeanClass(), annotationType);
|
||||
Class<?> beanClass = abd.getBeanClass();
|
||||
if (beanClass != beanType) {
|
||||
ann = AnnotationUtils.findAnnotation(beanClass, annotationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -728,14 +758,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
|
||||
resolveBeanClass(mbd, beanDefinitionName);
|
||||
if (mbd.isFactoryMethodUnique) {
|
||||
boolean resolve;
|
||||
synchronized (mbd.constructorArgumentLock) {
|
||||
resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
|
||||
}
|
||||
if (resolve) {
|
||||
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
|
||||
}
|
||||
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
|
||||
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
|
||||
}
|
||||
return resolver.isAutowireCandidate(
|
||||
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
|
||||
@@ -790,8 +814,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public void preInstantiateSingletons() throws BeansException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Pre-instantiating singletons in " + this);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Pre-instantiating singletons in " + this);
|
||||
}
|
||||
|
||||
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
|
||||
@@ -958,7 +982,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
/**
|
||||
* Reset all bean definition caches for the given bean,
|
||||
* including the caches of beans that are derived from it.
|
||||
* <p>Called after an existing bean definition has been replaced or removed,
|
||||
* triggering {@link #clearMergedBeanDefinition}, {@link #destroySingleton}
|
||||
* and {@link MergedBeanDefinitionPostProcessor#resetBeanDefinition} on the
|
||||
* given bean and on all bean definitions that have the given bean as parent.
|
||||
* @param beanName the name of the bean to reset
|
||||
* @see #registerBeanDefinition
|
||||
* @see #removeBeanDefinition
|
||||
*/
|
||||
protected void resetBeanDefinition(String beanName) {
|
||||
// Remove the merged bean definition for the given bean, if already created.
|
||||
@@ -969,6 +999,13 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
|
||||
destroySingleton(beanName);
|
||||
|
||||
// Notify all post-processors that the specified bean definition has been reset.
|
||||
for (BeanPostProcessor processor : getBeanPostProcessors()) {
|
||||
if (processor instanceof MergedBeanDefinitionPostProcessor) {
|
||||
((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all bean definitions that have the given bean as parent (recursively).
|
||||
for (String bdName : this.beanDefinitionNames) {
|
||||
if (!beanName.equals(bdName)) {
|
||||
@@ -1059,8 +1096,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
|
||||
|
||||
Assert.notNull(requiredType, "Required type must not be null");
|
||||
Class<?> clazz = requiredType.getRawClass();
|
||||
Assert.notNull(clazz, "Required type must have a raw Class");
|
||||
String[] candidateNames = getBeanNamesForType(requiredType);
|
||||
|
||||
if (candidateNames.length > 1) {
|
||||
@@ -1077,7 +1112,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
if (candidateNames.length == 1) {
|
||||
String beanName = candidateNames[0];
|
||||
return new NamedBeanHolder<>(beanName, (T) getBean(beanName, clazz, args));
|
||||
return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
|
||||
}
|
||||
else if (candidateNames.length > 1) {
|
||||
Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
|
||||
@@ -1090,14 +1125,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
candidates.put(beanName, getType(beanName));
|
||||
}
|
||||
}
|
||||
String candidateName = determinePrimaryCandidate(candidates, clazz);
|
||||
String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
|
||||
if (candidateName == null) {
|
||||
candidateName = determineHighestPriorityCandidate(candidates, clazz);
|
||||
candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
|
||||
}
|
||||
if (candidateName != null) {
|
||||
Object beanInstance = candidates.get(candidateName);
|
||||
if (beanInstance == null || beanInstance instanceof Class) {
|
||||
beanInstance = getBean(candidateName, clazz, args);
|
||||
beanInstance = getBean(candidateName, requiredType.toClass(), args);
|
||||
}
|
||||
return new NamedBeanHolder<>(candidateName, (T) beanInstance);
|
||||
}
|
||||
@@ -1151,13 +1186,20 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (value != null) {
|
||||
if (value instanceof String) {
|
||||
String strVal = resolveEmbeddedValue((String) value);
|
||||
BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
|
||||
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
|
||||
getMergedBeanDefinition(beanName) : null);
|
||||
value = evaluateBeanDefinitionString(strVal, bd);
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
return (descriptor.getField() != null ?
|
||||
converter.convertIfNecessary(value, type, descriptor.getField()) :
|
||||
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
|
||||
try {
|
||||
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// A custom TypeConverter which does not support TypeDescriptor resolution...
|
||||
return (descriptor.getField() != null ?
|
||||
converter.convertIfNecessary(value, type, descriptor.getField()) :
|
||||
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
|
||||
}
|
||||
}
|
||||
|
||||
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
|
||||
@@ -1225,29 +1267,33 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
|
||||
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
|
||||
|
||||
Class<?> type = descriptor.getDependencyType();
|
||||
final Class<?> type = descriptor.getDependencyType();
|
||||
|
||||
if (descriptor.isStreamAccess()) {
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type,
|
||||
new MultiElementDescriptor(descriptor, false));
|
||||
if (descriptor instanceof StreamDependencyDescriptor) {
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
|
||||
if (autowiredBeanNames != null) {
|
||||
autowiredBeanNames.addAll(matchingBeans.keySet());
|
||||
}
|
||||
return matchingBeans.values().stream();
|
||||
Stream<Object> stream = matchingBeans.keySet().stream()
|
||||
.map(name -> descriptor.resolveCandidate(name, type, this))
|
||||
.filter(bean -> !(bean instanceof NullBean));
|
||||
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
|
||||
stream = stream.sorted(adaptOrderComparator(matchingBeans));
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
else if (type.isArray()) {
|
||||
Class<?> componentType = type.getComponentType();
|
||||
ResolvableType resolvableType = descriptor.getResolvableType();
|
||||
Class<?> resolvedArrayType = resolvableType.resolve();
|
||||
if (resolvedArrayType != null && resolvedArrayType != type) {
|
||||
type = resolvedArrayType;
|
||||
Class<?> resolvedArrayType = resolvableType.resolve(type);
|
||||
if (resolvedArrayType != type) {
|
||||
componentType = resolvableType.getComponentType().resolve();
|
||||
}
|
||||
if (componentType == null) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
|
||||
new MultiElementDescriptor(descriptor, true));
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1255,9 +1301,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
autowiredBeanNames.addAll(matchingBeans.keySet());
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
|
||||
if (getDependencyComparator() != null && result instanceof Object[]) {
|
||||
Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
|
||||
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
|
||||
if (result instanceof Object[]) {
|
||||
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
|
||||
if (comparator != null) {
|
||||
Arrays.sort((Object[]) result, comparator);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1267,7 +1316,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
|
||||
new MultiElementDescriptor(descriptor, true));
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1276,8 +1325,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
|
||||
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
|
||||
if (getDependencyComparator() != null && result instanceof List) {
|
||||
((List<?>) result).sort(adaptDependencyComparator(matchingBeans));
|
||||
if (result instanceof List) {
|
||||
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
|
||||
if (comparator != null) {
|
||||
((List<?>) result).sort(comparator);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1292,7 +1344,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
|
||||
new MultiElementDescriptor(descriptor, true));
|
||||
new MultiElementDescriptor(descriptor));
|
||||
if (matchingBeans.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -1316,7 +1368,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Comparator<Object> adaptDependencyComparator(Map<String, Object> matchingBeans) {
|
||||
private Comparator<Object> adaptDependencyComparator(Map<String, ?> matchingBeans) {
|
||||
Comparator<Object> comparator = getDependencyComparator();
|
||||
if (comparator instanceof OrderComparator) {
|
||||
return ((OrderComparator) comparator).withSourceProvider(
|
||||
@@ -1327,7 +1379,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
|
||||
private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map<String, Object> beans) {
|
||||
private Comparator<Object> adaptOrderComparator(Map<String, ?> matchingBeans) {
|
||||
Comparator<Object> dependencyComparator = getDependencyComparator();
|
||||
OrderComparator comparator = (dependencyComparator instanceof OrderComparator ?
|
||||
(OrderComparator) dependencyComparator : OrderComparator.INSTANCE);
|
||||
return comparator.withSourceProvider(createFactoryAwareOrderSourceProvider(matchingBeans));
|
||||
}
|
||||
|
||||
private OrderComparator.OrderSourceProvider createFactoryAwareOrderSourceProvider(Map<String, ?> beans) {
|
||||
IdentityHashMap<Object, String> instancesToBeanNames = new IdentityHashMap<>();
|
||||
beans.forEach((beanName, instance) -> instancesToBeanNames.put(instance, beanName));
|
||||
return new FactoryAwareOrderSourceProvider(instancesToBeanNames);
|
||||
@@ -1368,15 +1427,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
addCandidateEntry(result, candidate, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
|
||||
if (result.isEmpty()) {
|
||||
boolean multiple = indicatesMultipleBeans(requiredType);
|
||||
// Consider fallback matches if the first pass failed to find anything...
|
||||
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
|
||||
for (String candidate : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
|
||||
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
|
||||
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
|
||||
addCandidateEntry(result, candidate, descriptor, requiredType);
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
if (result.isEmpty() && !multiple) {
|
||||
// Consider self references as a final pass...
|
||||
// but in the case of a dependency collection, not the very same bean itself.
|
||||
for (String candidate : candidateNames) {
|
||||
@@ -1404,7 +1465,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
candidates.put(candidateName, beanInstance);
|
||||
}
|
||||
}
|
||||
else if (containsSingleton(candidateName)) {
|
||||
else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor &&
|
||||
((StreamDependencyDescriptor) descriptor).isOrdered())) {
|
||||
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
|
||||
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
|
||||
}
|
||||
@@ -1635,7 +1697,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
super.resolveCandidate(beanName, requiredType, beanFactory));
|
||||
}
|
||||
};
|
||||
return Optional.ofNullable(doResolveDependency(descriptorToUse, beanName, null, null));
|
||||
Object result = doResolveDependency(descriptorToUse, beanName, null, null);
|
||||
return (result instanceof Optional ? (Optional<?>) result : Optional.ofNullable(result));
|
||||
}
|
||||
|
||||
|
||||
@@ -1696,7 +1759,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
// Lenient fallback: dummy factory in case of original factory not found...
|
||||
return new DefaultListableBeanFactory();
|
||||
DefaultListableBeanFactory dummyFactory = new DefaultListableBeanFactory();
|
||||
dummyFactory.serializationId = this.id;
|
||||
return dummyFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1714,15 +1779,30 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
|
||||
/**
|
||||
* A dependency descriptor marker for multiple elements.
|
||||
* A dependency descriptor for a multi-element declaration with nested elements.
|
||||
*/
|
||||
private static class MultiElementDescriptor extends DependencyDescriptor {
|
||||
private static class MultiElementDescriptor extends NestedDependencyDescriptor {
|
||||
|
||||
public MultiElementDescriptor(DependencyDescriptor original, boolean nested) {
|
||||
public MultiElementDescriptor(DependencyDescriptor original) {
|
||||
super(original);
|
||||
if (nested) {
|
||||
increaseNestingLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A dependency descriptor marker for stream access to multiple elements.
|
||||
*/
|
||||
private static class StreamDependencyDescriptor extends DependencyDescriptor {
|
||||
|
||||
private final boolean ordered;
|
||||
|
||||
public StreamDependencyDescriptor(DependencyDescriptor original, boolean ordered) {
|
||||
super(original);
|
||||
this.ordered = ordered;
|
||||
}
|
||||
|
||||
public boolean isOrdered() {
|
||||
return this.ordered;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1832,25 +1912,21 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Stream<Object> stream() {
|
||||
DependencyDescriptor descriptorToUse = new DependencyDescriptor(this.descriptor) {
|
||||
@Override
|
||||
public boolean isStreamAccess() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return resolveStream(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Object> orderedStream() {
|
||||
return resolveStream(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Stream<Object> resolveStream(boolean ordered) {
|
||||
DependencyDescriptor descriptorToUse = new StreamDependencyDescriptor(this.descriptor, ordered);
|
||||
Object result = doResolveDependency(descriptorToUse, this.beanName, null, null);
|
||||
if (result instanceof Stream) {
|
||||
return (Stream<Object>) result;
|
||||
}
|
||||
else if (result instanceof Collection) {
|
||||
return ((Collection<Object>) result).stream();
|
||||
}
|
||||
else {
|
||||
return (result != null ? Stream.of(result) : Stream.empty());
|
||||
}
|
||||
return (result instanceof Stream ? (Stream<Object>) result : Stream.of(result));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -489,8 +489,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
}
|
||||
|
||||
public void destroySingletons() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Destroying singletons in " + this);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Destroying singletons in " + this);
|
||||
}
|
||||
synchronized (this.singletonObjects) {
|
||||
this.singletonsCurrentlyInDestruction = true;
|
||||
@@ -557,8 +557,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
dependencies = this.dependentBeanMap.remove(beanName);
|
||||
}
|
||||
if (dependencies != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
|
||||
}
|
||||
for (String dependentBeanName : dependencies) {
|
||||
destroySingleton(dependentBeanName);
|
||||
@@ -571,7 +571,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
bean.destroy();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.warn("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -115,7 +115,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
this.destroyMethod = determineDestroyMethod(destroyMethodName);
|
||||
if (this.destroyMethod == null) {
|
||||
if (beanDefinition.isEnforceDestroyMethod()) {
|
||||
throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" +
|
||||
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
|
||||
destroyMethodName + "' on bean with name '" + beanName + "'");
|
||||
}
|
||||
}
|
||||
@@ -242,8 +242,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
}
|
||||
|
||||
if (this.invokeDisposableBean) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
|
||||
}
|
||||
try {
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -259,10 +259,10 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
catch (Throwable ex) {
|
||||
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex);
|
||||
logger.info(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex);
|
||||
logger.info(msg + ": " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,8 +314,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
if (paramTypes.length == 1) {
|
||||
args[0] = Boolean.TRUE;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Invoking destroy method '" + this.destroyMethodName +
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Invoking destroy method '" + this.destroyMethodName +
|
||||
"' on bean with name '" + this.beanName + "'");
|
||||
}
|
||||
try {
|
||||
@@ -341,14 +341,14 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" +
|
||||
this.beanName + "' threw an exception";
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex.getTargetException());
|
||||
logger.info(msg, ex.getTargetException());
|
||||
}
|
||||
else {
|
||||
logger.warn(msg + ": " + ex.getTargetException());
|
||||
logger.info(msg + ": " + ex.getTargetException());
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.warn("Failed to invoke destroy method '" + this.destroyMethodName +
|
||||
logger.info("Failed to invoke destroy method '" + this.destroyMethodName +
|
||||
"' on bean with name '" + this.beanName + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -127,7 +128,11 @@ public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCan
|
||||
if (cacheType) {
|
||||
rbd.targetType = targetType;
|
||||
}
|
||||
if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) {
|
||||
if (descriptor.fallbackMatchAllowed() &&
|
||||
(targetType.hasUnresolvableGenerics() || targetType.resolve() == Properties.class)) {
|
||||
// Fallback matches allow unresolvable generics, e.g. plain HashMap to Map<String,String>;
|
||||
// and pragmatically also java.util.Properties to any Map (since despite formally being a
|
||||
// Map<Object,Object>, java.util.Properties is usually perceived as a Map<String,String>).
|
||||
return true;
|
||||
}
|
||||
// Full check for complex generic type match...
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,8 +38,8 @@ public interface InstantiationStrategy {
|
||||
/**
|
||||
* Return an instance of the bean with the given name in this factory.
|
||||
* @param bd the bean definition
|
||||
* @param beanName the name of the bean when it's created in this context.
|
||||
* The name can be {@code null} if we're autowiring a bean which doesn't
|
||||
* @param beanName the name of the bean when it is created in this context.
|
||||
* The name can be {@code null} if we are autowiring a bean which doesn't
|
||||
* belong to the factory.
|
||||
* @param owner the owning BeanFactory
|
||||
* @return a bean instance for this bean definition
|
||||
@@ -52,8 +52,8 @@ public interface InstantiationStrategy {
|
||||
* Return an instance of the bean with the given name in this factory,
|
||||
* creating it via the given constructor.
|
||||
* @param bd the bean definition
|
||||
* @param beanName the name of the bean when it's created in this context.
|
||||
* The name can be {@code null} if we're autowiring a bean which doesn't
|
||||
* @param beanName the name of the bean when it is created in this context.
|
||||
* The name can be {@code null} if we are autowiring a bean which doesn't
|
||||
* belong to the factory.
|
||||
* @param owner the owning BeanFactory
|
||||
* @param ctor the constructor to use
|
||||
@@ -62,14 +62,14 @@ public interface InstantiationStrategy {
|
||||
* @throws BeansException if the instantiation attempt failed
|
||||
*/
|
||||
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
|
||||
Constructor<?> ctor, @Nullable Object... args) throws BeansException;
|
||||
Constructor<?> ctor, Object... args) throws BeansException;
|
||||
|
||||
/**
|
||||
* Return an instance of the bean with the given name in this factory,
|
||||
* creating it via the given factory method.
|
||||
* @param bd the bean definition
|
||||
* @param beanName the name of the bean when it's created in this context.
|
||||
* The name can be {@code null} if we're autowiring a bean which doesn't
|
||||
* @param beanName the name of the bean when it is created in this context.
|
||||
* The name can be {@code null} if we are autowiring a bean which doesn't
|
||||
* belong to the factory.
|
||||
* @param owner the owning BeanFactory
|
||||
* @param factoryBean the factory bean instance to call the factory method on,
|
||||
@@ -80,7 +80,7 @@ public interface InstantiationStrategy {
|
||||
* @throws BeansException if the instantiation attempt failed
|
||||
*/
|
||||
Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
|
||||
@Nullable Object factoryBean, Method factoryMethod, @Nullable Object... args)
|
||||
@Nullable Object factoryBean, Method factoryMethod, Object... args)
|
||||
throws BeansException;
|
||||
|
||||
}
|
||||
|
||||
+13
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,7 +42,19 @@ public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
|
||||
* @param beanDefinition the merged bean definition for the bean
|
||||
* @param beanType the actual type of the managed bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
|
||||
*/
|
||||
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
|
||||
|
||||
/**
|
||||
* A notification that the bean definition for the specified name has been reset,
|
||||
* and that this post-processor should clear any metadata for the affected bean.
|
||||
* <p>The default implementation is empty.
|
||||
* @param beanName the name of the bean
|
||||
* @since 5.1
|
||||
* @see DefaultListableBeanFactory#resetBeanDefinition
|
||||
*/
|
||||
default void resetBeanDefinition(String beanName) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-6
@@ -247,6 +247,10 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
public int loadBeanDefinitions(EncodedResource encodedResource, @Nullable String prefix)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Loading properties bean definitions from " + encodedResource);
|
||||
}
|
||||
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
try (InputStream is = encodedResource.getResource().getInputStream()) {
|
||||
@@ -257,7 +261,12 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
getPropertiesPersister().load(props, is);
|
||||
}
|
||||
}
|
||||
return registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription());
|
||||
|
||||
int count = registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loaded " + count + " bean definitions from " + encodedResource);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new BeanDefinitionStoreException("Could not parse properties from " + encodedResource.getResource(), ex);
|
||||
@@ -368,8 +377,8 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
}
|
||||
if (sepIdx != -1) {
|
||||
String beanName = nameAndProperty.substring(0, sepIdx);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found bean name '" + beanName + "'");
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Found bean name '" + beanName + "'");
|
||||
}
|
||||
if (!getRegistry().containsBeanDefinition(beanName)) {
|
||||
// If we haven't already registered it...
|
||||
@@ -468,8 +477,8 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering bean definition for bean name '" + beanName + "' with " + pvs);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Registering bean definition for bean name '" + beanName + "' with " + pvs);
|
||||
}
|
||||
|
||||
// Just use default parent if we're not dealing with the parent itself,
|
||||
@@ -501,7 +510,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
* Reads the value of the entry. Correctly interprets bean references for
|
||||
* values that are prefixed with an asterisk.
|
||||
*/
|
||||
private Object readValue(Map.Entry<? ,?> entry) {
|
||||
private Object readValue(Map.Entry<?, ?> entry) {
|
||||
Object val = entry.getValue();
|
||||
if (val instanceof String) {
|
||||
String strVal = (String) val;
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -82,9 +82,10 @@ public class ReplaceOverride extends MethodOverride {
|
||||
if (this.typeIdentifiers.size() != method.getParameterCount()) {
|
||||
return false;
|
||||
}
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
for (int i = 0; i < this.typeIdentifiers.size(); i++) {
|
||||
String identifier = this.typeIdentifiers.get(i);
|
||||
if (!method.getParameterTypes()[i].getName().contains(identifier)) {
|
||||
if (!parameterTypes[i].getName().contains(identifier)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+18
-4
@@ -17,6 +17,7 @@
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -74,6 +75,10 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
@Nullable
|
||||
volatile ResolvableType factoryMethodReturnType;
|
||||
|
||||
/** Package-visible field for caching a unique factory method candidate for introspection. */
|
||||
@Nullable
|
||||
volatile Method factoryMethodToIntrospect;
|
||||
|
||||
/** Common lock for the four constructor fields below. */
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
@@ -335,6 +340,18 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
return (targetType != null ? targetType : ResolvableType.forClass(getBeanClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine preferred constructors to use for default construction, if any.
|
||||
* Constructor arguments will be autowired if necessary.
|
||||
* @return one or more preferred constructors, or {@code null} if none
|
||||
* (in which case the regular no-arg default constructor will be called)
|
||||
* @since 5.1
|
||||
*/
|
||||
@Nullable
|
||||
public Constructor<?>[] getPreferredConstructors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a factory method name that refers to a non-overloaded method.
|
||||
*/
|
||||
@@ -357,10 +374,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
*/
|
||||
@Nullable
|
||||
public Method getResolvedFactoryMethod() {
|
||||
synchronized (this.constructorArgumentLock) {
|
||||
Executable candidate = this.resolvedConstructorOrFactoryMethod;
|
||||
return (candidate instanceof Method ? (Method) candidate : null);
|
||||
}
|
||||
return this.factoryMethodToIntrospect;
|
||||
}
|
||||
|
||||
public void registerExternallyManagedConfigMember(Member configMember) {
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -75,7 +75,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
|
||||
}
|
||||
else {
|
||||
constructorToUse = clazz.getDeclaredConstructor();
|
||||
constructorToUse = clazz.getDeclaredConstructor();
|
||||
}
|
||||
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
|
||||
@Override
|
||||
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
|
||||
final Constructor<?> ctor, @Nullable Object... args) {
|
||||
final Constructor<?> ctor, Object... args) {
|
||||
|
||||
if (!bd.hasMethodOverrides()) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
@@ -114,7 +114,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return (args != null ? BeanUtils.instantiateClass(ctor, args) : BeanUtils.instantiateClass(ctor));
|
||||
return BeanUtils.instantiateClass(ctor, args);
|
||||
}
|
||||
else {
|
||||
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
|
||||
@@ -128,14 +128,14 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
||||
* Instantiation should use the given constructor and parameters.
|
||||
*/
|
||||
protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName,
|
||||
BeanFactory owner, @Nullable Constructor<?> ctor, @Nullable Object... args) {
|
||||
BeanFactory owner, @Nullable Constructor<?> ctor, Object... args) {
|
||||
|
||||
throw new UnsupportedOperationException("Method Injection not supported in SimpleInstantiationStrategy");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
|
||||
@Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {
|
||||
@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
|
||||
|
||||
try {
|
||||
if (System.getSecurityManager() != null) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user