mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
363 Commits
v4.3.0.RC1
..
4.0.x
| Author | SHA1 | Date | |
|---|---|---|---|
| a636420239 | |||
| e68a7ae776 | |||
| 0dedba016c | |||
| 82ee0bef93 | |||
| b8a133d2f4 | |||
| f2e5e5aa86 | |||
| b6083c7f77 | |||
| 8575533081 | |||
| 5528c8a93b | |||
| c9912f0d2d | |||
| 8e14a5d640 | |||
| 230aa07fbb | |||
| b9aa471def | |||
| 39fbfbd343 | |||
| e9d24d5336 | |||
| 4a27a98702 | |||
| 929c596b55 | |||
| 9362d0d547 | |||
| 37713ae9dd | |||
| e118086bd1 | |||
| 0c7fa9e786 | |||
| dc15070877 | |||
| 61a6bc0139 | |||
| c087e51b80 | |||
| 9cb1569e67 | |||
| ac5c361688 | |||
| 328ba7b6d4 | |||
| d97add075a | |||
| c8ff562d1f | |||
| 1d6978afd5 | |||
| 4660e61cf9 | |||
| dfc79721cb | |||
| 90ae073854 | |||
| 50c578c5a0 | |||
| c89d8ec382 | |||
| 7e07f3d083 | |||
| e039185fec | |||
| b45f1aa26f | |||
| 054464709f | |||
| 5ac868036f | |||
| 58bea23f1d | |||
| 98569045cb | |||
| c2ffbf28c5 | |||
| a5e2afc980 | |||
| 5be50c8e5e | |||
| 1214624265 | |||
| 493e8463fa | |||
| 6d3a0d5735 | |||
| 5f58cd3b79 | |||
| 8854c33bf7 | |||
| f093a5f749 | |||
| 1f45dd297d | |||
| 21b8ce5284 | |||
| 2490d1b38d | |||
| ffa4736895 | |||
| 9beae9ae42 | |||
| e42e2330b3 | |||
| b331d65019 | |||
| 1823ce1fad | |||
| 2d0a677117 | |||
| a09bc9b1c1 | |||
| 260b451d5f | |||
| acefd8381d | |||
| 7fa3e65d04 | |||
| 329ba2a913 | |||
| f691618967 | |||
| fde0713a94 | |||
| 4729483804 | |||
| d3ec48f490 | |||
| 2d874d724b | |||
| 91940f212e | |||
| de8645b30c | |||
| c8b8dc5f97 | |||
| aa82da8507 | |||
| 16a4fe70f2 | |||
| 6117311906 | |||
| 6e5711a7fb | |||
| 15c8987cc4 | |||
| 0e907764a4 | |||
| a305bf7ad1 | |||
| e16f21c281 | |||
| 7507560e75 | |||
| a1c0905a7c | |||
| 6f9d7da59e | |||
| 47ed4d634b | |||
| da2c30cd0c | |||
| a7eeedaf6a | |||
| 578c3dd853 | |||
| 9758bc7833 | |||
| c672678423 | |||
| ac4103d1b9 | |||
| d23b033f61 | |||
| c74bad6e07 | |||
| f41e0bc796 | |||
| c7b6b72e73 | |||
| 1df8133237 | |||
| 43d40187d9 | |||
| b91cab1fde | |||
| d46c3fc7bf | |||
| 3267e5aa33 | |||
| 251970a2f9 | |||
| 901346eb7d | |||
| 1ffefcb548 | |||
| 0c680d6d03 | |||
| b87329cda7 | |||
| f21c8c37fb | |||
| 50e50d0c18 | |||
| 205e681295 | |||
| 29abca5399 | |||
| 60d5ff8dd5 | |||
| d2e8b7e6ee | |||
| 7d55715213 | |||
| d07230cf6a | |||
| bf881e4544 | |||
| 36a1d6242e | |||
| 10d4888408 | |||
| f8b729aa5f | |||
| b39e66b897 | |||
| 64849a46b4 | |||
| afb0342924 | |||
| bea9f3ff76 | |||
| 31094f3ef6 | |||
| d765698ac3 | |||
| d081a4530c | |||
| 97bd0ccfec | |||
| 8543a5548e | |||
| d2ef6dcb8d | |||
| bff2bf2cdb | |||
| 72d62a7113 | |||
| e1a01d4c3c | |||
| b7726ff48c | |||
| a52ff46fea | |||
| eb3509a37c | |||
| 93ad7f8def | |||
| 54ba5c5e7b | |||
| 249c688e9b | |||
| e324c2ab4a | |||
| 39a23660fa | |||
| 25971d9927 | |||
| 379e5abd83 | |||
| 8fb7b694dd | |||
| 21d0ce5af8 | |||
| fb452fad7c | |||
| 2dd2b7175f | |||
| f418e6e981 | |||
| 5e2b9b6f07 | |||
| a95a3ae4ec | |||
| 0c0d23d0f4 | |||
| a31ebb6c1e | |||
| 42c090efa4 | |||
| 035a9b91d2 | |||
| a7492fa55b | |||
| ecf23ff6cd | |||
| 4129f00a02 | |||
| e2d71a8ccd | |||
| 1034b0dae2 | |||
| c08ded769a | |||
| d61353db51 | |||
| 96efafef97 | |||
| fbf24a927d | |||
| f2eea9d911 | |||
| cac0683dab | |||
| 9ad6618207 | |||
| 84a4433898 | |||
| 44fac40a2f | |||
| 6e95b2613e | |||
| fca72f6b65 | |||
| 0dca31c39b | |||
| d45f743248 | |||
| acbd61b87a | |||
| dcb83c2daf | |||
| 5342d92db7 | |||
| 7af1e002bd | |||
| abd5f18e85 | |||
| 940ae0c528 | |||
| 5f77dce1ee | |||
| 0ef17a2f2c | |||
| 452260316e | |||
| c0815407bb | |||
| 845528a6cb | |||
| ed88155f55 | |||
| a3a76d8c15 | |||
| 10a039000b | |||
| 7de42efaf2 | |||
| 7dcc01e69b | |||
| adb73d5f35 | |||
| 7eee7d2e30 | |||
| d72ee809b7 | |||
| 31a251e44a | |||
| ce6adfbe35 | |||
| 60d3a7f300 | |||
| 6dbb465585 | |||
| 47de943926 | |||
| 0164f8691a | |||
| 077c624b73 | |||
| dae81fd5e6 | |||
| 837f27851f | |||
| c3b992c5c4 | |||
| f8ab4f6980 | |||
| 77406eded8 | |||
| 977c5ca439 | |||
| ede2150544 | |||
| 07edf11e21 | |||
| f27b9498be | |||
| e9ecaf6f4a | |||
| 5092414842 | |||
| 6438209557 | |||
| 7396210d40 | |||
| b9935e9fe3 | |||
| 86ea3059b6 | |||
| 4384c1ae50 | |||
| 347b7313b8 | |||
| 3fb05017a1 | |||
| 48f753f368 | |||
| c16032b98a | |||
| c32d5592c7 | |||
| 5f695a47db | |||
| 74c878ee0e | |||
| 178d58cc75 | |||
| 7b38b41bf5 | |||
| 6403479902 | |||
| 5af1a691bc | |||
| 9f967b1d81 | |||
| e50507206f | |||
| c73ac075c4 | |||
| 0bf0901b8f | |||
| 7d94b5e853 | |||
| 8ddbbc2e67 | |||
| 0a34f86333 | |||
| a0c86ae455 | |||
| 0761ee99ae | |||
| 9054f4fb58 | |||
| 41e78d0f50 | |||
| 526d5ba253 | |||
| 40c203ca71 | |||
| d18fc53148 | |||
| 618771d59d | |||
| 87077d3fad | |||
| c0c3618906 | |||
| 0405bb401a | |||
| e3e71ba92a | |||
| d4e1b9eb4c | |||
| 44ee51a6c9 | |||
| ba6d187b5c | |||
| 54636b3f7c | |||
| 545c28fd4e | |||
| 95a7bfd327 | |||
| ccebbf74ec | |||
| c350080f99 | |||
| 6b9738fd68 | |||
| 1120680c65 | |||
| a2ef2c9d3e | |||
| 1bbc032071 | |||
| c70a81a805 | |||
| 3c709a763d | |||
| 7d78c65187 | |||
| 748167bfa3 | |||
| 3e70013b55 | |||
| ea9ad4ee9b | |||
| 482eff81e1 | |||
| c706cbbed4 | |||
| 7bc38acbf6 | |||
| 297e4eec36 | |||
| 235b65d103 | |||
| 8a28645dd6 | |||
| f94ded830d | |||
| ad8f17b6af | |||
| 261520cea0 | |||
| 00aa40b8da | |||
| ac9b64e528 | |||
| 1e7fade89e | |||
| 3c58be05a5 | |||
| ef290ff95c | |||
| ae45794451 | |||
| fccec210b4 | |||
| 96da77ef75 | |||
| c9417d0610 | |||
| 085e52fc31 | |||
| 8f175046c8 | |||
| c1dbd9f150 | |||
| 42a35ef3be | |||
| 21fd68150a | |||
| d20259be1d | |||
| 6ca921021c | |||
| eab9d24c31 | |||
| 15749c2a9d | |||
| 93b0f0b126 | |||
| 27b2ed1614 | |||
| 790d62bcb1 | |||
| 563476f57c | |||
| 79de45b805 | |||
| 63a868dafb | |||
| 1afdd9bd75 | |||
| d0c839f0eb | |||
| 744727b8aa | |||
| 9fbb7394e2 | |||
| 80cb0c4e5b | |||
| 5c4804f4a4 | |||
| a679f3e7a3 | |||
| bd5b3749c5 | |||
| 89398b0811 | |||
| a87c9b8c5c | |||
| d0f9853769 | |||
| bed739ce92 | |||
| cb712afa97 | |||
| c97c246940 | |||
| 4196e6c96f | |||
| 59cef3ce81 | |||
| c8ea80d7ed | |||
| 656fc52ff9 | |||
| a4d6f8473e | |||
| 443fb8e4ee | |||
| 95b1cb7173 | |||
| 51fb485181 | |||
| f16e6c4105 | |||
| 4dbc0c296c | |||
| d71d38bfaf | |||
| eb28259371 | |||
| 7ae6a60f43 | |||
| d3c9a31e9a | |||
| 5aa126600f | |||
| 2f15f72fcc | |||
| d5aacdefd9 | |||
| e379e77b96 | |||
| 9c45755890 | |||
| 5962fc2590 | |||
| 1b59b4eb26 | |||
| f6b89c2ca9 | |||
| 82c32db5a1 | |||
| 52f580149f | |||
| 271fe4f554 | |||
| 02e8198283 | |||
| 090ab4bb6d | |||
| 18ef1d4f76 | |||
| d9cb44527c | |||
| 8e44521ec4 | |||
| d28c6d8bdb | |||
| c9432ce499 | |||
| 2d8e0c8f87 | |||
| 03ae8eeb95 | |||
| 9230b38aea | |||
| d5ce30f360 | |||
| 428aee5b72 | |||
| f7a17added | |||
| 196f629a20 | |||
| 7135e729e2 | |||
| 21874627d2 | |||
| 3ab88b857b | |||
| 294545d07a | |||
| 38cd79047a | |||
| 8a779c32d5 | |||
| 7ba31dee45 | |||
| 1c45d7573c | |||
| f014bbb5cf | |||
| d1030b798d | |||
| d628025f13 | |||
| 30ea1a3475 | |||
| 7b014eaa55 | |||
| e21c47d4ce | |||
| 632ae6a4df | |||
| 989f6194b6 | |||
| 17bf5b991f | |||
| cd9d7cfe4f |
@@ -1,23 +0,0 @@
|
||||
Juergen Hoeller <jhoeller@pivotal.io> jhoeller <jhoeller@vmware.com>
|
||||
<jhoeller@pivotal.io> <jhoeller@vmware.com>
|
||||
<jhoeller@pivotal.io> <jhoeller@gopivotal.com>
|
||||
<rstoyanchev@pivotal.io> <rstoyanchev@vmware.com>
|
||||
<rstoyanchev@pivotal.io> <rstoyanchev@gopivotal.com>
|
||||
<pwebb@pivotal.io> <pwebb@vmware.com>
|
||||
<pwebb@pivotal.io> <pwebb@gopivotal.com>
|
||||
<cbeams@pivotal.io> <cbeams@vmware.com>
|
||||
<cbeams@pivotal.io> <cbeams@gopivotal.com>
|
||||
<cbeams@pivotal.io> <cbeams@gmail.com>
|
||||
<apoutsma@pivotal.io> <apoutsma@vmware.com>
|
||||
<apoutsma@pivotal.io> <apoutsma@gopivotal.com>
|
||||
<apoutsma@pivotal.io> <poutsma@mac.com>
|
||||
<ogierke@pivotal.io> <ogierke@vmware.com>
|
||||
<ogierke@pivotal.io> <ogierke@gopivotal.com>
|
||||
<dsyer@pivotal.io> <dsyer@vmware.com>
|
||||
<dsyer@pivotal.io> <dsyer@gopivotal.com>
|
||||
<dsyer@pivotal.io> <david_syer@hotmail.com>
|
||||
<aclement@pivotal.io> <aclement@vmware.com>
|
||||
<aclement@pivotal.io> <aclement@gopivotal.com>
|
||||
<aclement@pivotal.io> <andrew.clement@gmail.com>
|
||||
<dmitry.katsubo@gmail.com> <dmitry.katsubo@gmai.com>
|
||||
Nick Williams <nicholas@nicholaswilliams.net> Nicholas Williams <nicholas@nicholaswilliams.net>
|
||||
@@ -1,44 +0,0 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open
|
||||
and welcoming community, we pledge to respect all people who contribute through reporting
|
||||
issues, posting feature requests, updating documentation, submitting pull requests or
|
||||
patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for
|
||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments,
|
||||
commits, code, wiki edits, issues, and other contributions that are not aligned to this
|
||||
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
|
||||
that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
|
||||
consistently applying these principles to every aspect of managing this project. Project
|
||||
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
|
||||
from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an
|
||||
individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
||||
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
|
||||
be reviewed and investigated and will result in a response that is deemed necessary and
|
||||
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
|
||||
+22
-43
@@ -6,10 +6,6 @@ to expect from the Spring team when evaluating your submission._
|
||||
_Please refer back to this document as a checklist before issuing any pull
|
||||
request; this will save time for everyone!_
|
||||
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Take Your First Steps
|
||||
|
||||
### Understand the basics
|
||||
@@ -17,15 +13,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
excellent [help documentation][] first.
|
||||
|
||||
### Search Stack Overflow first; discuss if necessary
|
||||
|
||||
If you're unsure why something isn't working or wondering if there is a better
|
||||
way of doing it please check on Stack Overflow first and if necessary start
|
||||
a discussion. This is the official list of
|
||||
[Spring project tags](https://spring.io/questions). In short the issue tracker
|
||||
should be used to report issues and make feature requests.
|
||||
|
||||
### Search JIRA; create an issue if necessary
|
||||
### Search JIRA first; create an issue if necessary
|
||||
|
||||
Is there already an issue that addresses your concern? Do a bit of searching
|
||||
in our [JIRA issue tracker][] to see if you can find something similar. If you
|
||||
@@ -33,18 +22,10 @@ do not find something similar, please create a new JIRA issue before submitting
|
||||
a pull request unless the change is truly trivial -- for example: typo fixes,
|
||||
removing compiler warnings, etc.
|
||||
|
||||
### Discuss non-trivial contribution ideas with committers
|
||||
|
||||
If you're considering anything more than correcting a typo or fixing a minor
|
||||
bug, please discuss it on the [spring-framework-contrib][] mailing list before
|
||||
submitting a pull request. We're happy to provide guidance, but please spend an
|
||||
hour or two researching the subject on your own, including searching the mailing
|
||||
list for prior discussions.
|
||||
|
||||
### Sign the Individual Contributor License Agreement (ICLA)
|
||||
### Sign the Contributor License Agreement
|
||||
|
||||
If you have not previously done so, please fill out and submit the
|
||||
[Spring ICLA form][]. You'll receive a token when this process is complete.
|
||||
[SpringSource CLA form][]. You'll receive a token when this process is complete.
|
||||
Keep track of this; you may be asked for it later!
|
||||
|
||||
Note that emailing/postal mailing a signed copy is _not_ necessary. Submission
|
||||
@@ -53,8 +34,8 @@ of the web form is all that is required.
|
||||
Once you've completed the web form, simply add the following in a comment on
|
||||
your pull request:
|
||||
|
||||
I have signed and agree to the terms of the Spring Individual Contributor
|
||||
License Agreement.
|
||||
I have signed and agree to the terms of the SpringSource Individual
|
||||
Contributor License Agreement.
|
||||
|
||||
You do not need to include your token/id. Please add the above statement to all
|
||||
future pull requests as well, simply so that the Spring Framework team knows
|
||||
@@ -104,7 +85,7 @@ present in the framework.
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -125,18 +106,16 @@ package ...;
|
||||
### Update Apache license header in modified files as necessary
|
||||
|
||||
Always check the date range in the license header. For example, if you've
|
||||
modified a file in 2015 whose header still reads:
|
||||
modified a file in 2014 whose header still reads:
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2015 accordingly:
|
||||
Then be sure to update it to 2014 accordingly:
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
@@ -148,7 +127,7 @@ For example:
|
||||
* ...
|
||||
*
|
||||
* @author First Last
|
||||
* @since 4.2.3
|
||||
* @since 4.0
|
||||
* @see ...
|
||||
*/
|
||||
```
|
||||
@@ -200,11 +179,11 @@ intend to submit as pull requests. For example, this is not acceptable:
|
||||
Author: Nickname <user@mail.com>
|
||||
|
||||
Rather, please include your first and last name, properly capitalized, as
|
||||
submitted against the Spring Individual Contributor License Agreement (ICLA):
|
||||
submitted against the SpringSource contributor license agreement:
|
||||
|
||||
Author: First Last <user@mail.com>
|
||||
|
||||
This helps ensure traceability against the ICLA and also goes a long way to
|
||||
This helps ensure traceability against the CLA and also goes a long way to
|
||||
ensuring useful output from tools like `git shortlog` and others.
|
||||
|
||||
You can configure this via the account admin area in GitHub (useful for
|
||||
@@ -247,16 +226,16 @@ Most importantly, please format your commit messages in the following way
|
||||
Issue: SPR-1234, SPR-1235
|
||||
|
||||
|
||||
1. Use imperative statements in the subject line, e.g. "Fix broken Javadoc link".
|
||||
1. Use imperative statements in the subject line, e.g. "Fix broken Javadoc link"
|
||||
1. Begin the subject line with a capitalized verb, e.g. "Add, Prune, Fix,
|
||||
Introduce, Avoid, etc."
|
||||
1. Do not end the subject line with a period.
|
||||
1. Restrict the subject line to 50 characters or less if possible.
|
||||
1. Wrap lines in the body at 72 characters or less.
|
||||
1. Do not end the subject line with a period
|
||||
1. Restrict the subject line to 50 characters or less if possible
|
||||
1. Wrap lines in the body at 72 characters or less
|
||||
1. Mention associated JIRA issue(s) at the end of the commit comment, prefixed
|
||||
with "Issue: " as above.
|
||||
with "Issue: " as above
|
||||
1. In the body of the commit message, explain how things worked before this
|
||||
commit, what has changed, and how things work now.
|
||||
commit, what has changed, and how things work now
|
||||
|
||||
For examples of this style, issue a `git log --author=cbeams` in the
|
||||
`spring-framework` git repository. For convenience, here are several such commits:
|
||||
@@ -287,9 +266,9 @@ In the body:
|
||||
mechanisms in the framework insufficient? Make a case that this is a
|
||||
general-purpose problem and that yours is a general-purpose solution, etc.
|
||||
1. Add any additional information and ask questions; start a conversation or
|
||||
continue one from JIRA.
|
||||
1. Mention the JIRA issue ID.
|
||||
1. Also mention that you have submitted the ICLA as described above.
|
||||
continue one from JIRA
|
||||
1. Mention the JIRA issue ID
|
||||
1. Also mention that you have submitted the CLA as described above
|
||||
|
||||
Note that for pull requests containing a single commit, GitHub will default the
|
||||
subject line and body of the pull request to match the subject line and body of
|
||||
@@ -320,7 +299,7 @@ need to issue a new pull request when asked to make changes.
|
||||
[help documentation]: http://help.github.com/send-pull-requests
|
||||
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
|
||||
[spring-framework-contrib]: https://groups.google.com/forum/#!forum/spring-framework-contrib
|
||||
[Spring ICLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[SpringSource CLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
|
||||
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
|
||||
[Rewriting History section of Pro Git]: http://git-scm.com/book/en/Git-Tools-Rewriting-History
|
||||
|
||||
@@ -1,33 +1,30 @@
|
||||
## Spring Framework
|
||||
The Spring Framework provides a comprehensive programming and configuration
|
||||
model for modern Java-based enterprise applications -- on any kind of deployment
|
||||
model for modern Java-based enterprise applications - on any kind of deployment
|
||||
platform. A key element of Spring is infrastructural support at the application
|
||||
level: Spring focuses on the "plumbing" of enterprise applications so that teams
|
||||
can focus on application-level business logic, without unnecessary ties to
|
||||
specific deployment environments.
|
||||
|
||||
The framework also serves as the foundation for [Spring Integration][], [Spring Batch][]
|
||||
and the rest of the Spring [family of projects][]. Browse the repositories under
|
||||
the [Spring organization][] on GitHub for a full list.
|
||||
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
The framework also serves as the foundation for [Spring Integration][], [Spring
|
||||
Batch][] and the rest of the Spring [family of projects][]. Browse the repositories
|
||||
under the [Spring organization][] on GitHub for a full list.
|
||||
|
||||
## Downloading Artifacts
|
||||
See [downloading Spring artifacts][] for Maven repository information. Unable to
|
||||
use Maven or other transitive dependency management tools?
|
||||
See [building a distribution with dependencies][].
|
||||
use Maven or other transitive dependency management tools? See [building a
|
||||
distribution with dependencies][].
|
||||
|
||||
## Documentation
|
||||
See the current [Javadoc][] and [reference docs][].
|
||||
|
||||
## Getting Support
|
||||
Check out the [spring][spring tags] tags on [Stack Overflow][]. [Commercial support][]
|
||||
Check out the [Spring forums][] and the [spring][spring tag] and
|
||||
[spring-mvc][spring-mvc tag] tags on [Stack Overflow][]. [Commercial support][]
|
||||
is available too.
|
||||
|
||||
## Issue Tracking
|
||||
Report issues via the [Spring Framework JIRA][]. Understand our issue management
|
||||
Report issues via the [Spring Framework JIRA]. Understand our issue management
|
||||
process by reading about [the lifecycle of an issue][]. Think you've found a
|
||||
bug? Please consider submitting a reproduction project via the
|
||||
[spring-framework-issues][] GitHub repository. The [readme][] there provides
|
||||
@@ -40,7 +37,7 @@ a cross-platform, self-contained bootstrap mechanism for the build.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
[Git][] and [JDK 8 update 20 or later][JDK8 build]
|
||||
[Git][] and [OpenJDK 8 early access build 100 or later][JDK8 build]
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder
|
||||
extracted from the JDK download.
|
||||
@@ -80,7 +77,9 @@ The Spring Framework is released under version 2.0 of the [Apache License][].
|
||||
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
|
||||
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
|
||||
[spring tags]: http://spring.io/questions
|
||||
[Spring forums]: http://forum.spring.io/
|
||||
[spring tag]: http://stackoverflow.com/questions/tagged/spring
|
||||
[spring-mvc tag]: http://stackoverflow.com/questions/tagged/spring-mvc
|
||||
[Stack Overflow]: http://stackoverflow.com/faq
|
||||
[Commercial support]: http://spring.io/services
|
||||
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
|
||||
@@ -90,13 +89,13 @@ The Spring Framework is released under version 2.0 of the [Apache License][].
|
||||
[Gradle]: http://gradle.org
|
||||
[`./gradlew`]: http://vimeo.com/34436402
|
||||
[Git]: http://help.github.com/set-up-git-redirect
|
||||
[JDK8 build]: http://www.oracle.com/technetwork/java/javase/downloads
|
||||
[JDK8 build]: http://jdk8.java.net/download.html
|
||||
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Pull requests]: http://help.github.com/send-pull-requests
|
||||
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@SpringFramework]: https://twitter.com/springframework
|
||||
[@SpringCentral]: https://twitter.com/springcentral
|
||||
[team members]: https://twitter.com/springframework/lists/team/members
|
||||
[team members]: https://twitter.com/springframework/team/members
|
||||
[The Spring Blog]: http://spring.io/blog/
|
||||
[news feed]: http://spring.io/blog/category/news
|
||||
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
+247
-445
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -68,8 +68,8 @@ class MergePlugin implements Plugin<Project> {
|
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
|
||||
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
|
||||
project.eclipse.classpath.plusConfigurations += [runtimeMerge]
|
||||
project.idea.module.scopes.PROVIDED.plus += runtimeMerge
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
@@ -132,9 +132,8 @@ class MergePlugin implements Plugin<Project> {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100 + index, intoConfiguration, mapping.scope)
|
||||
mapping.priority + 100, intoConfiguration, mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.3.0.RC1
|
||||
version=4.0.10.BUILD-SNAPSHOT
|
||||
|
||||
+8
-6
@@ -5,19 +5,19 @@ import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||
apply plugin: "propdeps-eclipse"
|
||||
apply plugin: "propdeps-idea"
|
||||
|
||||
// Until eclipse fully supports Java 8 use 1.7 source level
|
||||
eclipse.jdt {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
sourceCompatibility = 1.7
|
||||
targetCompatibility = 1.7
|
||||
}
|
||||
|
||||
// Replace classpath entries with project dependencies (GRADLE-1116)
|
||||
// http://issues.gradle.org/browse/GRADLE-1116
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
||||
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
||||
projectOutputDependencies.each { entry ->
|
||||
def matcher = (entry.path =~ regexp)
|
||||
if (matcher) {
|
||||
if(matcher) {
|
||||
def projectName = matcher[0][1]
|
||||
def path = "/${projectName}"
|
||||
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
||||
@@ -58,9 +58,10 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||
}
|
||||
}
|
||||
|
||||
// Allow projects to be used as WTP modules
|
||||
// Allow projects to be used as WPT modules
|
||||
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
|
||||
|
||||
|
||||
// Include project specific settings
|
||||
task eclipseSettings(type: Copy) {
|
||||
from rootProject.files(
|
||||
@@ -85,8 +86,8 @@ task eclipseJdtPrepare(type: Copy) {
|
||||
}
|
||||
|
||||
task cleanEclipseJdtUi(type: Delete) {
|
||||
delete project.file(".settings/org.eclipse.jdt.core.prefs")
|
||||
delete project.file(".settings/org.eclipse.jdt.ui.prefs")
|
||||
delete project.file("org.eclipse.jdt.core.prefs")
|
||||
delete project.file(".settings/org.eclipse.wst.common.component")
|
||||
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
|
||||
}
|
||||
@@ -97,6 +98,7 @@ tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||
|
||||
|
||||
// Filter 'build' folder
|
||||
|
||||
eclipse.project.file.withXml {
|
||||
def node = it.asNode()
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@ def customizePom(pom, gradleProject) {
|
||||
url = "https://github.com/spring-projects/spring-framework"
|
||||
organization {
|
||||
name = "Spring IO"
|
||||
url = "http://projects.spring.io/spring-framework"
|
||||
url = "https://projects.spring.io/spring-framework"
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name "The Apache Software License, Version 2.0"
|
||||
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
url "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
distribution "repo"
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ def customizePom(pom, gradleProject) {
|
||||
developer {
|
||||
id = "jhoeller"
|
||||
name = "Juergen Hoeller"
|
||||
email = "jhoeller@pivotal.io"
|
||||
email = "jhoeller@gopivotal.com"
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Mon Mar 14 14:42:52 CET 2016
|
||||
#Wed Apr 30 13:06:57 CEST 2014
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
|
||||
|
||||
@@ -43,6 +43,11 @@ case "`uname`" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
@@ -57,9 +62,9 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@@ -110,7 +115,6 @@ fi
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
|
||||
Vendored
+1
-1
@@ -47,7 +47,7 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
@@ -17,7 +17,7 @@ echo been tested against STS %STS_TEST_VERSION%), but at the minimum you will
|
||||
echo need Eclipse + AJDT.
|
||||
echo.
|
||||
echo If you need to download and install STS, please do that now by
|
||||
echo visiting http://spring.io/tools/sts/all
|
||||
echo visiting https://spring.io/tools/sts/all
|
||||
echo.
|
||||
echo Otherwise, press enter and we'll begin.
|
||||
|
||||
|
||||
+36
-51
@@ -1,37 +1,22 @@
|
||||
STS_TEST_VERSION='2.9.2.RELEASE'
|
||||
|
||||
cd `dirname $0`
|
||||
clear
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Spring Framework - Eclipse/STS Project Import Guide
|
||||
-----------------------------------------------------------------------
|
||||
Spring Framework Eclipse/STS project import guide
|
||||
|
||||
This script will guide you through the process of importing the Spring
|
||||
Framework projects into Eclipse or the Spring Tool Suite (STS). It is
|
||||
recommended that you have a recent version of Eclipse or STS. As a bare
|
||||
minimum you will need Eclipse with full Java 8 support, the AspectJ
|
||||
Development Tools (AJDT), and the Groovy Compiler.
|
||||
This script will guide you through the process of importing the
|
||||
Spring Framework sources into Eclipse/STS. It is recommended that you
|
||||
have a recent version of the SpringSource Tool Suite (this script has
|
||||
been tested against STS $STS_TEST_VERSION), but at the minimum you will
|
||||
need Eclipse + AJDT.
|
||||
|
||||
This script has been tested against:
|
||||
If you need to download and install STS, please do that now by
|
||||
visiting https://spring.io/tools/sts/all
|
||||
|
||||
- STS: 3.6.3.RELEASE (Eclipse Luna SR1 4.4.1)
|
||||
- AJDT: 2.2.4.e44x-20141118-0700 (Luna 4.4)
|
||||
|
||||
If you need to download and install Eclipse or STS, please do that now
|
||||
by visiting one of the following sites:
|
||||
|
||||
- Eclipse downloads: http://download.eclipse.org/eclipse/downloads
|
||||
- STS downloads: http://spring.io/tools/sts/all
|
||||
- STS nightly builds: http://dist.springsource.com/snapshot/STS/nightly-distributions.html
|
||||
|
||||
If you need to install a recent CI build for AJDT (i.e., so that the
|
||||
spring-aspects module properly compiles in Eclipse/STS), click on the
|
||||
"Artifacts" tab of a successful CI build and copy the link to the
|
||||
"update site" which you can then use to install or update AJDT within
|
||||
Eclipse/STS.
|
||||
|
||||
- AJDT CI builds: https://build.spring.io/browse/AJDT-AE44
|
||||
|
||||
Once Eclipse/STS is installed, press enter, and we'll begin.
|
||||
Otherwise, press enter and we'll begin.
|
||||
EOM
|
||||
|
||||
read
|
||||
@@ -46,14 +31,14 @@ COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------
|
||||
STEP 1: Generate subproject Eclipse metadata
|
||||
|
||||
The first step will be to generate Eclipse project metadata for each of
|
||||
the spring-* subprojects. This happens via the built-in "Gradle wrapper"
|
||||
script (./gradlew in this directory). If this is your first time using
|
||||
the Gradle wrapper, this step may take a few minutes while a Gradle
|
||||
distribution is downloaded for you.
|
||||
The first step will be to generate Eclipse project metadata for each
|
||||
of the spring-* subprojects. This happens via the built-in
|
||||
"Gradle wrapper" script (./gradlew in this directory). If this is your
|
||||
first time using the Gradle wrapper, this step may take a few minutes
|
||||
while a Gradle distribution is downloaded for you.
|
||||
|
||||
The command run will be:
|
||||
|
||||
@@ -68,16 +53,16 @@ $COMMAND || exit
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------
|
||||
STEP 2: Import subprojects into Eclipse/STS
|
||||
|
||||
Within Eclipse/STS, do the following:
|
||||
|
||||
- File > Import... > Existing Projects into Workspace
|
||||
- When prompted for the 'root directory', provide $PWD.
|
||||
- Press enter. You will see the modules show up under "Projects".
|
||||
- All projects should be selected/checked. Click Finish.
|
||||
- When the project import is complete, you should have no errors.
|
||||
File > Import... > Existing Projects into Workspace
|
||||
> When prompted for the 'root directory', provide $PWD
|
||||
> Press enter. You will see the modules show up under "Projects"
|
||||
> All projects should be selected/checked. Click Finish.
|
||||
> When the project import is complete, you should have no errors.
|
||||
|
||||
When the above is complete, return here and press the enter key.
|
||||
EOM
|
||||
@@ -88,13 +73,13 @@ COMMAND="./gradlew :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
------------------------------------------------------------------------
|
||||
STEP 3: Generate root project Eclipse metadata
|
||||
-----------------------------------------------------------------------
|
||||
STEP 3: generate root project Eclipse metadata
|
||||
|
||||
Unfortunately, Eclipse does not support importing project hierarchies,
|
||||
so we had to skip root project metadata generation during step 1. In
|
||||
this step we simply generate root project metadata so that you can
|
||||
import it in the next step.
|
||||
Unfortunately, Eclipse does not allow for importing project
|
||||
hierarchies, so we had to skip root project metadata generation in the
|
||||
during step 1. In this step we simply generate root project metadata
|
||||
so you can import it in the next step.
|
||||
|
||||
The command run will be:
|
||||
|
||||
@@ -108,11 +93,11 @@ read
|
||||
$COMMAND || exit
|
||||
|
||||
cat <<EOM
|
||||
------------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------
|
||||
STEP 4: Import root project into Eclipse/STS
|
||||
|
||||
Follow the project import steps listed in step 2 above to import the
|
||||
root "spring" project.
|
||||
root project.
|
||||
|
||||
Press enter when complete, and move on to the final step.
|
||||
EOM
|
||||
@@ -120,14 +105,14 @@ EOM
|
||||
read
|
||||
|
||||
cat <<EOM
|
||||
------------------------------------------------------------------------
|
||||
-----------------------------------------------------------------------
|
||||
STEP 5: Enable Git support for all projects
|
||||
|
||||
- In the Eclipse/STS Package Explorer, select all spring* projects.
|
||||
- Right-click to open the context menu and select Team > Share Project...
|
||||
- In the Share Project dialog that appears, select Git and press Next.
|
||||
- Check "Use or create repository in parent folder of project".
|
||||
- Click Finish.
|
||||
- In the Share Project dialog that appears, select Git and press Next
|
||||
- Check "Use or create repository in parent folder of project"
|
||||
- Click Finish
|
||||
|
||||
When complete, you'll have Git support enabled for all projects.
|
||||
|
||||
|
||||
+7
-7
@@ -1,21 +1,21 @@
|
||||
The following has been tested against Intellij IDEA 13.1
|
||||
The following has been tested against Intellij IDEA 12.0
|
||||
|
||||
## Steps
|
||||
|
||||
_Within your locally cloned spring-framework working directory:_
|
||||
|
||||
1. Pre-compile `spring-oxm` with `./gradlew cleanIdea :spring-oxm:compileTestJava`
|
||||
2. Import into IDEA (File->import project->import from external model->Gradle)
|
||||
3. Set the Project JDK as appropriate (1.8+)
|
||||
4. Exclude the `spring-aspects` module (Go to File->Project Structure->Modules)
|
||||
1. Generate IDEA metadata with `./gradlew :spring-oxm:compileTestJava cleanIdea idea`
|
||||
2. Import into IDEA as usual
|
||||
3. Set the Project JDK as appropriate
|
||||
4. Add git support
|
||||
5. Code away
|
||||
|
||||
## Known issues
|
||||
|
||||
1. `spring-oxm` should be pre-compiled since it's using repackaged dependencies (see *RepackJar tasks)
|
||||
1. Those steps don't work currently for Intellij IDEA 13+
|
||||
2. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
|
||||
See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the 'spring-aspects'
|
||||
should be excluded from the overall project to avoid compilation errors.
|
||||
module has been excluded from the overall project to avoid compilation errors.
|
||||
3. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
|
||||
likely need to set the following VM options to avoid out of memory errors:
|
||||
|
||||
+1
-2
@@ -15,14 +15,13 @@ include "spring-jms"
|
||||
include "spring-messaging"
|
||||
include "spring-orm"
|
||||
include "spring-orm-hibernate4"
|
||||
include "spring-orm-hibernate5"
|
||||
include "spring-oxm"
|
||||
include "spring-test"
|
||||
include "spring-tx"
|
||||
include "spring-web"
|
||||
include "spring-webmvc"
|
||||
include "spring-webmvc-portlet"
|
||||
include "spring-webmvc-tiles2"
|
||||
include "spring-webmvc-tiles3"
|
||||
include "spring-websocket"
|
||||
include "spring-framework-bom"
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.aop;
|
||||
|
||||
/**
|
||||
* Tag interface for Advice. Implementations can be any type
|
||||
* of advice, such as Interceptors.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @version $Id: Advice.java,v 1.1 2004/03/19 17:02:16 johnsonr Exp $
|
||||
*/
|
||||
public interface Advice {
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.aop;
|
||||
|
||||
/**
|
||||
* Superclass for all AOP infrastructure exceptions.
|
||||
* Unchecked, as such exceptions are fatal and end user
|
||||
* code shouldn't be forced to catch them.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Bob Lee
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructor for AspectException.
|
||||
* @param message the exception message
|
||||
*/
|
||||
public AspectException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for AspectException.
|
||||
* @param message the exception message
|
||||
* @param cause the root cause, if any
|
||||
*/
|
||||
public AspectException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* Intercepts the construction of a new object.
|
||||
*
|
||||
* <p>The user should implement the {@link
|
||||
* #construct(ConstructorInvocation)} method to modify the original
|
||||
* behavior. E.g. the following class implements a singleton
|
||||
* interceptor (allows only one unique instance for the intercepted
|
||||
* class):
|
||||
*
|
||||
* <pre class=code>
|
||||
* class DebuggingInterceptor implements ConstructorInterceptor {
|
||||
* Object instance=null;
|
||||
*
|
||||
* Object construct(ConstructorInvocation i) throws Throwable {
|
||||
* if(instance==null) {
|
||||
* return instance=i.proceed();
|
||||
* } else {
|
||||
* throw new Exception("singleton does not allow multiple instance");
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface ConstructorInterceptor extends Interceptor {
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the construction of a new object. Polite implementations
|
||||
* would certainly like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the construction joinpoint
|
||||
* @return the newly created object, which is also the result of
|
||||
* the call to {@link Joinpoint#proceed()}; might be replaced by
|
||||
* the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
*/
|
||||
Object construct(ConstructorInvocation invocation) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* Description of an invocation to a constuctor, given to an
|
||||
* interceptor upon constructor-call.
|
||||
*
|
||||
* <p>A constructor invocation is a joinpoint and can be intercepted
|
||||
* by a constructor interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see ConstructorInterceptor
|
||||
*/
|
||||
public interface ConstructorInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the constructor being called.
|
||||
* <p>This method is a friendly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the constructor being called
|
||||
*/
|
||||
Constructor<?> getConstructor();
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* This interface represents a generic interceptor.
|
||||
*
|
||||
* <p>A generic interceptor can intercept runtime events that occur
|
||||
* within a base program. Those events are materialized by (reified
|
||||
* in) joinpoints. Runtime joinpoints can be invocations, field
|
||||
* access, exceptions...
|
||||
*
|
||||
* <p>This interface is not used directly. Use the the sub-interfaces
|
||||
* to intercept specific events. For instance, the following class
|
||||
* implements some specific interceptors in order to implement a
|
||||
* debugger:
|
||||
*
|
||||
* <pre class=code>
|
||||
* class DebuggingInterceptor implements MethodInterceptor,
|
||||
* ConstructorInterceptor, FieldInterceptor {
|
||||
*
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
* debug(i.getMethod(), i.getThis(), i.getArgs());
|
||||
* return i.proceed();
|
||||
* }
|
||||
*
|
||||
* Object construct(ConstructorInvocation i) throws Throwable {
|
||||
* debug(i.getConstructor(), i.getThis(), i.getArgs());
|
||||
* return i.proceed();
|
||||
* }
|
||||
*
|
||||
* Object get(FieldAccess fa) throws Throwable {
|
||||
* debug(fa.getField(), fa.getThis(), null);
|
||||
* return fa.proceed();
|
||||
* }
|
||||
*
|
||||
* Object set(FieldAccess fa) throws Throwable {
|
||||
* debug(fa.getField(), fa.getThis(), fa.getValueToSet());
|
||||
* return fa.proceed();
|
||||
* }
|
||||
*
|
||||
* void debug(AccessibleObject ao, Object this, Object value) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Joinpoint
|
||||
*/
|
||||
public interface Interceptor extends Advice {
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* This interface represents an invocation in the program.
|
||||
*
|
||||
* <p>An invocation is a joinpoint and can be intercepted by an
|
||||
* interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface Invocation extends Joinpoint {
|
||||
|
||||
/**
|
||||
* Get the arguments as an array object.
|
||||
* It is possible to change element values within this
|
||||
* array to change the arguments.
|
||||
* @return the argument of the invocation
|
||||
*/
|
||||
Object[] getArguments();
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
|
||||
/**
|
||||
* This interface represents a generic runtime joinpoint (in the AOP
|
||||
* terminology).
|
||||
*
|
||||
* <p>A runtime joinpoint is an <i>event</i> that occurs on a static
|
||||
* joinpoint (i.e. a location in a the program). For instance, an
|
||||
* invocation is the runtime joinpoint on a method (static joinpoint).
|
||||
* The static part of a given joinpoint can be generically retrieved
|
||||
* using the {@link #getStaticPart()} method.
|
||||
*
|
||||
* <p>In the context of an interception framework, a runtime joinpoint
|
||||
* is then the reification of an access to an accessible object (a
|
||||
* method, a constructor, a field), i.e. the static part of the
|
||||
* joinpoint. It is passed to the interceptors that are installed on
|
||||
* the static joinpoint.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Interceptor
|
||||
*/
|
||||
public interface Joinpoint {
|
||||
|
||||
/**
|
||||
* Proceed to the next interceptor in the chain.
|
||||
* <p>The implementation and the semantics of this method depends
|
||||
* on the actual joinpoint type (see the children interfaces).
|
||||
* @return see the children interfaces' proceed definition
|
||||
* @throws Throwable if the joinpoint throws an exception
|
||||
*/
|
||||
Object proceed() throws Throwable;
|
||||
|
||||
/**
|
||||
* Return the object that holds the current joinpoint's static part.
|
||||
* <p>For instance, the target object for an invocation.
|
||||
* @return the object (can be null if the accessible object is static)
|
||||
*/
|
||||
Object getThis();
|
||||
|
||||
/**
|
||||
* Return the static part of this joinpoint.
|
||||
* <p>The static part is an accessible object on which a chain of
|
||||
* interceptors are installed.
|
||||
*/
|
||||
AccessibleObject getStaticPart();
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* Intercepts calls on an interface on its way to the target. These
|
||||
* are nested "on top" of the target.
|
||||
*
|
||||
* <p>The user should implement the {@link #invoke(MethodInvocation)}
|
||||
* method to modify the original behavior. E.g. the following class
|
||||
* implements a tracing interceptor (traces all the calls on the
|
||||
* intercepted method(s)):
|
||||
*
|
||||
* <pre class=code>
|
||||
* class TracingInterceptor implements MethodInterceptor {
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
* System.out.println("method "+i.getMethod()+" is called on "+
|
||||
* i.getThis()+" with args "+i.getArguments());
|
||||
* Object ret=i.proceed();
|
||||
* System.out.println("method "+i.getMethod()+" returns "+ret);
|
||||
* return ret;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodInterceptor extends Interceptor {
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed();
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
*/
|
||||
Object invoke(MethodInvocation invocation) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Description of an invocation to a method, given to an interceptor
|
||||
* upon method-call.
|
||||
*
|
||||
* <p>A method invocation is a joinpoint and can be intercepted by a
|
||||
* method interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see MethodInterceptor
|
||||
*/
|
||||
public interface MethodInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the method being called.
|
||||
* <p>This method is a frienly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the method being called
|
||||
*/
|
||||
Method getMethod();
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -86,7 +86,7 @@ public interface MethodMatcher {
|
||||
* @return whether there's a runtime match
|
||||
* @see MethodMatcher#matches(Method, Class)
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass, Object... args);
|
||||
boolean matches(Method method, Class<?> targetClass, Object[] args);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,14 +57,14 @@ public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
* @return an invocable clone of this invocation.
|
||||
* {@code proceed()} can be called once per clone.
|
||||
*/
|
||||
MethodInvocation invocableClone(Object... arguments);
|
||||
MethodInvocation invocableClone(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Set the arguments to be used on subsequent invocations in the any advice
|
||||
* in this chain.
|
||||
* @param arguments the argument array
|
||||
*/
|
||||
void setArguments(Object... arguments);
|
||||
void setArguments(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Add the specified user attribute with the given value to this invocation.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@ package org.springframework.aop;
|
||||
* Minimal interface for exposing the target class behind a proxy.
|
||||
*
|
||||
* <p>Implemented by AOP proxy objects and proxy factories
|
||||
* (via {@link org.springframework.aop.framework.Advised})
|
||||
* (via {@link org.springframework.aop.framework.Advised}}
|
||||
* as well as by {@link TargetSource TargetSources}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,14 +29,12 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueMethodMatcher() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return false;
|
||||
@@ -48,17 +46,11 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// Should never be invoked as isRuntime returns false.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
@@ -68,4 +60,9 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
-50
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -58,8 +55,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation {
|
||||
|
||||
/**
|
||||
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
|
||||
@@ -90,13 +86,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
protected final Method aspectJAdviceMethod;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
protected transient Method aspectJAdviceMethod;
|
||||
/** The total number of arguments we have to populate on advice dispatch */
|
||||
private final int adviceInvocationArgumentCount;
|
||||
|
||||
private final AspectJExpressionPointcut pointcut;
|
||||
|
||||
@@ -142,7 +135,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
*/
|
||||
private int joinPointStaticPartArgumentIndex = -1;
|
||||
|
||||
private Map<String, Integer> argumentBindings;
|
||||
private Map<String, Integer> argumentBindings = null;
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
@@ -161,10 +154,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
|
||||
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
|
||||
this.methodName = aspectJAdviceMethod.getName();
|
||||
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
|
||||
this.aspectJAdviceMethod = aspectJAdviceMethod;
|
||||
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
this.pointcut = pointcut;
|
||||
this.aspectInstanceFactory = aspectInstanceFactory;
|
||||
}
|
||||
@@ -259,17 +250,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.argumentNames[i] + "' that is not a valid Java identifier");
|
||||
}
|
||||
}
|
||||
if (this.argumentNames != null) {
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) {
|
||||
if (argumentNames != null) {
|
||||
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = this.argumentNames;
|
||||
this.argumentNames = new String[oldNames.length + 1];
|
||||
this.argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
|
||||
String[] oldNames = argumentNames;
|
||||
argumentNames = new String[oldNames.length + 1];
|
||||
argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,11 +359,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
*/
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
|
||||
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numUnboundArgs = this.parameterTypes.length;
|
||||
int numUnboundArgs = this.adviceInvocationArgumentCount;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
@@ -390,7 +381,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
|
||||
if (JoinPoint.class == candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.class)) {
|
||||
this.joinPointArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -400,7 +391,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
|
||||
if (ProceedingJoinPoint.class == candidateParameterType) {
|
||||
if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
|
||||
if (!supportsProceedingJoinPoint()) {
|
||||
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
|
||||
}
|
||||
@@ -417,7 +408,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
|
||||
if (JoinPoint.StaticPart.class == candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
|
||||
this.joinPointStaticPartArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -465,13 +456,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
|
||||
" arguments to bind by name in advice, but actually found " +
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
|
||||
+ " arguments to bind by name in advice, but actually found " +
|
||||
this.argumentNames.length + " arguments.");
|
||||
}
|
||||
|
||||
// So we match in number...
|
||||
int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
|
||||
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
|
||||
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
|
||||
this.argumentBindings.put(this.argumentNames[i], i);
|
||||
}
|
||||
@@ -480,8 +471,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
// specified, and find the discovered argument types.
|
||||
if (this.returningName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.returningName)) {
|
||||
throw new IllegalStateException("Returning argument name '" + this.returningName +
|
||||
"' was not bound in advice arguments");
|
||||
throw new IllegalStateException("Returning argument name '"
|
||||
+ this.returningName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.returningName);
|
||||
@@ -491,8 +482,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
if (this.throwingName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.throwingName)) {
|
||||
throw new IllegalStateException("Throwing argument name '" + this.throwingName +
|
||||
"' was not bound in advice arguments");
|
||||
throw new IllegalStateException("Throwing argument name '"
|
||||
+ this.throwingName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.throwingName);
|
||||
@@ -552,7 +543,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
calculateArgumentBindings();
|
||||
|
||||
// AMC start
|
||||
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length];
|
||||
Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount];
|
||||
int numBound = 0;
|
||||
|
||||
if (this.joinPointArgumentIndex != -1) {
|
||||
@@ -589,10 +580,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
|
||||
if (numBound != this.parameterTypes.length) {
|
||||
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
|
||||
" arguments, but only bound " + numBound + " (JoinPointMatch " +
|
||||
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
|
||||
if (numBound != this.adviceInvocationArgumentCount) {
|
||||
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount
|
||||
+ " arguments, but only bound " + numBound + " (JoinPointMatch " +
|
||||
(jpMatch == null ? "was NOT" : "WAS") +
|
||||
" bound in invocation)");
|
||||
}
|
||||
|
||||
return adviceInvocationArgs;
|
||||
@@ -673,16 +665,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
"aspect name '" + this.aspectName + "'";
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MethodMatcher that excludes the specified advice method.
|
||||
|
||||
-1
@@ -28,7 +28,6 @@ import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
implements MethodInterceptor, AfterAdvice, Serializable {
|
||||
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -40,7 +37,6 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
try {
|
||||
|
||||
+4
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@@ -33,9 +32,7 @@ import org.springframework.util.TypeUtils;
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
implements AfterReturningAdvice, AfterAdvice, Serializable {
|
||||
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice {
|
||||
|
||||
public AspectJAfterReturningAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -43,7 +40,6 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -66,7 +62,6 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Following AspectJ semantics, if a returning clause was specified, then the
|
||||
* advice is only invoked if the returned value is an instance of the given
|
||||
@@ -98,10 +93,10 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
if (returnValue != null) {
|
||||
return ClassUtils.isAssignableValue(type, returnValue);
|
||||
}
|
||||
else if (Object.class == type && void.class == method.getReturnType()) {
|
||||
else if (type.equals(Object.class) && method.getReturnType().equals(void.class)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
else{
|
||||
return ClassUtils.isAssignable(type, method.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
implements MethodInterceptor, AfterAdvice, Serializable {
|
||||
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterThrowingAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -40,7 +37,6 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -61,11 +57,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
try {
|
||||
return mi.proceed();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (shouldInvokeOnThrowing(ex)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, ex);
|
||||
catch (Throwable t) {
|
||||
if (shouldInvokeOnThrowing(t)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, t);
|
||||
}
|
||||
throw ex;
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +69,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
* In AspectJ semantics, after throwing advice that specifies a throwing clause
|
||||
* is only invoked if the thrown exception is a subtype of the given throwing type.
|
||||
*/
|
||||
private boolean shouldInvokeOnThrowing(Throwable ex) {
|
||||
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
|
||||
private boolean shouldInvokeOnThrowing(Throwable t) {
|
||||
return getDiscoveredThrowingType().isAssignableFrom(t.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -34,8 +33,7 @@ import org.springframework.aop.ProxyMethodInvocation;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
|
||||
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor {
|
||||
|
||||
public AspectJAroundAdvice(
|
||||
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -43,7 +41,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
super(aspectJAroundAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -59,6 +56,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
|
||||
+21
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.aop.aspectj;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -204,7 +203,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
pointcutParameters[i] = parser.createPointcutParameter(
|
||||
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
|
||||
}
|
||||
return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()),
|
||||
return parser.parsePointcutExpression(
|
||||
replaceBooleanOperators(getExpression()),
|
||||
this.pointcutDeclarationScope, pointcutParameters);
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
checkReadyToMatch();
|
||||
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
|
||||
@@ -327,41 +327,29 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
// TODO: Should we really proceed here?
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
logger.debug("Couldn't access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
|
||||
try {
|
||||
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
|
||||
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
|
||||
|
||||
/*
|
||||
* Do a final check to see if any this(TYPE) kind of residue match. For
|
||||
* this purpose, we use the original method's (proxy method's) shadow to
|
||||
* ensure that 'this' is correctly checked against. Without this check,
|
||||
* we get incorrect match on this(TYPE) where TYPE matches the target
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
if (joinPointMatch.matches()) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
}
|
||||
/*
|
||||
* Do a final check to see if any this(TYPE) kind of residue match. For
|
||||
* this purpose, we use the original method's (proxy method's) shadow to
|
||||
* ensure that 'this' is correctly checked against. Without this check,
|
||||
* we get incorrect match on this(TYPE) where TYPE matches the target
|
||||
* type but not 'this' (as would be the case of JDK dynamic proxies).
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return joinPointMatch.matches();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
|
||||
" - falling back to non-match", ex);
|
||||
if (joinPointMatch.matches()) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return joinPointMatch.matches();
|
||||
}
|
||||
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
@@ -28,8 +27,7 @@ import org.springframework.aop.MethodBeforeAdvice;
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
|
||||
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {
|
||||
|
||||
public AspectJMethodBeforeAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -37,7 +35,6 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, null);
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -243,7 +243,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
private String toString(boolean includeModifier, boolean includeReturnTypeAndArgs,
|
||||
boolean useLongReturnAndArgumentTypeName, boolean useLongTypeName) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (includeModifier) {
|
||||
sb.append(Modifier.toString(getModifiers()));
|
||||
@@ -263,9 +262,8 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendTypes(StringBuilder sb, Class<?>[] types, boolean includeArgs,
|
||||
boolean useLongReturnAndArgumentTypeName) {
|
||||
|
||||
private void appendTypes(StringBuilder sb, Class<?>[] types,
|
||||
boolean includeArgs, boolean useLongReturnAndArgumentTypeName) {
|
||||
if (includeArgs) {
|
||||
for (int size = types.length, i = 0; i < size; i++) {
|
||||
appendType(sb, types[i], useLongReturnAndArgumentTypeName);
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* migrate to {@code ShadowMatch.getVariablesInvolvedInRuntimeTest()}
|
||||
* or some similar operation.
|
||||
*
|
||||
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>Bug 151593</a>
|
||||
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Ramnivas Laddad
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -31,8 +29,7 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
* @see SimpleAspectInstanceFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Serializable {
|
||||
public class SingletonAspectInstanceFactory implements AspectInstanceFactory {
|
||||
|
||||
private final Object aspectInstance;
|
||||
|
||||
|
||||
+29
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,6 @@ import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
@@ -61,6 +60,34 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<A>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -153,7 +180,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
throw new IllegalStateException("Expecting at least " + argNames.length +
|
||||
" arguments in the advice declaration, but only found " + paramTypes.length);
|
||||
}
|
||||
|
||||
// Make the simplifying assumption for now that all of the JoinPoint based arguments
|
||||
// come first in the advice declaration.
|
||||
int typeOffset = paramTypes.length - argNames.length;
|
||||
@@ -164,36 +190,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<A>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,31 +63,31 @@ public interface AspectJAdvisorFactory {
|
||||
/**
|
||||
* Build Spring AOP Advisors for all annotated At-AspectJ methods
|
||||
* on the specified aspect instance.
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* (not the aspect instance itself in order to avoid eager instantiation)
|
||||
* @param aif the aspect instance factory (not the aspect instance itself
|
||||
* in order to avoid eager instantiation)
|
||||
* @return a list of advisors for this class
|
||||
*/
|
||||
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
|
||||
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advisor for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* @param declarationOrder the declaration order within the aspect
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return {@code null} if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
* create a Spring advice in its own right
|
||||
*/
|
||||
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
int declarationOrder, String aspectName);
|
||||
Advisor getAdvisor(Method candidateAdviceMethod,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advice for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param expressionPointcut the AspectJ expression pointcut
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* @param declarationOrder the declaration order within the aspect
|
||||
* @param pointcut the corresponding AspectJ expression pointcut
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return {@code null} if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
@@ -98,7 +98,7 @@ public interface AspectJAdvisorFactory {
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
|
||||
*/
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyCreatorSupport;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* Create a new {@code AspectJProxyFactory}.
|
||||
* No target, only interfaces. Must add interceptors.
|
||||
*/
|
||||
public AspectJProxyFactory(Class<?>... interfaces) {
|
||||
public AspectJProxyFactory(Class<?>[] interfaces) {
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
|
||||
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
|
||||
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
|
||||
AnnotationAwareOrderComparator.sort(advisors);
|
||||
OrderComparator.sort(advisors);
|
||||
addAdvisors(advisors);
|
||||
}
|
||||
|
||||
|
||||
+14
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
@@ -44,27 +40,12 @@ import org.springframework.aop.support.ComposablePointcut;
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.AspectJExpressionPointcut
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectMetadata implements Serializable {
|
||||
|
||||
/**
|
||||
* The name of this aspect as defined to Spring (the bean name) -
|
||||
* allows us to determine if two pieces of advice come from the
|
||||
* same aspect and hence their relative precedence.
|
||||
*/
|
||||
private final String aspectName;
|
||||
|
||||
/**
|
||||
* The aspect class, stored separately for re-resolution of the
|
||||
* corresponding AjType on deserialization.
|
||||
*/
|
||||
private final Class<?> aspectClass;
|
||||
public class AspectMetadata {
|
||||
|
||||
/**
|
||||
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
|
||||
* Re-resolved on deserialization since it isn't serializable itself.
|
||||
*/
|
||||
private transient AjType<?> ajType;
|
||||
private final AjType<?> ajType;
|
||||
|
||||
/**
|
||||
* Spring AOP pointcut corresponding to the per clause of the
|
||||
@@ -73,6 +54,13 @@ public class AspectMetadata implements Serializable {
|
||||
*/
|
||||
private final Pointcut perClausePointcut;
|
||||
|
||||
/**
|
||||
* The name of this aspect as defined to Spring (the bean name) -
|
||||
* allows us to determine if two pieces of advice come from the
|
||||
* same aspect and hence their relative precedence.
|
||||
*/
|
||||
private String aspectName;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectMetadata instance for the given aspect class.
|
||||
@@ -84,7 +72,7 @@ public class AspectMetadata implements Serializable {
|
||||
|
||||
Class<?> currClass = aspectClass;
|
||||
AjType<?> ajType = null;
|
||||
while (currClass != Object.class) {
|
||||
while (!currClass.equals(Object.class)) {
|
||||
AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
|
||||
if (ajTypeToCheck.isAspect()) {
|
||||
ajType = ajTypeToCheck;
|
||||
@@ -95,11 +83,10 @@ public class AspectMetadata implements Serializable {
|
||||
if (ajType == null) {
|
||||
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
|
||||
}
|
||||
if (ajType.getDeclarePrecedence().length > 0) {
|
||||
this.ajType = ajType;
|
||||
if (this.ajType.getDeclarePrecedence().length > 0) {
|
||||
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
|
||||
}
|
||||
this.aspectClass = ajType.getJavaClass();
|
||||
this.ajType = ajType;
|
||||
|
||||
switch (this.ajType.getPerClause().getKind()) {
|
||||
case SINGLETON :
|
||||
@@ -145,7 +132,7 @@ public class AspectMetadata implements Serializable {
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public Class<?> getAspectClass() {
|
||||
return this.aspectClass;
|
||||
return this.ajType.getJavaClass();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,10 +173,4 @@ public class AspectMetadata implements Serializable {
|
||||
return (isPerThisOrPerTarget() || isPerTypeWithin());
|
||||
}
|
||||
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
this.ajType = AjTypeSystem.getAjType(this.aspectClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -39,8 +38,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
@@ -112,7 +110,10 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {
|
||||
return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();
|
||||
}
|
||||
return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);
|
||||
Order order = AnnotationUtils.findAnnotation(type, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
+28
-53
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
@@ -40,70 +37,58 @@ import org.springframework.aop.support.Pointcuts;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class InstantiationModelAwarePointcutAdvisorImpl
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation {
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
private transient Method aspectJAdviceMethod;
|
||||
|
||||
private final AspectJAdvisorFactory aspectJAdvisorFactory;
|
||||
private Pointcut pointcut;
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
private final int declarationOrder;
|
||||
|
||||
private final String aspectName;
|
||||
|
||||
private final Pointcut pointcut;
|
||||
private final Method method;
|
||||
|
||||
private final boolean lazy;
|
||||
|
||||
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
|
||||
|
||||
private Advice instantiatedAdvice;
|
||||
|
||||
private int declarationOrder;
|
||||
|
||||
private String aspectName;
|
||||
|
||||
private Boolean isBeforeAdvice;
|
||||
|
||||
private Boolean isAfterAdvice;
|
||||
|
||||
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
|
||||
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
|
||||
this.methodName = aspectJAdviceMethod.getName();
|
||||
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
|
||||
this.aspectJAdviceMethod = aspectJAdviceMethod;
|
||||
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
|
||||
this.aspectInstanceFactory = aspectInstanceFactory;
|
||||
this.declarationOrder = declarationOrder;
|
||||
this.declaredPointcut = ajexp;
|
||||
this.method = method;
|
||||
this.atAspectJAdvisorFactory = af;
|
||||
this.aspectInstanceFactory = aif;
|
||||
this.declarationOrder = declarationOrderInAspect;
|
||||
this.aspectName = aspectName;
|
||||
|
||||
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
|
||||
if (aif.getAspectMetadata().isLazilyInstantiated()) {
|
||||
// Static part of the pointcut is a lazy type.
|
||||
Pointcut preInstantiationPointcut = Pointcuts.union(
|
||||
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
|
||||
Pointcut preInstantiationPointcut =
|
||||
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
|
||||
|
||||
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
||||
// If it's not a dynamic pointcut, it may be optimized out
|
||||
// by the Spring AOP infrastructure after the first evaluation.
|
||||
this.pointcut = new PerTargetInstantiationModelPointcut(
|
||||
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
|
||||
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
|
||||
this.lazy = true;
|
||||
}
|
||||
else {
|
||||
// A singleton aspect.
|
||||
this.pointcut = this.declaredPointcut;
|
||||
this.lazy = false;
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
this.pointcut = declaredPointcut;
|
||||
this.lazy = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +142,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return this.atAspectJAdvisorFactory.getAdvice(
|
||||
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
@@ -206,7 +191,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
*/
|
||||
private void determineAdviceType() {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
|
||||
if (aspectJAnnotation == null) {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
@@ -235,21 +220,11 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
"]; advice method [" + this.method + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
@@ -281,7 +256,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// This can match only on declared pointcut.
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
|
||||
}
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -27,8 +25,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory maaif;
|
||||
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a
|
||||
* {@link BeanFactory}-provided prototype, enforcing prototype semantics.
|
||||
* AspectInstanceFactory backed by a BeanFactory-provided prototype,
|
||||
* enforcing prototype semantics.
|
||||
*
|
||||
* <p>Note that this may instantiate multiple times, which probably won't give the
|
||||
* semantics you expect. Use a {@link LazySingletonAspectInstanceFactoryDecorator}
|
||||
@@ -34,8 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable {
|
||||
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory {
|
||||
|
||||
/**
|
||||
* Create a PrototypeAspectInstanceFactory. AspectJ will be called to
|
||||
|
||||
+28
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -66,8 +65,7 @@ import org.springframework.util.comparator.InstanceComparator;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory {
|
||||
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
@@ -79,9 +77,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
new Converter<Method, Annotation>() {
|
||||
@Override
|
||||
public Annotation convert(Method method) {
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return annotation == null ? null : annotation.getAnnotation();
|
||||
}
|
||||
}));
|
||||
comparator.addComparator(new ConvertingComparator<Method, String>(
|
||||
@@ -96,17 +93,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
|
||||
@Override
|
||||
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
|
||||
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
|
||||
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
|
||||
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
|
||||
final String aspectName = maaif.getAspectMetadata().getAspectName();
|
||||
validate(aspectClass);
|
||||
|
||||
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
|
||||
// so that it will only instantiate once.
|
||||
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
|
||||
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(maaif);
|
||||
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
final List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
@@ -160,7 +157,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DeclareParents.class == declareParents.defaultImpl()) {
|
||||
if (DeclareParents.class.equals(declareParents.defaultImpl())) {
|
||||
// This is what comes back if it wasn't set. This seems bizarre...
|
||||
// TODO this restriction possibly should be relaxed
|
||||
throw new IllegalStateException("defaultImpl must be set on DeclareParents");
|
||||
@@ -172,19 +169,18 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
|
||||
@Override
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
|
||||
int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
|
||||
validate(aif.getAspectMetadata().getAspectClass());
|
||||
|
||||
AspectJExpressionPointcut expressionPointcut = getPointcut(
|
||||
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
|
||||
if (expressionPointcut == null) {
|
||||
AspectJExpressionPointcut ajexp =
|
||||
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
|
||||
if (ajexp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
|
||||
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(
|
||||
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
|
||||
@@ -193,7 +189,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
if (aspectJAnnotation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
|
||||
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
|
||||
@@ -202,10 +197,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
|
||||
@Override
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
|
||||
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
|
||||
validate(candidateAspectClass);
|
||||
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
@@ -230,32 +225,27 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfter:
|
||||
springAdvice = new AspectJAfterAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfterReturning:
|
||||
springAdvice = new AspectJAfterReturningAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
|
||||
springAdvice.setReturningName(afterReturningAnnotation.returning());
|
||||
}
|
||||
break;
|
||||
case AtAfterThrowing:
|
||||
springAdvice = new AspectJAfterThrowingAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -264,12 +254,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
"Unsupported advice type on method " + candidateAdviceMethod);
|
||||
}
|
||||
|
||||
// Now to configure the advice...
|
||||
springAdvice.setAspectName(aspectName);
|
||||
springAdvice.setDeclarationOrder(declarationOrder);
|
||||
springAdvice.setDeclarationOrder(declarationOrderInAspect);
|
||||
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
|
||||
if (argNames != null) {
|
||||
springAdvice.setArgumentNamesFromStringArray(argNames);
|
||||
@@ -278,7 +268,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synthetic advisor that instantiates the aspect.
|
||||
* Triggered by per-clause pointcut on non-singleton aspect.
|
||||
|
||||
+15
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,8 @@ package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that
|
||||
@@ -50,9 +51,20 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine a fallback order for the case that the aspect instance
|
||||
* does not express an instance-specific order through implementing
|
||||
* the {@link org.springframework.core.Ordered} interface.
|
||||
* <p>The default implementation simply returns {@code Ordered.LOWEST_PRECEDENCE}.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that is backed
|
||||
@@ -32,9 +31,8 @@ import org.springframework.core.annotation.OrderUtils;
|
||||
* @since 2.0
|
||||
* @see SimpleMetadataAwareAspectInstanceFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspectInstanceFactory
|
||||
implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final AspectMetadata metadata;
|
||||
|
||||
@@ -55,9 +53,19 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the aspect class carries an
|
||||
* {@link org.springframework.core.annotation.Order} annotation,
|
||||
* falling back to {@code Ordered.LOWEST_PRECEDENCE}.
|
||||
* @see org.springframework.core.annotation.Order
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
Order order = AnnotationUtils.findAnnotation(aspectClass, Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Classes enabling AspectJ 5 @Annotated classes to be used in Spring AOP.
|
||||
*
|
||||
* <p>Normally to be used through an AspectJAutoProxyCreator rather than directly.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
|
||||
+12
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import java.util.Comparator;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJAopUtils;
|
||||
import org.springframework.aop.aspectj.AspectJPrecedenceInformation;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -29,13 +29,15 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* <p>Given two pieces of advice, {@code a} and {@code b}:
|
||||
* <ul>
|
||||
* <li>if {@code a} and {@code b} are defined in different aspects, then the advice
|
||||
* in the aspect with the lowest order value has the highest precedence</li>
|
||||
* <li>if {@code a} and {@code b} are defined in the same aspect, then if one of
|
||||
* {@code a} or {@code b} is a form of after advice, then the advice declared last
|
||||
* in the aspect has the highest precedence. If neither {@code a} nor {@code b} is
|
||||
* a form of after advice, then the advice declared first in the aspect has the
|
||||
* highest precedence.</li>
|
||||
* <li>if {@code a} and {@code b} are defined in different
|
||||
* aspects, then the advice in the aspect with the lowest order
|
||||
* value has the highest precedence</li>
|
||||
* <li>if {@code a} and {@code b} are defined in the same
|
||||
* aspect, then if one of {@code a} or {@code b} is a form of
|
||||
* after advice, then the advice declared last in the aspect has the
|
||||
* highest precedence. If neither {@code a} nor {@code b} is a
|
||||
* form of after advice, then the advice declared first in the aspect has
|
||||
* the highest precedence.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Important: Note that unlike a normal comparator a return of 0 means
|
||||
@@ -49,12 +51,9 @@ import org.springframework.util.Assert;
|
||||
class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
|
||||
private static final int HIGHER_PRECEDENCE = -1;
|
||||
|
||||
private static final int SAME_PRECEDENCE = 0;
|
||||
|
||||
private static final int LOWER_PRECEDENCE = 1;
|
||||
|
||||
|
||||
private final Comparator<? super Advisor> advisorComparator;
|
||||
|
||||
|
||||
@@ -62,7 +61,7 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
* Create a default AspectJPrecedenceComparator.
|
||||
*/
|
||||
public AspectJPrecedenceComparator() {
|
||||
this.advisorComparator = AnnotationAwareOrderComparator.INSTANCE;
|
||||
this.advisorComparator = OrderComparator.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Base classes enabling auto-proxying based on AspectJ.
|
||||
* Support for AspectJ annotation aspects resides in the "aspectj.annotation" package.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/**
|
||||
*
|
||||
* AspectJ integration package. Includes Spring AOP advice implementations for AspectJ 5
|
||||
* annotation-style methods, and an AspectJExpressionPointcut: a Spring AOP Pointcut
|
||||
* implementation that allows use of the AspectJ pointcut expression language with the Spring AOP
|
||||
@@ -7,5 +8,7 @@
|
||||
* <p>Note that use of this package does <i>not</i> require the use of the {@code ajc} compiler
|
||||
* or AspectJ load-time weaver. It is intended to enable the use of a valuable subset of AspectJ
|
||||
* functionality, with consistent semantics, with the proxy-based Spring AOP framework.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.parsing.ComponentDefinition}
|
||||
* that bridges the gap between the advisor bean definition configured
|
||||
* by the {@code <aop:advisor>} tag and the component definition
|
||||
* by the {@code <aop:advisor>} tag and the component definition
|
||||
* infrastructure.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
* {@code NamespaceHandler} for the {@code aop} namespace.
|
||||
*
|
||||
* <p>Provides a {@link org.springframework.beans.factory.xml.BeanDefinitionParser} for the
|
||||
* {@code <aop:config>} tag. A {@code config} tag can include nested
|
||||
* {@code <aop:config>} tag. A {@code config} tag can include nested
|
||||
* {@code pointcut}, {@code advisor} and {@code aspect} tags.
|
||||
*
|
||||
* <p>The {@code pointcut} tag allows for creation of named
|
||||
|
||||
+4
-4
@@ -49,7 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} for the {@code <aop:config>} tag.
|
||||
* {@link BeanDefinitionParser} for the {@code <aop:config>} tag.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -123,7 +123,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Configures the auto proxy creator needed to support the {@link BeanDefinition BeanDefinitions}
|
||||
* created by the '{@code <aop:config/>}' tag. Will force class proxying if the
|
||||
* created by the '{@code <aop:config/>}' tag. Will force class proxying if the
|
||||
* '{@code proxy-target-class}' attribute is set to '{@code true}'.
|
||||
* @see AopNamespaceUtils
|
||||
*/
|
||||
@@ -132,7 +132,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the supplied {@code <advisor>} element and registers the resulting
|
||||
* Parses the supplied {@code <advisor>} element and registers the resulting
|
||||
* {@link org.springframework.aop.Advisor} and any resulting {@link org.springframework.aop.Pointcut}
|
||||
* with the supplied {@link BeanDefinitionRegistry}.
|
||||
*/
|
||||
@@ -428,7 +428,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the supplied {@code <pointcut>} and registers the resulting
|
||||
* Parses the supplied {@code <pointcut>} and registers the resulting
|
||||
* Pointcut with the BeanDefinitionRegistry.
|
||||
*/
|
||||
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionDecorator} responsible for parsing the
|
||||
* {@code <aop:scoped-proxy/>} tag.
|
||||
* {@code <aop:scoped-proxy/>} tag.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Support package for declarative AOP configuration,
|
||||
* with XML schema being the primary configuration format.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.config;
|
||||
|
||||
|
||||
+33
-43
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Base class for {@link BeanPostProcessor} implementations that apply a
|
||||
@@ -31,13 +34,22 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
* @since 3.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
|
||||
public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
|
||||
implements BeanPostProcessor, BeanClassLoaderAware, Ordered {
|
||||
|
||||
protected Advisor advisor;
|
||||
|
||||
protected boolean beforeExistingAdvisors = false;
|
||||
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(256);
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
/**
|
||||
* This should run after all other post-processors, so that it can just add
|
||||
* an advisor to existing proxies rather than double-proxy.
|
||||
*/
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(64);
|
||||
|
||||
|
||||
/**
|
||||
@@ -53,6 +65,20 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
this.beforeExistingAdvisors = beforeExistingAdvisors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
@@ -81,13 +107,11 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
}
|
||||
|
||||
if (isEligible(bean, beanName)) {
|
||||
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
|
||||
}
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
customizeProxyFactory(proxyFactory);
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
return proxyFactory.getProxy(this.beanClassLoader);
|
||||
}
|
||||
|
||||
// No async proxy needed.
|
||||
@@ -130,38 +154,4 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
return eligible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a {@link ProxyFactory} for the given bean.
|
||||
* <p>Subclasses may customize the handling of the target instance and in
|
||||
* particular the exposure of the target class. The default introspection
|
||||
* of interfaces for non-target-class proxies and the configured advisor
|
||||
* will be applied afterwards; {@link #customizeProxyFactory} allows for
|
||||
* late customizations of those parts right before proxy creation.
|
||||
* @param bean the bean instance to create a proxy for
|
||||
* @param beanName the corresponding bean name
|
||||
* @return the ProxyFactory, initialized with this processor's
|
||||
* {@link ProxyConfig} settings and the specified bean
|
||||
* @since 4.2.3
|
||||
* @see #customizeProxyFactory
|
||||
*/
|
||||
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.setTarget(bean);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may choose to implement this: for example,
|
||||
* to change the interfaces exposed.
|
||||
* <p>The default implementation is empty.
|
||||
* @param proxyFactory ProxyFactory that is already configured with
|
||||
* target, advisor and interfaces and will be used to create the proxy
|
||||
* immediately after this method returns
|
||||
* @since 4.2.3
|
||||
* @see #prepareProxyFactory
|
||||
*/
|
||||
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,7 +66,7 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
* @see org.springframework.aop.target.SingletonTargetSource
|
||||
* @see org.springframework.aop.target.LazyInitTargetSource
|
||||
* @see org.springframework.aop.target.PrototypeTargetSource
|
||||
* @see org.springframework.aop.target.CommonsPool2TargetSource
|
||||
* @see org.springframework.aop.target.CommonsPoolTargetSource
|
||||
*/
|
||||
public void setTarget(Object target) {
|
||||
this.target = target;
|
||||
@@ -173,8 +173,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
|
||||
}
|
||||
|
||||
postProcessProxyFactory(proxyFactory);
|
||||
|
||||
this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
|
||||
}
|
||||
|
||||
@@ -193,15 +191,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A hook for subclasses to post-process the {@link ProxyFactory}
|
||||
* before creating the proxy instance with it.
|
||||
* @param proxyFactory the AOP ProxyFactory about to be used
|
||||
* @since 4.2
|
||||
*/
|
||||
protected void postProcessProxyFactory(ProxyFactory proxyFactory) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getObject() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.aop.TargetSource;
|
||||
/**
|
||||
* Interface to be implemented by classes that hold the configuration
|
||||
* of a factory of AOP proxies. This configuration includes the
|
||||
* Interceptors and other advice, Advisors, and the proxied interfaces.
|
||||
* Interceptors and other advice, and Advisors, and the proxied interfaces.
|
||||
*
|
||||
* <p>Any AOP proxy obtained from Spring can be cast to this interface to
|
||||
* allow manipulation of its AOP advice.
|
||||
@@ -49,8 +49,8 @@ public interface Advised extends TargetClassAware {
|
||||
boolean isProxyTargetClass();
|
||||
|
||||
/**
|
||||
* Return the interfaces proxied by the AOP proxy.
|
||||
* <p>Will not include the target class, which may also be proxied.
|
||||
* Return the interfaces proxied by the AOP proxy. Will not
|
||||
* include the target class, which may also be proxied.
|
||||
*/
|
||||
Class<?>[] getProxiedInterfaces();
|
||||
|
||||
@@ -60,34 +60,33 @@ public interface Advised extends TargetClassAware {
|
||||
*/
|
||||
boolean isInterfaceProxied(Class<?> intf);
|
||||
|
||||
|
||||
/**
|
||||
* Change the {@code TargetSource} used by this {@code Advised} object.
|
||||
* <p>Only works if the configuration isn't {@linkplain #isFrozen frozen}.
|
||||
* Change the TargetSource used by this Advised object.
|
||||
* Only works if the configuration isn't frozen.
|
||||
* @param targetSource new TargetSource to use
|
||||
*/
|
||||
void setTargetSource(TargetSource targetSource);
|
||||
|
||||
/**
|
||||
* Return the {@code TargetSource} used by this {@code Advised} object.
|
||||
* Return the TargetSource used by this Advised object.
|
||||
*/
|
||||
TargetSource getTargetSource();
|
||||
|
||||
/**
|
||||
* Set whether the proxy should be exposed by the AOP framework as a
|
||||
* {@link ThreadLocal} for retrieval via the {@link AopContext} class.
|
||||
* <p>It can be necessary to expose the proxy if an advised object needs
|
||||
* to invoke a method on itself with advice applied. Otherwise, if an
|
||||
* advised object invokes a method on {@code this}, no advice will be applied.
|
||||
* <p>Default is {@code false}, for optimal performance.
|
||||
* ThreadLocal for retrieval via the AopContext class. This is useful
|
||||
* if an advised object needs to call another advised method on itself.
|
||||
* (If it uses {@code this}, the invocation will not be advised).
|
||||
* <p>Default is "false", for optimal performance.
|
||||
*/
|
||||
void setExposeProxy(boolean exposeProxy);
|
||||
|
||||
/**
|
||||
* Return whether the factory should expose the proxy as a {@link ThreadLocal}.
|
||||
* <p>It can be necessary to expose the proxy if an advised object needs
|
||||
* to invoke a method on itself with advice applied. Otherwise, if an
|
||||
* advised object invokes a method on {@code this}, no advice will be applied.
|
||||
* <p>Getting the proxy is analogous to an EJB calling {@code getEJBObject()}.
|
||||
* Return whether the factory should expose the proxy as a ThreadLocal.
|
||||
* This can be necessary if a target object needs to invoke a method on itself
|
||||
* benefitting from advice. (If it invokes a method on {@code this} no advice
|
||||
* will apply.) Getting the proxy is analogous to an EJB calling getEJBObject().
|
||||
* @see AopContext
|
||||
*/
|
||||
boolean isExposeProxy();
|
||||
@@ -108,6 +107,7 @@ public interface Advised extends TargetClassAware {
|
||||
*/
|
||||
boolean isPreFiltered();
|
||||
|
||||
|
||||
/**
|
||||
* Return the advisors applying to this proxy.
|
||||
* @return a list of Advisors applying to this proxy (never {@code null})
|
||||
@@ -170,6 +170,7 @@ public interface Advised extends TargetClassAware {
|
||||
*/
|
||||
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
|
||||
|
||||
|
||||
/**
|
||||
* Add the given AOP Alliance advice to the tail of the advice (interceptor) chain.
|
||||
* <p>This will be wrapped in a DefaultPointcutAdvisor with a pointcut that always
|
||||
@@ -216,6 +217,7 @@ public interface Advised extends TargetClassAware {
|
||||
*/
|
||||
int indexOf(Advice advice);
|
||||
|
||||
|
||||
/**
|
||||
* As {@code toString()} will normally be delegated to the target,
|
||||
* this returns the equivalent for the AOP proxy.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -113,7 +113,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Create a AdvisedSupport instance with the given parameters.
|
||||
* @param interfaces the proxied interfaces
|
||||
*/
|
||||
public AdvisedSupport(Class<?>... interfaces) {
|
||||
public AdvisedSupport(Class<?>[] interfaces) {
|
||||
this();
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
@@ -586,7 +586,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Simple wrapper class around a Method. Used as the key when
|
||||
* caching methods, for efficient equals and hashCode comparisons.
|
||||
*/
|
||||
private static final class MethodCacheKey implements Comparable<MethodCacheKey> {
|
||||
private static class MethodCacheKey {
|
||||
|
||||
private final Method method;
|
||||
|
||||
@@ -599,28 +599,17 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (this == other || (other instanceof MethodCacheKey &&
|
||||
this.method == ((MethodCacheKey) other).method));
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
MethodCacheKey otherKey = (MethodCacheKey) other;
|
||||
return (this.method == otherKey.method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.method.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MethodCacheKey other) {
|
||||
int result = this.method.getName().compareTo(other.method.getName());
|
||||
if (result == 0) {
|
||||
result = this.method.toString().compareTo(other.method.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.aop.SpringProxy;
|
||||
@@ -26,9 +23,7 @@ import org.springframework.aop.TargetClassAware;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for AOP proxy factories.
|
||||
@@ -45,11 +40,11 @@ public abstract class AopProxyUtils {
|
||||
|
||||
/**
|
||||
* Determine the ultimate target class of the given bean instance, traversing
|
||||
* not only a top-level proxy but any number of nested proxies as well —
|
||||
* not only a top-level proxy but any number of nested proxies as well -
|
||||
* as long as possible without side effects, that is, just for singleton targets.
|
||||
* @param candidate the instance to check (might be an AOP proxy)
|
||||
* @return the ultimate target class (or the plain class of the given
|
||||
* object as fallback; never {@code null})
|
||||
* @return the target class (or the plain class of the given object as fallback;
|
||||
* never {@code null})
|
||||
* @see org.springframework.aop.TargetClassAware#getTargetClass()
|
||||
* @see Advised#getTargetSource()
|
||||
*/
|
||||
@@ -79,46 +74,21 @@ public abstract class AopProxyUtils {
|
||||
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
|
||||
* {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
|
||||
* {@link org.springframework.aop.SpringProxy} marker interface.
|
||||
* @param advised the proxy config
|
||||
* @return the complete set of interfaces to proxy
|
||||
* @see SpringProxy
|
||||
* @see Advised
|
||||
* @see org.springframework.aop.SpringProxy
|
||||
*/
|
||||
public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
|
||||
return completeProxiedInterfaces(advised, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the complete set of interfaces to proxy for the given AOP configuration.
|
||||
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
|
||||
* {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
|
||||
* {@link org.springframework.aop.SpringProxy} marker interface.
|
||||
* @param advised the proxy config
|
||||
* @param decoratingProxy whether to expose the {@link DecoratingProxy} interface
|
||||
* @return the complete set of interfaces to proxy
|
||||
* @since 4.3
|
||||
* @see SpringProxy
|
||||
* @see Advised
|
||||
* @see DecoratingProxy
|
||||
*/
|
||||
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
|
||||
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
|
||||
if (specifiedInterfaces.length == 0) {
|
||||
// No user-specified interfaces: check whether target class is an interface.
|
||||
Class<?> targetClass = advised.getTargetClass();
|
||||
if (targetClass != null) {
|
||||
if (targetClass.isInterface()) {
|
||||
advised.setInterfaces(targetClass);
|
||||
}
|
||||
else if (Proxy.isProxyClass(targetClass)) {
|
||||
advised.setInterfaces(targetClass.getInterfaces());
|
||||
}
|
||||
specifiedInterfaces = advised.getProxiedInterfaces();
|
||||
if (targetClass != null && targetClass.isInterface()) {
|
||||
specifiedInterfaces = new Class<?>[] {targetClass};
|
||||
}
|
||||
}
|
||||
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
|
||||
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
|
||||
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
|
||||
int nonUserIfcCount = 0;
|
||||
if (addSpringProxy) {
|
||||
nonUserIfcCount++;
|
||||
@@ -126,22 +96,13 @@ public abstract class AopProxyUtils {
|
||||
if (addAdvised) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
if (addDecoratingProxy) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
|
||||
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
|
||||
int index = specifiedInterfaces.length;
|
||||
if (addSpringProxy) {
|
||||
proxiedInterfaces[index] = SpringProxy.class;
|
||||
index++;
|
||||
proxiedInterfaces[specifiedInterfaces.length] = SpringProxy.class;
|
||||
}
|
||||
if (addAdvised) {
|
||||
proxiedInterfaces[index] = Advised.class;
|
||||
index++;
|
||||
}
|
||||
if (addDecoratingProxy) {
|
||||
proxiedInterfaces[index] = DecoratingProxy.class;
|
||||
proxiedInterfaces[proxiedInterfaces.length - 1] = Advised.class;
|
||||
}
|
||||
return proxiedInterfaces;
|
||||
}
|
||||
@@ -163,9 +124,6 @@ public abstract class AopProxyUtils {
|
||||
if (proxy instanceof Advised) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
if (proxy instanceof DecoratingProxy) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - nonUserIfcCount];
|
||||
System.arraycopy(proxyInterfaces, 0, userInterfaces, 0, userInterfaces.length);
|
||||
Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces");
|
||||
@@ -196,38 +154,4 @@ public abstract class AopProxyUtils {
|
||||
return Arrays.equals(a.getAdvisors(), b.getAdvisors());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the given arguments to the target signature in the given method,
|
||||
* if necessary: in particular, if a given vararg argument array does not
|
||||
* match the array type of the declared vararg parameter in the method.
|
||||
* @param method the target method
|
||||
* @param arguments the given arguments
|
||||
* @return a cloned argument array, or the original if no adaptation is needed
|
||||
* @since 4.2.3
|
||||
*/
|
||||
static Object[] adaptArgumentsIfNecessary(Method method, Object... arguments) {
|
||||
if (method.isVarArgs() && !ObjectUtils.isEmpty(arguments)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length == arguments.length) {
|
||||
int varargIndex = paramTypes.length - 1;
|
||||
Class<?> varargType = paramTypes[varargIndex];
|
||||
if (varargType.isArray()) {
|
||||
Object varargArray = arguments[varargIndex];
|
||||
if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
|
||||
Object[] newArguments = new Object[arguments.length];
|
||||
System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
|
||||
Class<?> targetElementType = varargType.getComponentType();
|
||||
int varargLength = Array.getLength(varargArray);
|
||||
Object newVarargArray = Array.newInstance(targetElementType, varargLength);
|
||||
System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
|
||||
newArguments[varargIndex] = newVarargArray;
|
||||
return newArguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,7 +36,6 @@ import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cglib.core.ClassGenerator;
|
||||
import org.springframework.cglib.core.CodeGenerationException;
|
||||
import org.springframework.cglib.core.SpringNamingPolicy;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
@@ -94,7 +93,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
|
||||
/** Logger available to subclasses; static to optimize serialization */
|
||||
protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
|
||||
protected final static Log logger = LogFactory.getLog(CglibAopProxy.class);
|
||||
|
||||
/** Keeps track of the Classes that we have validated for final methods */
|
||||
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<Class<?>, Boolean>();
|
||||
@@ -103,9 +102,9 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
/** The configuration used to configure this proxy */
|
||||
protected final AdvisedSupport advised;
|
||||
|
||||
protected Object[] constructorArgs;
|
||||
private Object[] constructorArgs;
|
||||
|
||||
protected Class<?>[] constructorArgTypes;
|
||||
private Class<?>[] constructorArgTypes;
|
||||
|
||||
/** Dispatcher used for methods on Advised */
|
||||
private final transient AdvisedDispatcher advisedDispatcher;
|
||||
@@ -173,7 +172,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
// Validate the class, writing log messages as necessary.
|
||||
validateClassIfNecessary(proxySuperClass, classLoader);
|
||||
validateClassIfNecessary(proxySuperClass);
|
||||
|
||||
// Configure CGLIB Enhancer...
|
||||
Enhancer enhancer = createEnhancer();
|
||||
@@ -187,7 +186,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
enhancer.setSuperclass(proxySuperClass);
|
||||
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
|
||||
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
|
||||
Callback[] callbacks = getCallbacks(rootClass);
|
||||
Class<?>[] types = new Class<?>[callbacks.length];
|
||||
@@ -240,11 +239,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* Checks to see whether the supplied {@code Class} has already been validated and
|
||||
* validates it if not.
|
||||
*/
|
||||
private void validateClassIfNecessary(Class<?> proxySuperClass, ClassLoader proxyClassLoader) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
private void validateClassIfNecessary(Class<?> proxySuperClass) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
synchronized (validatedClasses) {
|
||||
if (!validatedClasses.containsKey(proxySuperClass)) {
|
||||
doValidateClass(proxySuperClass, proxyClassLoader);
|
||||
doValidateClass(proxySuperClass);
|
||||
validatedClasses.put(proxySuperClass, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
@@ -252,28 +251,19 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for final methods on the given {@code Class}, as well as package-visible
|
||||
* methods across ClassLoaders, and writes warnings to the log for each one found.
|
||||
* Checks for final methods on the {@code Class} and writes warnings to the log
|
||||
* for each one found.
|
||||
*/
|
||||
private void doValidateClass(Class<?> proxySuperClass, ClassLoader proxyClassLoader) {
|
||||
if (Object.class != proxySuperClass) {
|
||||
Method[] methods = proxySuperClass.getDeclaredMethods();
|
||||
private void doValidateClass(Class<?> proxySuperClass) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
Method[] methods = proxySuperClass.getMethods();
|
||||
for (Method method : methods) {
|
||||
int mod = method.getModifiers();
|
||||
if (!Modifier.isStatic(mod)) {
|
||||
if (Modifier.isFinal(mod)) {
|
||||
logger.info("Unable to proxy method [" + method + "] because it is final: " +
|
||||
"All calls to this method via a proxy will NOT be routed to the target instance.");
|
||||
}
|
||||
else if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) && !Modifier.isPrivate(mod) &&
|
||||
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
|
||||
logger.info("Unable to proxy method [" + method + "] because it is package-visible " +
|
||||
"across different ClassLoaders: All calls to this method via a proxy will " +
|
||||
"NOT be routed to the target instance.");
|
||||
}
|
||||
if (!Object.class.equals(method.getDeclaringClass()) && !Modifier.isStatic(method.getModifiers()) &&
|
||||
Modifier.isFinal(method.getModifiers())) {
|
||||
logger.warn("Unable to proxy method [" + method + "] because it is final: " +
|
||||
"All calls to this method via a proxy will NOT be routed to the target instance.");
|
||||
}
|
||||
}
|
||||
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,13 +295,13 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Callback targetDispatcher = isStatic ?
|
||||
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
|
||||
|
||||
Callback[] mainCallbacks = new Callback[] {
|
||||
aopInterceptor, // for normal advice
|
||||
targetInterceptor, // invoke target without considering advice, if optimized
|
||||
new SerializableNoOp(), // no override for methods mapped to this
|
||||
targetDispatcher, this.advisedDispatcher,
|
||||
new EqualsInterceptor(this.advised),
|
||||
new HashCodeInterceptor(this.advised)
|
||||
Callback[] mainCallbacks = new Callback[]{
|
||||
aopInterceptor, // for normal advice
|
||||
targetInterceptor, // invoke target without considering advice, if optimized
|
||||
new SerializableNoOp(), // no override for methods mapped to this
|
||||
targetDispatcher, this.advisedDispatcher,
|
||||
new EqualsInterceptor(this.advised),
|
||||
new HashCodeInterceptor(this.advised)
|
||||
};
|
||||
|
||||
Callback[] callbacks;
|
||||
@@ -647,8 +637,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// Note that the final invoker must be an InvokerInterceptor, so we know
|
||||
// it does nothing but a reflective operation on the target, and no hot
|
||||
// swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
retVal = methodProxy.invoke(target, argsToUse);
|
||||
retVal = methodProxy.invoke(target, args);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
@@ -704,7 +693,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
|
||||
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
|
||||
|
||||
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
|
||||
this.methodProxy = methodProxy;
|
||||
this.publicMethod = Modifier.isPublic(method.getModifiers());
|
||||
@@ -824,7 +812,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method has advice and optimisations are enabled: " + method);
|
||||
}
|
||||
// We know that we are optimising so we can use the FixedStaticChainInterceptors.
|
||||
// We know that we are optimising so we can use the
|
||||
// FixedStaticChainInterceptors.
|
||||
int index = this.fixedInterceptorMap.get(key);
|
||||
return (index + this.fixedInterceptorOffset);
|
||||
}
|
||||
@@ -922,7 +911,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (aa == null || ba == null) {
|
||||
return (aa == ba);
|
||||
}
|
||||
return (aa.getClass() == ba.getClass());
|
||||
return aa.getClass().equals(ba.getClass());
|
||||
}
|
||||
|
||||
private boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
@@ -951,51 +940,4 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB GeneratorStrategy variant which exposes the application ClassLoader
|
||||
* as thread context ClassLoader for the time of class generation
|
||||
* (in order for ASM to pick it up when doing common superclass resolution).
|
||||
*/
|
||||
private static class ClassLoaderAwareUndeclaredThrowableStrategy extends UndeclaredThrowableStrategy {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public ClassLoaderAwareUndeclaredThrowableStrategy(ClassLoader classLoader) {
|
||||
super(UndeclaredThrowableException.class);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generate(ClassGenerator cg) throws Exception {
|
||||
if (this.classLoader == null) {
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader threadContextClassLoader;
|
||||
try {
|
||||
threadContextClassLoader = currentThread.getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access thread context ClassLoader - falling back...
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
boolean overrideClassLoader = !this.classLoader.equals(threadContextClassLoader);
|
||||
if (overrideClassLoader) {
|
||||
currentThread.setContextClassLoader(this.classLoader);
|
||||
}
|
||||
try {
|
||||
return super.generate(cg);
|
||||
}
|
||||
finally {
|
||||
if (overrideClassLoader) {
|
||||
// Reset original thread context ClassLoader.
|
||||
currentThread.setContextClassLoader(threadContextClassLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,23 +17,25 @@
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.SpringProxy;
|
||||
|
||||
/**
|
||||
* Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
|
||||
* or a JDK dynamic proxy.
|
||||
* Default {@link AopProxyFactory} implementation,
|
||||
* creating either a CGLIB proxy or a JDK dynamic proxy.
|
||||
*
|
||||
* <p>Creates a CGLIB proxy if one the following is true for a given
|
||||
* {@link AdvisedSupport} instance:
|
||||
* <p>Creates a CGLIB proxy if one the following is true
|
||||
* for a given {@link AdvisedSupport} instance:
|
||||
* <ul>
|
||||
* <li>the {@code optimize} flag is set
|
||||
* <li>the {@code proxyTargetClass} flag is set
|
||||
* <li>the "optimize" flag is set
|
||||
* <li>the "proxyTargetClass" flag is set
|
||||
* <li>no proxy interfaces have been specified
|
||||
* </ul>
|
||||
*
|
||||
* <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,
|
||||
* <p>Note that the CGLIB library classes have to be present on
|
||||
* the class path if an actual CGLIB proxy needs to be created.
|
||||
*
|
||||
* <p>In general, specify "proxyTargetClass" to enforce a CGLIB proxy,
|
||||
* or specify one or more interfaces to use a JDK dynamic proxy.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
@@ -54,7 +56,7 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
throw new AopConfigException("TargetSource cannot determine target class: " +
|
||||
"Either an interface or a target is required for proxy creation.");
|
||||
}
|
||||
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
|
||||
if (targetClass.isInterface()) {
|
||||
return new JdkDynamicAopProxy(config);
|
||||
}
|
||||
return new ObjenesisCglibAopProxy(config);
|
||||
@@ -70,8 +72,7 @@ public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
* (or no proxy interfaces specified at all).
|
||||
*/
|
||||
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
|
||||
Class<?>[] ifcs = config.getProxiedInterfaces();
|
||||
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
|
||||
Class<?>[] interfaces = config.getProxiedInterfaces();
|
||||
return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0])));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,6 @@ import org.springframework.aop.AopInvocationException;
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -117,7 +116,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
|
||||
}
|
||||
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
|
||||
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
|
||||
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
|
||||
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
|
||||
}
|
||||
@@ -165,15 +164,11 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// The target does not implement the equals(Object) method itself.
|
||||
return equals(args[0]);
|
||||
}
|
||||
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
// The target does not implement the hashCode() method itself.
|
||||
return hashCode();
|
||||
}
|
||||
else if (method.getDeclaringClass() == DecoratingProxy.class) {
|
||||
// There is only getDecoratedClass() declared -> dispatch to proxy config.
|
||||
return AopProxyUtils.ultimateTargetClass(this.advised);
|
||||
}
|
||||
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
|
||||
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
|
||||
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
|
||||
// Service invocations on ProxyConfig with the proxy config...
|
||||
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
|
||||
@@ -203,8 +198,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// We can skip creating a MethodInvocation: just invoke the target directly
|
||||
// Note that the final invoker must be an InvokerInterceptor so we know it does
|
||||
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
|
||||
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
|
||||
+19
-34
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -22,14 +22,14 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.objenesis.SpringObjenesis;
|
||||
import org.springframework.objenesis.ObjenesisException;
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
|
||||
/**
|
||||
* Objenesis-based extension of {@link CglibAopProxy} to create proxy instances
|
||||
* without invoking the constructor of the class.
|
||||
* Objenesis based extension of {@link CglibAopProxy} to create proxy instances without
|
||||
* invoking the constructor of the class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -37,49 +37,34 @@ class ObjenesisCglibAopProxy extends CglibAopProxy {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ObjenesisCglibAopProxy.class);
|
||||
|
||||
private static final SpringObjenesis objenesis = new SpringObjenesis();
|
||||
private final ObjenesisStd objenesis;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ObjenesisCglibAopProxy for the given AOP configuration.
|
||||
* @param config the AOP configuration as AdvisedSupport object
|
||||
* Creates a new {@link ObjenesisCglibAopProxy} using the given {@link AdvisedSupport}.
|
||||
* @param config must not be {@literal null}.
|
||||
*/
|
||||
public ObjenesisCglibAopProxy(AdvisedSupport config) {
|
||||
super(config);
|
||||
this.objenesis = new ObjenesisStd(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
|
||||
Class<?> proxyClass = enhancer.createClass();
|
||||
Object proxyInstance = null;
|
||||
|
||||
if (objenesis.isWorthTrying()) {
|
||||
try {
|
||||
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Unable to instantiate proxy using Objenesis, " +
|
||||
"falling back to regular proxy construction", ex);
|
||||
}
|
||||
try {
|
||||
Factory factory = (Factory) this.objenesis.newInstance(enhancer.createClass());
|
||||
factory.setCallbacks(callbacks);
|
||||
return factory;
|
||||
}
|
||||
|
||||
if (proxyInstance == null) {
|
||||
// Regular instantiation via default constructor...
|
||||
try {
|
||||
proxyInstance = (this.constructorArgs != null ?
|
||||
proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) :
|
||||
proxyClass.newInstance());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
|
||||
"and regular proxy instantiation via default constructor fails as well", ex);
|
||||
catch (ObjenesisException ex) {
|
||||
// Fallback to regular proxy construction on unsupported JVMs
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unable to instantiate proxy using Objenesis, falling back to regular proxy construction", ex);
|
||||
}
|
||||
return super.createProxyClassAndInstance(enhancer, callbacks);
|
||||
}
|
||||
|
||||
((Factory) proxyInstance).setCallbacks(callbacks);
|
||||
return proxyInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,9 +22,9 @@ import org.springframework.aop.TargetSource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Factory for AOP proxies for programmatic use, rather than via declarative
|
||||
* setup in a bean factory. This class provides a simple way of obtaining
|
||||
* and configuring AOP proxy instances in custom user code.
|
||||
* Factory for AOP proxies for programmatic use, rather than via a bean
|
||||
* factory. This class provides a simple way of obtaining and configuring
|
||||
* AOP proxies in code.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -44,7 +44,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -414,7 +414,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the advisor (interceptor) chain. Advisors that are sourced
|
||||
* Create the advisor (interceptor) chain. Aadvisors that are sourced
|
||||
* from a BeanFactory will be refreshed each time a new prototype instance
|
||||
* is added. Interceptors added programmatically through the factory API
|
||||
* are unaffected by such changes.
|
||||
@@ -525,7 +525,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
beans.add(bean);
|
||||
names.put(bean, name);
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(beans);
|
||||
OrderComparator.sort(beans);
|
||||
for (Object bean : beans) {
|
||||
String name = names.get(bean);
|
||||
if (name.startsWith(prefix)) {
|
||||
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Base class with common functionality for proxy processors, in particular
|
||||
* ClassLoader management and the {@link #evaluateProxyInterfaces} algorithm.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
* @see AbstractAdvisingBeanPostProcessor
|
||||
* @see org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean {
|
||||
|
||||
/**
|
||||
* This should run after all other processors, so that it can just add
|
||||
* an advisor to existing proxies rather than double-proxy.
|
||||
*/
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private boolean classLoaderConfigured = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set the ordering which will apply to this class's implementation
|
||||
* of Ordered, used when applying multiple processors.
|
||||
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
|
||||
* @param order the ordering value
|
||||
*/
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ClassLoader to generate the proxy class in.
|
||||
* <p>Default is the bean ClassLoader, i.e. the ClassLoader used by the containing
|
||||
* {@link org.springframework.beans.factory.BeanFactory} for loading all bean classes.
|
||||
* This can be overridden here for specific proxies.
|
||||
*/
|
||||
public void setProxyClassLoader(ClassLoader classLoader) {
|
||||
this.proxyClassLoader = classLoader;
|
||||
this.classLoaderConfigured = (classLoader != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured proxy ClassLoader for this processor.
|
||||
*/
|
||||
protected ClassLoader getProxyClassLoader() {
|
||||
return this.proxyClassLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
if (!this.classLoaderConfigured) {
|
||||
this.proxyClassLoader = classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check the interfaces on the given bean class and apply them to the {@link ProxyFactory},
|
||||
* if appropriate.
|
||||
* <p>Calls {@link #isConfigurationCallbackInterface} and {@link #isInternalLanguageInterface}
|
||||
* to filter for reasonable proxy interfaces, falling back to a target-class proxy otherwise.
|
||||
* @param beanClass the class of the bean
|
||||
* @param proxyFactory the ProxyFactory for the bean
|
||||
*/
|
||||
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
|
||||
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
|
||||
boolean hasReasonableProxyInterface = false;
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
|
||||
ifc.getMethods().length > 0) {
|
||||
hasReasonableProxyInterface = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasReasonableProxyInterface) {
|
||||
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given interface is just a container callback and
|
||||
* therefore not to be considered as a reasonable proxy interface.
|
||||
* <p>If no reasonable proxy interface is found for a given bean, it will get
|
||||
* proxied with its full target class, assuming that as the user's intention.
|
||||
* @param ifc the interface to check
|
||||
* @return whether the given interface is just a container callback
|
||||
*/
|
||||
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
|
||||
return (InitializingBean.class == ifc || DisposableBean.class == ifc ||
|
||||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given interface is a well-known internal language interface
|
||||
* and therefore not to be considered as a reasonable proxy interface.
|
||||
* <p>If no reasonable proxy interface is found for a given bean, it will get
|
||||
* proxied with its full target class, assuming that as the user's intention.
|
||||
* @param ifc the interface to check
|
||||
* @return whether the given interface is an internal language interface
|
||||
*/
|
||||
protected boolean isInternalLanguageInterface(Class<?> ifc) {
|
||||
return ifc.getName().equals("groovy.lang.GroovyObject");
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -109,7 +109,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
this.target = target;
|
||||
this.targetClass = targetClass;
|
||||
this.method = BridgeMethodResolver.findBridgedMethod(method);
|
||||
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
|
||||
this.arguments = arguments;
|
||||
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArguments(Object... arguments) {
|
||||
public void setArguments(Object[] arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
* @see java.lang.Object#clone()
|
||||
*/
|
||||
@Override
|
||||
public MethodInvocation invocableClone(Object... arguments) {
|
||||
public MethodInvocation invocableClone(Object[] arguments) {
|
||||
// Force initialization of the user attributes Map,
|
||||
// for having a shared Map reference in the clone.
|
||||
if (this.userAttributes == null) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -109,7 +109,7 @@ public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {
|
||||
logger.trace("Trying to find handler for exception of type [" + exceptionClass.getName() + "]");
|
||||
}
|
||||
Method handler = this.exceptionHandlerMap.get(exceptionClass);
|
||||
while (handler == null && exceptionClass != Throwable.class) {
|
||||
while (handler == null && !exceptionClass.equals(Throwable.class)) {
|
||||
exceptionClass = exceptionClass.getSuperclass();
|
||||
handler = this.exceptionHandlerMap.get(exceptionClass);
|
||||
}
|
||||
|
||||
+12
-6
@@ -1,12 +1,18 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* SPI package allowing Spring AOP framework to handle arbitrary advice types.
|
||||
*
|
||||
* <p>Users who want merely to <i>use</i> the Spring AOP framework, rather than extend
|
||||
* <br>
|
||||
* Users who want merely to <i>use</i> the Spring AOP framework, rather than extend
|
||||
* its capabilities, don't need to concern themselves with this package.
|
||||
* <br>
|
||||
* You may wish to use these adapters to wrap Spring-specific advices, such as MethodBeforeAdvice,
|
||||
* in MethodInterceptor, to allow their use in another AOP framework supporting the AOP Alliance interfaces.
|
||||
* </br>
|
||||
* <br>
|
||||
* These adapters do not depend on any other Spring framework classes to allow such usage.
|
||||
* </br>
|
||||
*
|
||||
* <p>You may wish to use these adapters to wrap Spring-specific advices, such as MethodBeforeAdvice,
|
||||
* in MethodInterceptor, to allow their use in another AOP framework supporting the AOP Alliance interfaces.
|
||||
*
|
||||
* <p>These adapters do not depend on any other Spring framework classes to allow such usage.
|
||||
*/
|
||||
package org.springframework.aop.framework.adapter;
|
||||
|
||||
|
||||
+4
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,7 @@ import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
|
||||
/**
|
||||
* Generic auto proxy creator that builds AOP proxies for specific beans
|
||||
@@ -138,11 +138,10 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
|
||||
* @param advisors the source List of Advisors
|
||||
* @return the sorted List of Advisors
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.core.annotation.Order
|
||||
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
|
||||
* @see org.springframework.core.OrderComparator
|
||||
*/
|
||||
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
|
||||
AnnotationAwareOrderComparator.sort(advisors);
|
||||
OrderComparator.sort(advisors);
|
||||
return advisors;
|
||||
}
|
||||
|
||||
|
||||
+103
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,20 +33,25 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.aop.framework.ProxyConfig;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.framework.ProxyProcessorSupport;
|
||||
import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
|
||||
import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
@@ -89,8 +94,9 @@ import org.springframework.util.StringUtils;
|
||||
* @see DefaultAdvisorAutoProxyCreator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
|
||||
public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
|
||||
Ordered, AopInfrastructureBean {
|
||||
|
||||
/**
|
||||
* Convenience constant for subclasses: Return value for "do not proxy".
|
||||
@@ -109,6 +115,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/** Default value is same as non-ordered */
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
/** Default is global AdvisorAdapterRegistry */
|
||||
private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
|
||||
|
||||
@@ -125,8 +134,14 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
private TargetSourceCreator[] customTargetSourceCreators;
|
||||
|
||||
private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private boolean classLoaderConfigured = false;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(64);
|
||||
|
||||
private final Set<String> targetSourcedBeans =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
|
||||
|
||||
@@ -135,8 +150,21 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<Object, Class<?>>(16);
|
||||
|
||||
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);
|
||||
|
||||
/**
|
||||
* Set the ordering which will apply to this class's implementation
|
||||
* of Ordered, used when applying multiple BeanPostProcessors.
|
||||
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
|
||||
* @param order ordering value
|
||||
*/
|
||||
public final void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not the proxy should be frozen, preventing advice
|
||||
@@ -200,6 +228,24 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ClassLoader to generate the proxy class in.
|
||||
* <p>Default is the bean ClassLoader, i.e. the ClassLoader used by the
|
||||
* containing BeanFactory for loading all bean classes. This can be
|
||||
* overridden here for specific proxies.
|
||||
*/
|
||||
public void setProxyClassLoader(ClassLoader classLoader) {
|
||||
this.proxyClassLoader = classLoader;
|
||||
this.classLoaderConfigured = (classLoader != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
if (!this.classLoaderConfigured) {
|
||||
this.proxyClassLoader = classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
@@ -216,9 +262,6 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
if (this.proxyTypes.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Object cacheKey = getCacheKey(beanClass, beanName);
|
||||
return this.proxyTypes.get(cacheKey);
|
||||
}
|
||||
@@ -304,23 +347,12 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
/**
|
||||
* Build a cache key for the given bean class and bean name.
|
||||
* <p>Note: As of 4.2.3, this implementation does not return a concatenated
|
||||
* class/name String anymore but rather the most efficient cache key possible:
|
||||
* a plain bean name, prepended with {@link BeanFactory#FACTORY_BEAN_PREFIX}
|
||||
* in case of a {@code FactoryBean}; or if no bean name specified, then the
|
||||
* given bean {@code Class} as-is.
|
||||
* @param beanClass the bean class
|
||||
* @param beanName the bean name
|
||||
* @return the cache key for the given class and name
|
||||
*/
|
||||
protected Object getCacheKey(Class<?> beanClass, String beanName) {
|
||||
if (StringUtils.hasLength(beanName)) {
|
||||
return (FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
|
||||
}
|
||||
else {
|
||||
return beanClass;
|
||||
}
|
||||
return beanClass.getName() + "_" + beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,8 +378,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
|
||||
if (specificInterceptors != DO_NOT_PROXY) {
|
||||
this.advisedBeans.put(cacheKey, Boolean.TRUE);
|
||||
Object proxy = createProxy(
|
||||
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
|
||||
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
|
||||
this.proxyTypes.put(cacheKey, proxy.getClass());
|
||||
return proxy;
|
||||
}
|
||||
@@ -436,11 +467,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
protected Object createProxy(
|
||||
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
|
||||
|
||||
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
|
||||
}
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
@@ -465,7 +493,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
proxyFactory.setPreFiltered(true);
|
||||
}
|
||||
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
return proxyFactory.getProxy(this.proxyClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -482,6 +510,47 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the interfaces on the given bean class and apply them to the ProxyFactory,
|
||||
* if appropriate.
|
||||
* <p>Calls {@link #isConfigurationCallbackInterface} to filter for reasonable
|
||||
* proxy interfaces, falling back to a target-class proxy otherwise.
|
||||
* @param beanClass the class of the bean
|
||||
* @param proxyFactory the ProxyFactory for the bean
|
||||
*/
|
||||
private void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
|
||||
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
|
||||
boolean hasReasonableProxyInterface = false;
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
if (!isConfigurationCallbackInterface(ifc) && ifc.getMethods().length > 0) {
|
||||
hasReasonableProxyInterface = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasReasonableProxyInterface) {
|
||||
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given interface is just a container callback and
|
||||
* therefore not to be considered as a reasonable proxy interface.
|
||||
* <p>If no reasonable proxy interface is found for a given bean, it will get
|
||||
* proxied with its full target class, assuming that as the user's intention.
|
||||
* @param ifc the interface to check
|
||||
* @return whether the given interface is just a container callback
|
||||
*/
|
||||
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
|
||||
return (ifc.equals(InitializingBean.class) || ifc.equals(DisposableBean.class) ||
|
||||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the Advisors returned by the subclass are pre-filtered
|
||||
* to match the bean's target class already, allowing the ClassFilter check
|
||||
@@ -511,7 +580,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
List<Object> allInterceptors = new ArrayList<Object>();
|
||||
if (specificInterceptors != null) {
|
||||
allInterceptors.addAll(Arrays.asList(specificInterceptors));
|
||||
if (commonInterceptors.length > 0) {
|
||||
if (commonInterceptors != null) {
|
||||
if (this.applyCommonInterceptorsFirst) {
|
||||
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
|
||||
}
|
||||
@@ -521,7 +590,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
int nrOfCommonInterceptors = commonInterceptors.length;
|
||||
int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
|
||||
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
|
||||
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
|
||||
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
|
||||
@@ -539,8 +608,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
* @see #setInterceptorNames
|
||||
*/
|
||||
private Advisor[] resolveInterceptorNames() {
|
||||
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
(ConfigurableBeanFactory) this.beanFactory : null);
|
||||
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory) ?
|
||||
(ConfigurableBeanFactory) this.beanFactory : null;
|
||||
List<Advisor> advisors = new ArrayList<Advisor>();
|
||||
for (String beanName : this.interceptorNames) {
|
||||
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
|
||||
@@ -557,7 +626,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
* <p>The default implementation is empty.
|
||||
* @param proxyFactory ProxyFactory that is already configured with
|
||||
* TargetSource and interfaces and will be used to create the proxy
|
||||
* immediately after this method returns
|
||||
* immediably after this method returns
|
||||
*/
|
||||
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
|
||||
}
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
|
||||
/**
|
||||
* Extension of {@link AbstractAutoProxyCreator} which implements {@link BeanFactoryAware},
|
||||
* adds exposure of the original target class for each proxied bean
|
||||
* ({@link AutoProxyUtils#ORIGINAL_TARGET_CLASS_ATTRIBUTE}),
|
||||
* and participates in an externally enforced target-class mode for any given bean
|
||||
* ({@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE}).
|
||||
* This post-processor is therefore aligned with {@link AbstractAutoProxyCreator}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2.3
|
||||
* @see AutoProxyUtils#shouldProxyTargetClass
|
||||
* @see AutoProxyUtils#determineTargetClass
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractBeanFactoryAwareAdvisingPostProcessor extends AbstractAdvisingBeanPostProcessor
|
||||
implements BeanFactoryAware {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = (beanFactory instanceof ConfigurableListableBeanFactory ?
|
||||
(ConfigurableListableBeanFactory) beanFactory : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
|
||||
if (this.beanFactory != null) {
|
||||
AutoProxyUtils.exposeTargetClass(this.beanFactory, beanName, bean.getClass());
|
||||
}
|
||||
|
||||
ProxyFactory proxyFactory = super.prepareProxyFactory(bean, beanName);
|
||||
if (!proxyFactory.isProxyTargetClass() && this.beanFactory != null &&
|
||||
AutoProxyUtils.shouldProxyTargetClass(this.beanFactory, beanName)) {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,21 +37,10 @@ public abstract class AutoProxyUtils {
|
||||
* <p>Proxy factories can set this attribute if they built a target class proxy
|
||||
* for a specific bean, and want to enforce that that bean can always be cast
|
||||
* to its target class (even if AOP advices get applied through auto-proxying).
|
||||
* @see #shouldProxyTargetClass
|
||||
*/
|
||||
public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
|
||||
|
||||
/**
|
||||
* Bean definition attribute that indicates the original target class of an
|
||||
* auto-proxied bean, e.g. to be used for the introspection of annotations
|
||||
* on the target class behind an interface-based proxy.
|
||||
* @since 4.2.3
|
||||
* @see #determineTargetClass
|
||||
*/
|
||||
public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the given bean should be proxied with its target
|
||||
@@ -70,40 +59,4 @@ public abstract class AutoProxyUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the original target class for the specified bean, if possible,
|
||||
* otherwise falling back to a regular {@code getType} lookup.
|
||||
* @param beanFactory the containing ConfigurableListableBeanFactory
|
||||
* @param beanName the name of the bean
|
||||
* @return the original target class as stored in the bean definition, if any
|
||||
* @since 4.2.3
|
||||
* @see org.springframework.beans.factory.BeanFactory#getType(String)
|
||||
*/
|
||||
public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanName == null) {
|
||||
return null;
|
||||
}
|
||||
if (beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
|
||||
Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
|
||||
if (targetClass != null) {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
return beanFactory.getType(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the given target class for the specified bean, if possible.
|
||||
* @param beanFactory the containing ConfigurableListableBeanFactory
|
||||
* @param beanName the name of the bean
|
||||
* @param targetClass the corresponding target class
|
||||
* @since 4.2.3
|
||||
*/
|
||||
static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName, Class<?> targetClass) {
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Bean post-processors for use in ApplicationContexts to simplify AOP usage
|
||||
* by automatically creating AOP proxies without the need to use a ProxyFactoryBean.
|
||||
*
|
||||
@@ -8,5 +10,7 @@
|
||||
* <p><b>NB</b>: Automatic auto-proxying is not supported for BeanFactory implementations,
|
||||
* as post-processors beans are only automatically detected in application contexts.
|
||||
* Post-processors can be explicitly registered on a ConfigurableBeanFactory instead.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,20 +17,19 @@
|
||||
package org.springframework.aop.framework.autoproxy.target;
|
||||
|
||||
import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
|
||||
import org.springframework.aop.target.CommonsPool2TargetSource;
|
||||
import org.springframework.aop.target.CommonsPoolTargetSource;
|
||||
import org.springframework.aop.target.PrototypeTargetSource;
|
||||
import org.springframework.aop.target.ThreadLocalTargetSource;
|
||||
|
||||
/**
|
||||
* Convenient TargetSourceCreator using bean name prefixes to create one of three
|
||||
* well-known TargetSource types:
|
||||
* <li>: CommonsPool2TargetSource
|
||||
* <li>: CommonsPoolTargetSource
|
||||
* <li>% ThreadLocalTargetSource
|
||||
* <li>! PrototypeTargetSource
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Stephane Nicoll
|
||||
* @see org.springframework.aop.target.CommonsPool2TargetSource
|
||||
* @see org.springframework.aop.target.CommonsPoolTargetSource
|
||||
* @see org.springframework.aop.target.ThreadLocalTargetSource
|
||||
* @see org.springframework.aop.target.PrototypeTargetSource
|
||||
*/
|
||||
@@ -45,7 +44,7 @@ public class QuickTargetSourceCreator extends AbstractBeanFactoryBasedTargetSour
|
||||
Class<?> beanClass, String beanName) {
|
||||
|
||||
if (beanName.startsWith(PREFIX_COMMONS_POOL)) {
|
||||
CommonsPool2TargetSource cpts = new CommonsPool2TargetSource();
|
||||
CommonsPoolTargetSource cpts = new CommonsPoolTargetSource();
|
||||
cpts.setMaxSize(25);
|
||||
return cpts;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Package containing Spring's basic AOP infrastructure, compliant with the
|
||||
* <a href="http://aopalliance.sourceforge.net">AOP Alliance</a> interfaces.
|
||||
*
|
||||
@@ -11,5 +13,7 @@
|
||||
* <p>The ProxyFactoryBean is a convenient way to create AOP proxies in a BeanFactory
|
||||
* or ApplicationContext. However, proxies can be created programmatically using the
|
||||
* ProxyFactory class.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
|
||||
+25
-231
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,35 +18,20 @@ package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
import org.springframework.lang.UsesJava8;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Base class for asynchronous method execution aspects, such as
|
||||
* {@code org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor}
|
||||
* {@link org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor}
|
||||
* or {@code org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect}.
|
||||
*
|
||||
* <p>Provides support for <i>executor qualification</i> on a method-by-method basis.
|
||||
@@ -55,89 +40,44 @@ import org.springframework.util.concurrent.ListenableFuture;
|
||||
* bean to be used when executing it, e.g. through an annotation attribute.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
|
||||
* <p>Note that the initial lookup happens by type; this is just the fallback
|
||||
* in case of multiple executor beans found in the context.
|
||||
* @since 4.2.6
|
||||
*/
|
||||
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
|
||||
|
||||
|
||||
// Java 8's CompletableFuture type present?
|
||||
private static final boolean completableFuturePresent = ClassUtils.isPresent(
|
||||
"java.util.concurrent.CompletableFuture", AsyncExecutionInterceptor.class.getClassLoader());
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<Method, AsyncTaskExecutor>(16);
|
||||
|
||||
private volatile Executor defaultExecutor;
|
||||
|
||||
private AsyncUncaughtExceptionHandler exceptionHandler;
|
||||
private Executor defaultExecutor;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
* Create a new {@link AsyncExecutionAspectSupport}, using the provided default
|
||||
* executor unless individual async methods indicate via qualifier that a more
|
||||
* specific executor should be used.
|
||||
* @param defaultExecutor the executor to use when executing asynchronous methods
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
|
||||
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AsyncExecutionAspectSupport} with the given exception handler.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
this.defaultExecutor = defaultExecutor;
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supply the executor to be used when executing async methods.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
* @see #getExecutorQualifier(Method)
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code
|
||||
* AsyncTaskExecutor} or {@link java.util.concurrent.ExecutorService}) to delegate to
|
||||
* unless a more specific executor has been requested via a qualifier on the async
|
||||
* method, in which case the executor will be looked up at invocation time against the
|
||||
* enclosing bean factory.
|
||||
* @see #getExecutorQualifier
|
||||
* @see #setBeanFactory(BeanFactory)
|
||||
* @see #getDefaultExecutor(BeanFactory)
|
||||
*/
|
||||
public void setExecutor(Executor defaultExecutor) {
|
||||
this.defaultExecutor = defaultExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply the {@link AsyncUncaughtExceptionHandler} to use to handle exceptions
|
||||
* thrown by invoking asynchronous methods with a {@code void} return type.
|
||||
*/
|
||||
public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link BeanFactory} to be used when looking up executors by qualifier
|
||||
* or when relying on the default executor lookup algorithm.
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
* @see #getDefaultExecutor(BeanFactory)
|
||||
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
@@ -147,33 +87,24 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* Determine the specific executor to use when executing the given method.
|
||||
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
|
||||
* @return the executor to use (or {@code null}, but just if no default executor is available)
|
||||
* @return the executor to use (or {@code null}, but just if no default executor has been set)
|
||||
*/
|
||||
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
|
||||
AsyncTaskExecutor executor = this.executors.get(method);
|
||||
if (executor == null) {
|
||||
Executor targetExecutor;
|
||||
Executor executorToUse = this.defaultExecutor;
|
||||
String qualifier = getExecutorQualifier(method);
|
||||
if (StringUtils.hasLength(qualifier)) {
|
||||
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
|
||||
Assert.notNull(this.beanFactory, "BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
this.beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
else {
|
||||
targetExecutor = this.defaultExecutor;
|
||||
if (targetExecutor == null) {
|
||||
synchronized (this.executors) {
|
||||
if (this.defaultExecutor == null) {
|
||||
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
|
||||
}
|
||||
targetExecutor = this.defaultExecutor;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetExecutor == null) {
|
||||
else if (executorToUse == null) {
|
||||
return null;
|
||||
}
|
||||
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
|
||||
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
|
||||
executor = (executorToUse instanceof AsyncTaskExecutor ?
|
||||
(AsyncTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
|
||||
this.executors.put(method, executor);
|
||||
}
|
||||
return executor;
|
||||
@@ -186,146 +117,9 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* been specified and that the {@linkplain #setExecutor(Executor) default executor}
|
||||
* should be used.
|
||||
* @param method the method to inspect for executor qualifier metadata
|
||||
* @return the qualifier if specified, otherwise empty String or {@code null}
|
||||
* @return the qualifier if specified, otherwise empty string or {@code null}
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
*/
|
||||
protected abstract String getExecutorQualifier(Method method);
|
||||
|
||||
/**
|
||||
* Retrieve a target executor for the given qualifier.
|
||||
* @param qualifier the qualifier to resolve
|
||||
* @return the target executor, or {@code null} if none available
|
||||
* @since 4.2.6
|
||||
* @see #getExecutorQualifier(Method)
|
||||
*/
|
||||
protected Executor findQualifiedExecutor(BeanFactory beanFactory, String qualifier) {
|
||||
if (beanFactory == null) {
|
||||
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
}
|
||||
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve or build a default executor for this advice instance.
|
||||
* An executor returned from here will be cached for further use.
|
||||
* <p>The default implementation searches for a unique {@link TaskExecutor} bean
|
||||
* in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
|
||||
* If neither of the two is resolvable, this implementation will return {@code null}.
|
||||
* @param beanFactory the BeanFactory to use for a default executor lookup
|
||||
* @return the default executor, or {@code null} if none available
|
||||
* @since 4.2.6
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
|
||||
*/
|
||||
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
|
||||
if (beanFactory != null) {
|
||||
try {
|
||||
// Search for TaskExecutor bean... not plain Executor since that would
|
||||
// match with ScheduledExecutorService as well, which is unusable for
|
||||
// our purposes here. TaskExecutor is more clearly designed for it.
|
||||
return beanFactory.getBean(TaskExecutor.class);
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
try {
|
||||
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex2) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
|
||||
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
|
||||
"as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
logger.debug("Could not find default TaskExecutor bean", ex);
|
||||
// Giving up -> either using local default executor or none at all...
|
||||
logger.info("No TaskExecutor bean found for async processing");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegate for actually executing the given task with the chosen executor.
|
||||
* @param task the task to execute
|
||||
* @param executor the chosen executor
|
||||
* @param returnType the declared return type (potentially a {@link Future} variant)
|
||||
* @return the execution result (potentially a corresponding {@link Future} handle)
|
||||
*/
|
||||
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
|
||||
if (completableFuturePresent) {
|
||||
Future<Object> result = CompletableFutureDelegate.processCompletableFuture(returnType, task, executor);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (ListenableFuture.class.isAssignableFrom(returnType)) {
|
||||
return ((AsyncListenableTaskExecutor) executor).submitListenable(task);
|
||||
}
|
||||
else if (Future.class.isAssignableFrom(returnType)) {
|
||||
return executor.submit(task);
|
||||
}
|
||||
else {
|
||||
executor.submit(task);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a fatal error thrown while asynchronously invoking the specified
|
||||
* {@link Method}.
|
||||
* <p>If the return type of the method is a {@link Future} object, the original
|
||||
* exception can be propagated by just throwing it at the higher level. However,
|
||||
* for all other cases, the exception will not be transmitted back to the client.
|
||||
* In that later case, the current {@link AsyncUncaughtExceptionHandler} will be
|
||||
* used to manage such exception.
|
||||
* @param ex the exception to handle
|
||||
* @param method the method that was invoked
|
||||
* @param params the parameters used to invoke the method
|
||||
*/
|
||||
protected void handleError(Throwable ex, Method method, Object... params) throws Exception {
|
||||
if (Future.class.isAssignableFrom(method.getReturnType())) {
|
||||
ReflectionUtils.rethrowException(ex);
|
||||
}
|
||||
else {
|
||||
// Could not transmit the exception to the caller with default executor
|
||||
try {
|
||||
this.exceptionHandler.handleUncaughtException(ex, method, params);
|
||||
}
|
||||
catch (Throwable ex2) {
|
||||
logger.error("Exception handler for async method '" + method.toGenericString() +
|
||||
"' threw unexpected exception itself", ex2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a hard dependency on Java 8.
|
||||
*/
|
||||
@UsesJava8
|
||||
private static class CompletableFutureDelegate {
|
||||
|
||||
public static <T> Future<T> processCompletableFuture(Class<?> returnType, final Callable<T> task, Executor executor) {
|
||||
if (!CompletableFuture.class.isAssignableFrom(returnType)) {
|
||||
return null;
|
||||
}
|
||||
return CompletableFuture.supplyAsync(new Supplier<T>() {
|
||||
@Override
|
||||
public T get() {
|
||||
try {
|
||||
return task.call();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new CompletionException(ex);
|
||||
}
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+30
-60
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@@ -26,12 +25,11 @@ import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* AOP Alliance {@code MethodInterceptor} that processes method invocations
|
||||
@@ -48,44 +46,27 @@ import org.springframework.util.ClassUtils;
|
||||
* (like Spring's {@link org.springframework.scheduling.annotation.AsyncResult}
|
||||
* or EJB 3.1's {@code javax.ejb.AsyncResult}).
|
||||
*
|
||||
* <p>When the return type is {@code java.util.concurrent.Future}, any exception thrown
|
||||
* during the execution can be accessed and managed by the caller. With {@code void}
|
||||
* return type however, such exceptions cannot be transmitted back. In that case an
|
||||
* {@link AsyncUncaughtExceptionHandler} can be registered to process such exceptions.
|
||||
*
|
||||
* <p>As of Spring 3.1.2 the {@code AnnotationAsyncExecutionInterceptor} subclass is
|
||||
* preferred for use due to its support for executor qualification in conjunction with
|
||||
* Spring's {@code @Async} annotation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.0
|
||||
* @see org.springframework.scheduling.annotation.Async
|
||||
* @see org.springframework.scheduling.annotation.AsyncAnnotationAdvisor
|
||||
* @see org.springframework.scheduling.annotation.AnnotationAsyncExecutionInterceptor
|
||||
*/
|
||||
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
}
|
||||
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
implements MethodInterceptor, Ordered {
|
||||
|
||||
/**
|
||||
* Create a new {@code AsyncExecutionInterceptor}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
super(defaultExecutor, exceptionHandler);
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,34 +81,37 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
|
||||
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
|
||||
AsyncTaskExecutor executor = determineAsyncExecutor(specificMethod);
|
||||
if (executor == null) {
|
||||
throw new IllegalStateException(
|
||||
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
|
||||
}
|
||||
|
||||
Callable<Object> task = new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
try {
|
||||
Object result = invocation.proceed();
|
||||
if (result instanceof Future) {
|
||||
return ((Future<?>) result).get();
|
||||
Future<?> result = executor.submit(
|
||||
new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
try {
|
||||
Object result = invocation.proceed();
|
||||
if (result instanceof Future) {
|
||||
return ((Future<?>) result).get();
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
ReflectionUtils.rethrowException(ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleError(ex, userDeclaredMethod, invocation.getArguments());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return doSubmit(task, executor, invocation.getMethod().getReturnType());
|
||||
if (Future.class.isAssignableFrom(invocation.getMethod().getReturnType())) {
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,20 +127,6 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation searches for a unique {@link org.springframework.core.task.TaskExecutor}
|
||||
* bean in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
|
||||
* If neither of the two is resolvable (e.g. if no {@code BeanFactory} was configured at all),
|
||||
* this implementation falls back to a newly created {@link SimpleAsyncTaskExecutor} instance
|
||||
* for local use if no default could be found.
|
||||
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
|
||||
*/
|
||||
@Override
|
||||
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
|
||||
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
|
||||
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A strategy for handling uncaught exceptions thrown from asynchronous methods.
|
||||
*
|
||||
* <p>An asynchronous method usually returns a {@link java.util.concurrent.Future}
|
||||
* instance that gives access to the underlying exception. When the method does
|
||||
* not provide that return type, this handler can be used to managed such
|
||||
* uncaught exceptions.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface AsyncUncaughtExceptionHandler {
|
||||
|
||||
/**
|
||||
* Handle the given uncaught exception thrown from an asynchronous method.
|
||||
* @param ex the exception thrown from the asynchronous method
|
||||
* @param method the asynchronous method
|
||||
* @param params the parameters used to invoked the method
|
||||
*/
|
||||
void handleUncaughtException(Throwable ex, Method method, Object... params);
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,7 +24,7 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Interceptor that exposes the current {@link org.aopalliance.intercept.MethodInvocation}
|
||||
@@ -41,7 +41,7 @@ import org.springframework.core.PriorityOrdered;
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
|
||||
public class ExposeInvocationInterceptor implements MethodInterceptor, Ordered, Serializable {
|
||||
|
||||
/** Singleton instance of this class */
|
||||
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
|
||||
@@ -98,7 +98,7 @@ public class ExposeInvocationInterceptor implements MethodInterceptor, PriorityO
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return PriorityOrdered.HIGHEST_PRECEDENCE + 1;
|
||||
return Ordered.HIGHEST_PRECEDENCE + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,26 +16,21 @@
|
||||
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
import com.jamonapi.MonKey;
|
||||
import com.jamonapi.MonKeyImp;
|
||||
import com.jamonapi.Monitor;
|
||||
import com.jamonapi.MonitorFactory;
|
||||
import com.jamonapi.utils.Misc;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
/**
|
||||
* Performance monitor interceptor that uses <b>JAMon</b> library to perform the
|
||||
* performance measurement on the intercepted method and output the stats.
|
||||
* In addition, it tracks/counts exceptions thrown by the intercepted method.
|
||||
* The stack traces can be viewed in the JAMon web application.
|
||||
* Performance monitor interceptor that uses <b>JAMon</b> library
|
||||
* to perform the performance measurement on the intercepted method
|
||||
* and output the stats.
|
||||
*
|
||||
* <p>This code is inspired by Thierry Templier's blog.
|
||||
*
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Steve Souza
|
||||
* @since 1.1.3
|
||||
* @see com.jamonapi.MonitorFactory
|
||||
* @see PerformanceMonitorInterceptor
|
||||
@@ -108,16 +103,10 @@ public class JamonPerformanceMonitorInterceptor extends AbstractMonitoringInterc
|
||||
@Override
|
||||
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
|
||||
String name = createInvocationTraceName(invocation);
|
||||
MonKey key = new MonKeyImp(name, name, "ms.");
|
||||
|
||||
Monitor monitor = MonitorFactory.start(key);
|
||||
Monitor monitor = MonitorFactory.start(name);
|
||||
try {
|
||||
return invocation.proceed();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
trackException(key, ex);
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
monitor.stop();
|
||||
if (!this.trackAllInvocations || isLogEnabled(logger)) {
|
||||
@@ -126,19 +115,4 @@ public class JamonPerformanceMonitorInterceptor extends AbstractMonitoringInterc
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the thrown exception and put the stack trace in the details portion of the key.
|
||||
* This will allow the stack trace to be viewed in the JAMon web application.
|
||||
*/
|
||||
protected void trackException(MonKey key, Throwable ex) {
|
||||
String stackTrace = "stackTrace=" + Misc.getExceptionTrace(ex);
|
||||
key.setDetails(stackTrace);
|
||||
|
||||
// Specific exception counter. Example: java.lang.RuntimeException
|
||||
MonitorFactory.add(new MonKeyImp(ex.getClass().getName(), stackTrace, "Exception"), 1);
|
||||
|
||||
// General exception counter which is a total for all exceptions thrown
|
||||
MonitorFactory.add(new MonKeyImp(MonitorFactory.EXCEPTIONS_LABEL, stackTrace, "Exception"), 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A default {@link AsyncUncaughtExceptionHandler} that simply logs the exception.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.1
|
||||
*/
|
||||
public class SimpleAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
|
||||
|
||||
private final Log logger = LogFactory.getLog(SimpleAsyncUncaughtExceptionHandler.class);
|
||||
|
||||
@Override
|
||||
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(String.format("Unexpected error occurred invoking async " +
|
||||
"method '%s'.", method), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Provides miscellaneous interceptor implementations.
|
||||
* More specific interceptors can be found in corresponding
|
||||
* functionality packages, like "transaction" and "orm".
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Core Spring AOP interfaces, built on AOP Alliance AOP interoperability interfaces.
|
||||
*
|
||||
* <p>Any AOP Alliance MethodInterceptor is usable in Spring.
|
||||
* <br>Any AOP Alliance MethodInterceptor is usable in Spring.
|
||||
*
|
||||
* <br>Spring AOP also offers:
|
||||
* <ul>
|
||||
* <li>Introduction support
|
||||
* <li>A Pointcut abstraction, supporting "static" pointcuts
|
||||
* (class and method-based) and "dynamic" pointcuts (also considering method arguments).
|
||||
* There are currently no AOP Alliance interfaces for pointcuts.
|
||||
* <li>A full range of advice types, including around, before, after returning and throws advice.
|
||||
* <li>Extensibility allowing arbitrary custom advice types to
|
||||
* be plugged in without modifying the core framework.
|
||||
* <li>Introduction support
|
||||
* <li>A Pointcut abstraction, supporting "static" pointcuts
|
||||
* (class and method-based) and "dynamic" pointcuts (also considering method arguments).
|
||||
* There are currently no AOP Alliance interfaces for pointcuts.
|
||||
* <li>A full range of advice types, including around, before, after returning and throws advice.
|
||||
* <li>Extensibility allowing arbitrary custom advice types to
|
||||
* be plugged in without modifying the core framework.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Spring AOP can be used programmatically or (preferably)
|
||||
* <br>
|
||||
* Spring AOP can be used programmatically or (preferably)
|
||||
* integrated with the Spring IoC container.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,13 +97,4 @@ public abstract class ScopedProxyUtils {
|
||||
return TARGET_NAME_PREFIX + originalBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if the {@code beanName} is the name of a bean that references the target
|
||||
* bean within a scoped proxy.
|
||||
* @since 4.1.4
|
||||
*/
|
||||
public static boolean isScopedTarget(String beanName) {
|
||||
return (beanName != null && beanName.startsWith(TARGET_NAME_PREFIX));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Support for AOP-based scoping of target objects, with configurable backend.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.scope;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.aop.support;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -35,15 +34,13 @@ import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.TargetClassAware;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for AOP support code.
|
||||
*
|
||||
* <p>Mainly for internal use within Spring's AOP support.
|
||||
* Mainly for internal use within Spring's AOP support.
|
||||
*
|
||||
* <p>See {@link org.springframework.aop.framework.AopProxyUtils} for a
|
||||
* collection of framework-specific AOP utility methods which depend
|
||||
@@ -58,8 +55,6 @@ public abstract class AopUtils {
|
||||
|
||||
/**
|
||||
* Check whether the given object is a JDK dynamic proxy or a CGLIB proxy.
|
||||
* <p>This method additionally checks if the given object is an instance
|
||||
* of {@link SpringProxy}.
|
||||
* @param object the object to check
|
||||
* @see #isJdkDynamicProxy
|
||||
* @see #isCglibProxy
|
||||
@@ -71,9 +66,6 @@ public abstract class AopUtils {
|
||||
|
||||
/**
|
||||
* Check whether the given object is a JDK dynamic proxy.
|
||||
* <p>This method goes beyond the implementation of
|
||||
* {@link Proxy#isProxyClass(Class)} by additionally checking if the
|
||||
* given object is an instance of {@link SpringProxy}.
|
||||
* @param object the object to check
|
||||
* @see java.lang.reflect.Proxy#isProxyClass
|
||||
*/
|
||||
@@ -82,10 +74,9 @@ public abstract class AopUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given object is a CGLIB proxy.
|
||||
* <p>This method goes beyond the implementation of
|
||||
* {@link ClassUtils#isCglibProxy(Object)} by additionally checking if
|
||||
* the given object is an instance of {@link SpringProxy}.
|
||||
* Check whether the given object is a CGLIB proxy. Goes beyond the implementation
|
||||
* in {@link ClassUtils#isCglibProxy(Object)} by checking also to see if the given
|
||||
* object is an instance of {@link SpringProxy}.
|
||||
* @param object the object to check
|
||||
* @see ClassUtils#isCglibProxy(Object)
|
||||
*/
|
||||
@@ -93,9 +84,29 @@ public abstract class AopUtils {
|
||||
return (object instanceof SpringProxy && ClassUtils.isCglibProxy(object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the specified class is a CGLIB-generated class.
|
||||
* @param clazz the class to check
|
||||
* @deprecated as of Spring 3.1 in favor of {@link ClassUtils#isCglibProxyClass(Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isCglibProxyClass(Class<?> clazz) {
|
||||
return ClassUtils.isCglibProxyClass(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the specified class name is a CGLIB-generated class.
|
||||
* @param className the class name to check
|
||||
* @deprecated as of Spring 3.1 in favor of {@link ClassUtils#isCglibProxyClassName(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isCglibProxyClassName(String className) {
|
||||
return ClassUtils.isCglibProxyClassName(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the target class of the given bean instance which might be an AOP proxy.
|
||||
* <p>Returns the target class for an AOP proxy or the plain class otherwise.
|
||||
* <p>Returns the target class for an AOP proxy and the plain class else.
|
||||
* @param candidate the instance to check (might be an AOP proxy)
|
||||
* @return the target class (or the plain class of the given object as fallback;
|
||||
* never {@code null})
|
||||
@@ -114,30 +125,6 @@ public abstract class AopUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an invocable method on the target type: either the given method itself
|
||||
* if actually exposed on the target type, or otherwise a corresponding method
|
||||
* on one of the target type's interfaces or on the target type itself.
|
||||
* @param method the method to check
|
||||
* @param targetType the target type to search methods on (typically an AOP proxy)
|
||||
* @return a corresponding invocable method on the target type
|
||||
* @throws IllegalStateException if the given method is not invocable on the given
|
||||
* target type (typically due to a proxy mismatch)
|
||||
* @since 4.3
|
||||
* @see MethodIntrospector#selectInvocableMethod(Method, Class)
|
||||
*/
|
||||
public static Method selectInvocableMethod(Method method, Class<?> targetType) {
|
||||
Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType);
|
||||
if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) &&
|
||||
SpringProxy.class.isAssignableFrom(targetType)) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Need to invoke method '%s' found on proxy for target class '%s' but cannot " +
|
||||
"be delegated to target bean. Switch its visibility to package or protected.",
|
||||
method.getName(), method.getDeclaringClass().getSimpleName()));
|
||||
}
|
||||
return methodToUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method is an "equals" method.
|
||||
* @see java.lang.Object#equals
|
||||
@@ -193,6 +180,7 @@ public abstract class AopUtils {
|
||||
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Can the given pointcut apply at all on the given class?
|
||||
* <p>This is an important test as it can be used to optimize
|
||||
@@ -310,6 +298,7 @@ public abstract class AopUtils {
|
||||
return eligibleAdvisors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoke the given target via reflection, as part of an AOP method invocation.
|
||||
* @param target the target object
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,17 +91,17 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
this.evaluations++;
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
++this.evaluations;
|
||||
ControlFlow cflow = ControlFlowFactory.createControlFlow();
|
||||
return (this.methodName != null ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz));
|
||||
return (this.methodName != null) ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* It's useful to know how many times we've fired, for optimization.
|
||||
*/
|
||||
public int getEvaluations() {
|
||||
return this.evaluations;
|
||||
return evaluations;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,6 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -138,7 +138,7 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// Because a dynamic intersection may be composed of a static and dynamic part,
|
||||
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
|
||||
// it will probably be an unsupported operation.
|
||||
|
||||
+1
-1
@@ -18,9 +18,9 @@ package org.springframework.aop.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,7 +71,7 @@ public abstract class Pointcuts {
|
||||
* @param args arguments to the method
|
||||
* @return whether there's a runtime match
|
||||
*/
|
||||
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args) {
|
||||
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object[] args) {
|
||||
Assert.notNull(pointcut, "Pointcut must not be null");
|
||||
if (pointcut == Pointcut.TRUE) {
|
||||
return true;
|
||||
@@ -98,9 +98,9 @@ public abstract class Pointcuts {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return (method.getName().startsWith("set") &&
|
||||
method.getParameterTypes().length == 1 &&
|
||||
method.getReturnType() == Void.TYPE);
|
||||
return method.getName().startsWith("set") &&
|
||||
method.getParameterTypes().length == 1 &&
|
||||
method.getReturnType() == Void.TYPE;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
@@ -119,8 +119,8 @@ public abstract class Pointcuts {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return (method.getName().startsWith("get") &&
|
||||
method.getParameterTypes().length == 0);
|
||||
return method.getName().startsWith("get") &&
|
||||
method.getParameterTypes().length == 0;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,7 +32,7 @@ public abstract class StaticMethodMatcher implements MethodMatcher {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public final boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// should never be invoked because isRuntime() returns false
|
||||
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Annotation support for AOP pointcuts.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.support.annotation;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user