mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc73f6bb2c | |||
| 119364f326 | |||
| 434735fbf6 | |||
| 8f4221deb3 | |||
| 2d646ca79e | |||
| 1245919331 | |||
| bcbd338fe2 | |||
| 945463b826 | |||
| 3ba3dd61d1 | |||
| cd523c7051 | |||
| 20ddd3254b | |||
| e30b842316 | |||
| b0675c031e | |||
| 0f71da5be6 | |||
| 9035a97e18 | |||
| d32a77a5f0 | |||
| d8e3ef7640 | |||
| ccb02a2355 | |||
| d0948f1f03 | |||
| ae0f23e942 | |||
| b40263e06b | |||
| 2f8dfb3e52 | |||
| d5c78c953d | |||
| dfac1d0510 | |||
| 14b83c3fcc | |||
| ae6e84bc7d | |||
| 4213a31a7d | |||
| 22454c8edf | |||
| 98da5a7b2b | |||
| 0a37552beb | |||
| 1b702fa6a2 | |||
| a2e438b2be | |||
| 9ff9d45283 | |||
| 1fee4c0c0b | |||
| dc87a2211c | |||
| 77b7344530 | |||
| 7cde4f1503 | |||
| 6c11fd3b5e | |||
| eec4a37d1c | |||
| 1e3dc4aeae | |||
| d4b54d834e | |||
| 3562cd759b | |||
| c1dc4e2c75 | |||
| 8feeec4a60 | |||
| 440a63a3d0 | |||
| 274ed1fe67 | |||
| 1b47f6c0b0 | |||
| 66e4c9b2bb | |||
| e608055021 | |||
| 199be0ad3c | |||
| af7753eac6 | |||
| cce74b8ba2 | |||
| dd7508d606 | |||
| 3bf56dda56 | |||
| a72209aad3 | |||
| 67f41b15eb | |||
| 3515acfa3d | |||
| 7fdd0c22b2 | |||
| a0f8a894f2 | |||
| 55f02db18e | |||
| 71e88cbf30 | |||
| 514a2e9568 | |||
| abfb439bfe | |||
| 4ba43b4737 | |||
| 2655657a51 | |||
| 404671416a | |||
| 260eafc819 | |||
| ef8b5763e6 | |||
| 6b89af824d | |||
| 86b4b2ef23 | |||
| faa8430fd7 | |||
| 76f870caca | |||
| 615315728b | |||
| 115442242f | |||
| 10c0e8af01 | |||
| b6e20a4cc9 | |||
| a8adec7673 | |||
| 2ae61c503e | |||
| c2b2f30669 | |||
| 239a7cd85f | |||
| 6e4317ebfb | |||
| 325d8834e3 | |||
| 0c76cb7e80 | |||
| 940011e233 | |||
| 92bbd8103b | |||
| 9c194699c7 | |||
| 25701ef984 | |||
| 87ef99df5e | |||
| 13ca2752ae | |||
| ef363b0f7a | |||
| f9db59e730 | |||
| 0dcca2304f | |||
| ad272a0c87 | |||
| be224e1f30 | |||
| 4bb0916202 | |||
| d3eda09c01 | |||
| 399f887128 | |||
| 4d005b6987 | |||
| 532a7a3a02 | |||
| b2d416fd5f | |||
| 7298c3d669 | |||
| 7bbd38b9e0 | |||
| 64d83a550e | |||
| 0df1630ab9 | |||
| 7cbc115da6 | |||
| b962239e11 | |||
| 872cf6b076 | |||
| b2bd319d47 | |||
| e3fa49063e | |||
| c302efdbbf | |||
| 12699696f4 | |||
| c4f2566070 | |||
| 6458643f15 | |||
| 2145545e69 | |||
| f6545cde38 | |||
| 601c64a65c | |||
| 964f1a6213 | |||
| 886cc2cce8 | |||
| 5bdd2d245c | |||
| d0513f7521 | |||
| 265c0c1505 | |||
| 886cf825cb | |||
| 03033f6c06 | |||
| 5ff2dfbe13 | |||
| fa44ab6336 | |||
| eed1a58b81 |
@@ -15,13 +15,10 @@ spring-test/test-output/
|
||||
.gradle
|
||||
argfile*
|
||||
pom.xml
|
||||
activemq-data/
|
||||
|
||||
classes/
|
||||
/build
|
||||
buildSrc/build
|
||||
/spring-*/build
|
||||
/src/asciidoc/build
|
||||
target/
|
||||
|
||||
# Eclipse artifacts, including WTP generated manifests
|
||||
@@ -33,8 +30,6 @@ spring-*/src/main/java/META-INF/MANIFEST.MF
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea
|
||||
out
|
||||
test-output
|
||||
atlassian-ide-plugin.xml
|
||||
.gradletasknamecache
|
||||
|
||||
@@ -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/]
|
||||
@@ -1,51 +0,0 @@
|
||||
= How to contribute to the reference
|
||||
|
||||
The Spring Framework reference now uses http://asciidoctor.org/[asciidoctor]. This
|
||||
document describes how to contribute documentation updates.
|
||||
|
||||
== Building with Gradle
|
||||
|
||||
You can build the documentation using gradle using the `reference` task. For example, from
|
||||
the project root execute the following command:
|
||||
|
||||
./gradlew reference
|
||||
|
||||
the output will be available at `spring-framework/build/reference/htmlsingle/index.html`
|
||||
|
||||
== Live editing
|
||||
|
||||
One of the nice features about using asciidoctor is the support for live editing.
|
||||
|
||||
You will find a Guardfile already present at `spring-framework/src/asciidoc/Guardfile`.
|
||||
Make sure first to follow the setup instructions within the
|
||||
http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/[Editing AsciiDoc with Live Preview]
|
||||
document. Once you have done that, there are additional gems to install to make it work
|
||||
(assuming that you are using http://livereload.com/[LiveReload]):
|
||||
|
||||
gem install guard-rspec guard-livereload
|
||||
|
||||
When running `guard start` within the `src/asciidoc/` folder, any changes to the
|
||||
`src/asciidoc/index.adoc` file will automatically be written at
|
||||
`src/asciidoc/build/index.html`.
|
||||
|
||||
== Troubleshooting
|
||||
|
||||
* If you are using LiveReload, make sure to select _Allow access to file URLs_ in the
|
||||
LiveEdit plugin options of your browser.
|
||||
* The icon used to enable _LiveReload_ can be a bit confusing. The dot is empty when it is
|
||||
disabled and full when the plugin is active. Make sure to enable it on the tab
|
||||
displaying the `index.html` file.
|
||||
* Ensure you are _not_ running guard start at all as two instances could not run at the
|
||||
same time. To exit a current session in a clean way, just type e in the shell.
|
||||
|
||||
== Documentation notes
|
||||
|
||||
Some notes on documentation
|
||||
|
||||
* Documentation is wrapped at 90 chars, ensure that you manually wrap your edits
|
||||
* Tabs are used for indentation, do not use spaces
|
||||
* Follow the existing style when inserting `source` blocks
|
||||
* http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[Asciidoctor Quick Reference]
|
||||
* http://asciidoctor.org/docs/user-manual/[Asciidoctor Manual]
|
||||
* http://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoctor Writers Guide]
|
||||
|
||||
+101
-102
@@ -1,67 +1,72 @@
|
||||
_Have something you'd like to contribute to the framework? We welcome pull
|
||||
requests but ask that you carefully read this document first to understand how
|
||||
requests, but ask that you carefully read this document first to understand how
|
||||
best to submit them; what kind of changes are likely to be accepted; and what
|
||||
to expect from the Spring team when evaluating your submission._
|
||||
|
||||
_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.
|
||||
## Understand the basics
|
||||
|
||||
## Take Your First Steps
|
||||
|
||||
### Understand the basics
|
||||
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
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 first; create an issue if necessary
|
||||
|
||||
### Search JIRA; 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 not,
|
||||
please create a new issue before submitting a pull request unless the change is
|
||||
truly trivial, e.g. typo fixes, removing compiler warnings, etc.
|
||||
|
||||
Is there already an issue that addresses your concern? Do a bit of searching
|
||||
in our [JIRA issue tracker][] to see if you can find something similar. If you
|
||||
do not find something similar, please create a new JIRA issue before submitting
|
||||
a pull request unless the change is truly trivial -- for example: typo fixes,
|
||||
removing compiler warnings, etc.
|
||||
## Discuss non-trivial contribution ideas with committers
|
||||
|
||||
### Sign the Contributor License Agreement (CLA)
|
||||
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.
|
||||
|
||||
If you have not previously done so, please sign the [Contributor License Agreement][].
|
||||
If you forget to do so, you'll be reminded when you submit a pull request.
|
||||
## Sign the Contributor License Agreement
|
||||
|
||||
## Create a Branch
|
||||
If you have not previously done so, please fill out and submit the
|
||||
[SpringSource CLA form][]. You'll receive a token when this process is complete.
|
||||
Keep track of this; you may be asked for it later!
|
||||
|
||||
### Branch from `master`
|
||||
Note that emailing/postal mailing a signed copy is _not_ necessary. Submission
|
||||
of the web form is all that is required.
|
||||
|
||||
Master currently represents work toward Spring Framework 5.0. Please submit
|
||||
all pull requests there, even bug fixes and minor improvements. Backports to
|
||||
`4.3.x` will be considered on a case-by-case basis.
|
||||
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 SpringSource Individual
|
||||
Contributor License Agreement.
|
||||
|
||||
You do not need to include your token/id. Please add the statement above to all
|
||||
future pull requests as well, simply so that the Spring Framework team knows
|
||||
immediately that this process is complete.
|
||||
|
||||
|
||||
### Use short branch names
|
||||
## Create your branch from `3.2.x`
|
||||
|
||||
If your pull request addresses a bug or improvement, please create your branch
|
||||
from Spring Framework's `3.2.x` branch. `master` is reserved for work on new features
|
||||
for the next major version of the framework. Rest assured that if your pull
|
||||
request is accepted and merged into `3.2.x`, these changes will also eventually
|
||||
be merged into `master`.
|
||||
|
||||
|
||||
## Use short branch names
|
||||
|
||||
Branches used when submitting pull requests should preferably be named
|
||||
according to JIRA issues, e.g. 'SPR-1234'. Otherwise, use succinct, lower-case,
|
||||
dash (-) delimited names, such as 'fix-warnings', 'fix-typo', etc. In
|
||||
[fork-and-edit][] cases, the GitHub default 'patch-1' is fine as well. This is
|
||||
important, because branch names show up in the merge commits that result from
|
||||
accepting pull requests and should be as expressive and concise as possible.
|
||||
accepting pull requests, and should be as expressive and concise as possible.
|
||||
|
||||
## Use Spring Framework Code Style
|
||||
|
||||
The complete [Spring Framework Code Style][] reference is available on the wiki, but
|
||||
here's a quick summary:
|
||||
|
||||
### Mind the whitespace
|
||||
## Mind the whitespace
|
||||
|
||||
Please carefully follow the whitespace and formatting conventions already
|
||||
present in the framework.
|
||||
@@ -73,15 +78,16 @@ present in the framework.
|
||||
1. Aim to wrap code at 90 characters, but favor readability over wrapping
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. UTF-8 encoding for Java sources
|
||||
naming conventions, etc.
|
||||
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
|
||||
if necessary
|
||||
|
||||
|
||||
### Add Apache license header to all new classes
|
||||
## Add Apache license header to all new classes
|
||||
|
||||
```java
|
||||
/*
|
||||
* 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.
|
||||
@@ -99,44 +105,40 @@ present in the framework.
|
||||
package ...;
|
||||
```
|
||||
|
||||
### Update Apache license header in modified files as necessary
|
||||
## Update Apache license header to 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 2013 whose header still reads
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2016 accordingly:
|
||||
then be sure to update it to 2013 appropriately
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
## Use @since tags for newly-added public API types and methods
|
||||
|
||||
For example:
|
||||
e.g.
|
||||
|
||||
```java
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @author First Last
|
||||
* @since 4.2.3
|
||||
* @since 3.2
|
||||
* @see ...
|
||||
*/
|
||||
```
|
||||
|
||||
## Prepare Your Commit
|
||||
## Submit JUnit test cases for all behavior changes
|
||||
|
||||
### Submit JUnit test cases for all behavior changes
|
||||
|
||||
Search the codebase to find related tests and add additional `@Test` methods
|
||||
as appropriate. It is also acceptable to submit test cases on a per JIRA issue
|
||||
basis, for example:
|
||||
Search the codebase to find related unit tests and add additional @Test methods
|
||||
within. It is also acceptable to submit test cases on a per JIRA issue basis,
|
||||
e.g.
|
||||
|
||||
```java
|
||||
package org.springframework.beans.factory.support;
|
||||
@@ -161,15 +163,15 @@ public class Spr8954Tests {
|
||||
```
|
||||
|
||||
|
||||
### Squash commits
|
||||
## Squash commits
|
||||
|
||||
Use `git rebase --interactive --autosquash`, `git add --patch`, and other tools
|
||||
to "squash" multiple commits into a single atomic commit. In addition to the man
|
||||
pages for git, there are many resources online to help you understand how these
|
||||
tools work. The [Rewriting History section of Pro Git][] provides a good overview.
|
||||
Use `git rebase --interactive`, `git add --patch` and other tools to "squash"
|
||||
multiple commits into atomic changes. In addition to the man pages for git,
|
||||
there are many resources online to help you understand how these tools work.
|
||||
Here is one: http://book.git-scm.com/4_interactive_rebasing.html.
|
||||
|
||||
|
||||
### Use real name in git commits
|
||||
## Use real name in git commits
|
||||
|
||||
Please configure git to use your real first and last name for any commits you
|
||||
intend to submit as pull requests. For example, this is not acceptable:
|
||||
@@ -177,30 +179,30 @@ 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
|
||||
fork-and-edit cases); _globally_ on your machine with
|
||||
You can configure this globally via the account admin area GitHub (useful for
|
||||
fork-and-edit cases); globally with
|
||||
|
||||
git config --global user.name "First Last"
|
||||
git config --global user.email user@mail.com
|
||||
|
||||
or _locally_ for the `spring-framework` repository only by omitting the
|
||||
'--global' flag:
|
||||
or locally for the spring-framework repository only by omitting the '--global'
|
||||
flag:
|
||||
|
||||
cd spring-framework
|
||||
git config user.name "First Last"
|
||||
git config user.email user@mail.com
|
||||
|
||||
|
||||
### Format commit messages
|
||||
## Format commit messages
|
||||
|
||||
Please read and follow the [Commit Guidelines section of Pro Git][].
|
||||
Please read and follow the [commit guidelines section of Pro Git][].
|
||||
|
||||
Most importantly, please format your commit messages in the following way
|
||||
(adapted from the commit template in the link above):
|
||||
@@ -224,34 +226,32 @@ 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. 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. Use imperative statements in the subject line, e.g. "Fix broken Javadoc link"
|
||||
1. Begin the subject line sentence with a capitalized verb, e.g. "Add, Prune,
|
||||
Fix, Introduce, Avoid, etc."
|
||||
1. Do not end the subject line with a period
|
||||
1. Keep 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:
|
||||
spring-framework git repository. For convenience, here are several such commits:
|
||||
|
||||
- https://github.com/spring-projects/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
|
||||
- https://github.com/spring-projects/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
|
||||
- https://github.com/spring-projects/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
|
||||
- https://github.com/spring-projects/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
|
||||
https://github.com/SpringSource/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
|
||||
https://github.com/SpringSource/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
|
||||
https://github.com/SpringSource/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
|
||||
https://github.com/SpringSource/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
|
||||
|
||||
## Run the Final Checklist
|
||||
## Run all tests prior to submission
|
||||
|
||||
### Run all tests prior to submission
|
||||
|
||||
See the [building from source][] section of the `README` for instructions. Make
|
||||
See the [building from source][] section of the README for instructions. Make
|
||||
sure that all tests pass prior to submitting your pull request.
|
||||
|
||||
|
||||
### Submit your pull request
|
||||
## Submit your pull request
|
||||
|
||||
Subject line:
|
||||
|
||||
@@ -263,10 +263,10 @@ In the body:
|
||||
1. Explain your use case. What led you to submit this change? Why were existing
|
||||
mechanisms in the framework insufficient? Make a case that this is a
|
||||
general-purpose problem and that yours is a general-purpose solution, etc.
|
||||
1. Add any additional information and ask questions; start a conversation or
|
||||
continue one from JIRA.
|
||||
1. Mention the JIRA issue ID.
|
||||
1. Also mention that you have submitted the ICLA as described above.
|
||||
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 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
|
||||
@@ -274,12 +274,12 @@ the commit message. This is fine, but please also include the items above in the
|
||||
body of the request.
|
||||
|
||||
|
||||
### Mention your pull request on the associated JIRA issue
|
||||
## Mention your pull request on the associated JIRA issue
|
||||
|
||||
Add a comment to the associated JIRA issue(s) linking to your new pull request.
|
||||
|
||||
|
||||
### Expect discussion and rework
|
||||
## Expect discussion and rework
|
||||
|
||||
The Spring team takes a very conservative approach to accepting contributions to
|
||||
the framework. This is to keep code quality and stability as high as possible,
|
||||
@@ -291,14 +291,13 @@ strongly recommend discussing any serious submissions with the Spring Framework
|
||||
team _prior_ to engaging in serious development work.
|
||||
|
||||
Note that you can always force push (`git push -f`) reworked / rebased commits
|
||||
against the branch used to submit your pull request. In other words, you do not
|
||||
need to issue a new pull request when asked to make changes.
|
||||
against the branch used to submit your pull request. i.e. you do not need to
|
||||
issue a new pull request when asked to make changes.
|
||||
|
||||
[help documentation]: https://help.github.com/categories/collaborating-on-projects-using-issues-and-pull-requests/
|
||||
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
|
||||
[Contributor License Agreement]: https://cla.pivotal.io/sign/spring
|
||||
[help documentation]: http://help.github.com/send-pull-requests
|
||||
[JIRA issue tracker]: https://jira.springsource.org/browse/SPR
|
||||
[spring-framework-contrib]: https://groups.google.com/forum/#!forum/spring-framework-contrib
|
||||
[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
|
||||
[Commit Guidelines section of Pro Git]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines
|
||||
[building from source]: https://github.com/spring-projects/spring-framework#building-from-source
|
||||
[commit guidelines section of Pro Git]: http://progit.org/book/ch5-2.html#commit_guidelines
|
||||
[building from source]: https://github.com/SpringSource/spring-framework#building-from-source
|
||||
|
||||
@@ -1,62 +1,54 @@
|
||||
## 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.
|
||||
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 [SpringSource 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.
|
||||
[.NET][] and [Python][] variants are available as well.
|
||||
|
||||
## Downloading Artifacts
|
||||
## 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][]
|
||||
## Getting 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
|
||||
simple step-by-step instructions.
|
||||
|
||||
## Building from Source
|
||||
## Building from source
|
||||
The Spring Framework uses a [Gradle][]-based build system. In the instructions
|
||||
below, [`./gradlew`][] is invoked from the root of the source tree and serves as
|
||||
a cross-platform, self-contained bootstrap mechanism for the build.
|
||||
a cross-platform, self-contained bootstrap mechanism for the build. The only
|
||||
prerequisites are [Git][] and JDK 1.7+.
|
||||
|
||||
### Prerequisites
|
||||
### check out sources
|
||||
`git clone git://github.com/SpringSource/spring-framework.git`
|
||||
|
||||
[Git][] and [JDK 8 update 20 or later][JDK8 build]
|
||||
### compile and test, build all jars, distribution zips and docs
|
||||
`./gradlew build`
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder
|
||||
extracted from the JDK download.
|
||||
|
||||
### Check out sources
|
||||
`git clone git@github.com:spring-projects/spring-framework.git`
|
||||
|
||||
### Import sources into your IDE
|
||||
Run `./import-into-eclipse.sh` or read `import-into-idea.md` as appropriate.
|
||||
> **Note:** Per the prerequisites above, ensure that you have JDK 8 configured properly in your IDE.
|
||||
|
||||
### Install all spring-\* jars into your local Maven cache
|
||||
### install all spring-\* jars into your local Maven cache
|
||||
`./gradlew install`
|
||||
|
||||
### Compile and test; build all jars, distribution zips, and docs
|
||||
`./gradlew build`
|
||||
### import sources into your IDE
|
||||
Run `./import-into-eclipse.sh` or read `import-into-idea.md` as appropriate.
|
||||
|
||||
... and discover more commands with `./gradlew tasks`. See also the [Gradle
|
||||
build and release FAQ][].
|
||||
@@ -64,39 +56,41 @@ build and release FAQ][].
|
||||
## Contributing
|
||||
[Pull requests][] are welcome; see the [contributor guidelines][] for details.
|
||||
|
||||
## Staying in Touch
|
||||
Follow [@SpringCentral][] as well as [@SpringFramework][] and its [team members][]
|
||||
on Twitter. In-depth articles can be found at [The Spring Blog][], and releases
|
||||
are announced via our [news feed][].
|
||||
## Staying in touch
|
||||
Follow [@springframework][] and its [team members][] on Twitter. In-depth
|
||||
articles can be found at the SpringSource [team blog][], and releases are
|
||||
announced via our [news feed][].
|
||||
|
||||
## License
|
||||
The Spring Framework is released under version 2.0 of the [Apache License][].
|
||||
|
||||
[Spring Integration]: https://github.com/spring-projects/spring-integration
|
||||
[Spring Batch]: https://github.com/spring-projects/spring-batch
|
||||
[family of projects]: http://spring.io/projects
|
||||
[Spring organization]: https://github.com/spring-projects
|
||||
[downloading Spring artifacts]: https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts
|
||||
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
|
||||
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
|
||||
[spring tags]: http://spring.io/questions
|
||||
[Spring Integration]: https://github.com/SpringSource/spring-integration
|
||||
[Spring Batch]: https://github.com/SpringSource/spring-batch
|
||||
[family of projects]: http://springsource.org/projects
|
||||
[SpringSource organization]: https://github.com/SpringSource
|
||||
[.NET]: https://github.com/SpringSource/spring-net
|
||||
[Python]: https://github.com/SpringSource/spring-python
|
||||
[downloading Spring artifacts]: https://github.com/SpringSource/spring-framework/wiki/Downloading-Spring-artifacts
|
||||
[building a distribution with dependencies]: https://github.com/SpringSource/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://static.springsource.org/spring-framework/docs/current/javadoc-api
|
||||
[reference docs]: http://static.springsource.org/spring-framework/docs/current/spring-framework-reference
|
||||
[Spring forums]: http://forum.springsource.org
|
||||
[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
|
||||
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[Commercial support]: http://springsource.com/support/springsupport
|
||||
[Spring Framework JIRA]: http://jira.springsource.org/browse/SPR
|
||||
[the lifecycle of an issue]: https://github.com/cbeams/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/SpringSource/spring-framework-issues#readme
|
||||
[readme]: https://github.com/SpringSource/spring-framework-issues#readme
|
||||
[Gradle]: http://gradle.org
|
||||
[`./gradlew`]: http://vimeo.com/34436402
|
||||
[Git]: http://help.github.com/set-up-git-redirect
|
||||
[JDK8 build]: http://www.oracle.com/technetwork/java/javase/downloads
|
||||
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Pull requests]: https://help.github.com/categories/collaborating-on-projects-using-issues-and-pull-requests/
|
||||
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@SpringFramework]: https://twitter.com/springframework
|
||||
[@SpringCentral]: https://twitter.com/springcentral
|
||||
[team members]: https://twitter.com/springframework/lists/team/members
|
||||
[The Spring Blog]: http://spring.io/blog/
|
||||
[news feed]: http://spring.io/blog/category/news
|
||||
[Gradle build and release FAQ]: https://github.com/SpringSource/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Pull requests]: http://help.github.com/send-pull-requests
|
||||
[contributor guidelines]: https://github.com/SpringSource/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@springframework]: http://twitter.com/springframework
|
||||
[team members]: http://twitter.com/springframework/team/members
|
||||
[team blog]: http://blog.springsource.org
|
||||
[news feed]: http://www.springsource.org/news-events
|
||||
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
+465
-888
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.
|
||||
@@ -21,17 +21,20 @@ import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
|
||||
import org.gradle.api.plugins.MavenPlugin
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
|
||||
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
import org.gradle.api.invocation.*
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that allows projects to merged together. Primarily developed to
|
||||
* allow Spring to support multiple incompatible versions of third-party
|
||||
* allow Spring to support multiple multiple incompatible versions of third-party
|
||||
* dependencies (for example Hibernate v3 and v4).
|
||||
* <p>
|
||||
* The 'merge' extension should be used to define how projects are merged, for example:
|
||||
* <pre class="code">
|
||||
* <pre>
|
||||
* configure(subprojects) {
|
||||
* apply plugin: MergePlugin
|
||||
* }
|
||||
@@ -64,24 +67,22 @@ class MergePlugin implements Plugin<Project> {
|
||||
project.plugins.apply(IdeaPlugin)
|
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel)
|
||||
model.project = project
|
||||
project.configurations.create("merging")
|
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
|
||||
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
|
||||
project.eclipse.classpath.plusConfigurations += [runtimeMerge]
|
||||
project.idea.module.scopes.PROVIDED.plus += runtimeMerge
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
if (it.merge.into != null) {
|
||||
if(it.merge.into != null) {
|
||||
setup(it)
|
||||
}
|
||||
setupIdeDependencies(it)
|
||||
}
|
||||
|
||||
// Hook to build runtimeMerge dependencies
|
||||
if (!attachedProjectsEvaluated) {
|
||||
if(!attachedProjectsEvaluated) {
|
||||
project.gradle.projectsEvaluated{
|
||||
postProcessProjects(it)
|
||||
}
|
||||
@@ -101,7 +102,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
// invoking a task will invoke the task with the same name on 'into' project
|
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
|
||||
def task = project.tasks.findByPath(it)
|
||||
if (task) {
|
||||
if(task) {
|
||||
task.enabled = false
|
||||
task.dependsOn(project.merge.into.tasks.findByPath(it))
|
||||
}
|
||||
@@ -116,20 +117,10 @@ class MergePlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private void setupIdeDependencies(Project project) {
|
||||
project.configurations.each { c ->
|
||||
c.dependencies.findAll( { it instanceof org.gradle.api.artifacts.ProjectDependency } ).each { d ->
|
||||
d.dependencyProject.merge.from.each { from ->
|
||||
project.dependencies.add("runtimeMerge", from)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMaven(Project project) {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if (mapping.scope) {
|
||||
if(mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.create(
|
||||
project.name + "-" + configuration.name)
|
||||
configuration.excludeRules.each {
|
||||
@@ -140,13 +131,12 @@ class MergePlugin implements Plugin<Project> {
|
||||
configuration.dependencies.each {
|
||||
def intoCompile = project.merge.into.configurations.getByName("compile")
|
||||
// Protect against changing a compile scope dependency (SPR-10218)
|
||||
if (!intoCompile.dependencies.contains(it)) {
|
||||
if(!intoCompile.dependencies.contains(it)) {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100 + index, intoConfiguration, mapping.scope)
|
||||
mapping.priority + 100, intoConfiguration, mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,12 +156,5 @@ class MergePlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
class MergeModel {
|
||||
Project project;
|
||||
Project into;
|
||||
List<Project> from = [];
|
||||
|
||||
public void setInto(Project into) {
|
||||
this.into = into;
|
||||
into.merge.from.add(project);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -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.
|
||||
@@ -21,6 +21,7 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that automatically updates testCompile dependencies to include
|
||||
* the test source sets of project dependencies.
|
||||
@@ -40,10 +41,11 @@ class TestSourceSetDependenciesPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
|
||||
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
|
||||
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies,
|
||||
Project project) {
|
||||
for(def configurationName in ["compile", "optional", "provided", "testCompile"]) {
|
||||
Configuration configuration = project.getConfigurations().findByName(configurationName)
|
||||
if (configuration) {
|
||||
if(configuration) {
|
||||
configuration.dependencies.findAll { it instanceof ProjectDependency }.each {
|
||||
projectDependencies.add(it)
|
||||
collectProjectDependencies(projectDependencies, it.dependencyProject)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.0.0.M2
|
||||
version=3.2.4.RELEASE
|
||||
|
||||
+5
-20
@@ -5,19 +5,13 @@ import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||
apply plugin: "propdeps-eclipse"
|
||||
apply plugin: "propdeps-idea"
|
||||
|
||||
eclipse.jdt {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
}
|
||||
|
||||
// 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 }) {
|
||||
@@ -47,20 +41,10 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure project dependencies come after 3rd-party libs (SPR-11836)
|
||||
// https://jira.spring.io/browse/SPR-11836
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
classpath.entries.findAll { it instanceof ProjectDependency }.each {
|
||||
// delete from original position
|
||||
classpath.entries.remove(it)
|
||||
// append to end of classpath
|
||||
classpath.entries.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
// 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 +69,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 +81,7 @@ tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||
|
||||
|
||||
// Filter 'build' folder
|
||||
|
||||
eclipse.project.file.withXml {
|
||||
def node = it.asNode()
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ def customizePom(pom, gradleProject) {
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
description = gradleProject.description
|
||||
url = "https://github.com/spring-projects/spring-framework"
|
||||
url = "https://github.com/SpringSource/spring-framework"
|
||||
organization {
|
||||
name = "Spring IO"
|
||||
url = "http://projects.spring.io/spring-framework"
|
||||
name = "SpringSource"
|
||||
url = "http://springsource.org/spring-framework"
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
@@ -35,21 +35,17 @@ def customizePom(pom, gradleProject) {
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url = "https://github.com/spring-projects/spring-framework"
|
||||
connection = "scm:git:git://github.com/spring-projects/spring-framework"
|
||||
developerConnection = "scm:git:git://github.com/spring-projects/spring-framework"
|
||||
url = "https://github.com/SpringSource/spring-framework"
|
||||
connection = "scm:git:git://github.com/SpringSource/spring-framework"
|
||||
developerConnection = "scm:git:git://github.com/SpringSource/spring-framework"
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = "jhoeller"
|
||||
name = "Juergen Hoeller"
|
||||
email = "jhoeller@pivotal.io"
|
||||
email = "jhoeller@vmware.com"
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
system = "Jira"
|
||||
url = "https://jira.springsource.org/browse/SPR"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+4
-4
@@ -1,6 +1,6 @@
|
||||
#Mon Aug 15 21:03:22 CEST 2016
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
#Tue Jul 30 09:29:28 PDT 2013
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.0-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -6,31 +6,13 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
GRADLE_OPTS="-XX:MaxPermSize=1024m -Xmx1024m $GRADLE_OPTS"
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
GRADLE_OPTS="-XX:MaxMetaspaceSize=1024m -Xmx1024m $GRADLE_OPTS"
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
@@ -49,7 +31,6 @@ die ( ) {
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
@@ -60,11 +41,31 @@ case "`uname`" in
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
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"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -90,7 +91,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
@@ -114,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`
|
||||
@@ -162,9 +162,4 @@ function splitJvmOpts() {
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
|
||||
Vendored
+11
-5
@@ -8,15 +8,15 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set GRADLE_OPTS=-XX:MaxPermSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set GRADLE_OPTS=-XX:MaxMetaspaceSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
@@ -47,9 +47,10 @@ 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
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@@ -60,6 +61,11 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
@@ -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 http://springsource.org/downloads/sts
|
||||
echo.
|
||||
echo Otherwise, press enter and we'll begin.
|
||||
|
||||
@@ -29,8 +29,8 @@ REM - generates OXM test classes to avoid errors on import into Eclipse
|
||||
REM - generates metadata for all subprojects
|
||||
REM - skips metadata gen for the root project (-x :eclipse) to work
|
||||
REM around Eclipse's inability to import hierarchical project structures
|
||||
REM SET COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
SET COMMAND=gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
|
||||
REM SET COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
SET COMMAND=gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
@@ -69,7 +69,7 @@ echo When the above is complete, return here and press the enter key.
|
||||
|
||||
pause
|
||||
|
||||
set COMMAND=gradlew --no-daemon :eclipse
|
||||
set COMMAND=gradlew :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
|
||||
+38
-53
@@ -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 http://springsource.org/downloads/sts
|
||||
|
||||
- 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
|
||||
@@ -42,18 +27,18 @@ read
|
||||
# - generates metadata for all subprojects
|
||||
# - skips metadata gen for the root project (-x :eclipse) to work
|
||||
# around Eclipse's inability to import hierarchical project structures
|
||||
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
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,33 +53,33 @@ $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
|
||||
|
||||
read
|
||||
|
||||
COMMAND="./gradlew --no-daemon :eclipse"
|
||||
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.
|
||||
|
||||
|
||||
+13
-15
@@ -1,27 +1,25 @@
|
||||
The following has been tested against IntelliJ IDEA 2016.2.2
|
||||
The following has been tested against Intellij IDEA 12.0
|
||||
|
||||
## Steps
|
||||
|
||||
_Within your locally cloned spring-framework working directory:_
|
||||
|
||||
1. Precompile `spring-oxm` with `./gradlew cleanIdea :spring-oxm:compileTestJava`
|
||||
2. Import into IntelliJ (File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)
|
||||
3. When prompted exclude the `spring-aspects` module (or after the import via File-> Project Structure -> Modules)
|
||||
4. Code away
|
||||
1. 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-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
|
||||
See `*RepackJar` tasks in the build and https://youtrack.jetbrains.com/issue/IDEA-160605).
|
||||
2. `spring-aspects` does not compile due to references to aspect types unknown to
|
||||
IntelliJ IDEA. See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the
|
||||
'spring-aspects' can be excluded from the project to avoid compilation errors.
|
||||
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
|
||||
IntelliJ IDEA. Resolving this is a work in progress. If attempting to run all JUnit tests from within
|
||||
IntelliJ IDEA, you will likely need to set the following VM options to avoid out of memory errors:
|
||||
1. `spring-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'
|
||||
module has been excluded from the overall project to avoid compilation errors.
|
||||
2. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
|
||||
likely need to set the following VM options to avoid out of memory errors:
|
||||
-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
|
||||
|
||||
|
||||
## Tips
|
||||
|
||||
In any case, please do not check in your own generated .iml, .ipr, or .iws files.
|
||||
@@ -29,6 +27,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
|
||||
|
||||
## FAQ
|
||||
|
||||
Q. What about IntelliJ IDEA's own [Gradle support](http://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
|
||||
Q. What about IDEA's own [Gradle support](http://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
|
||||
|
||||
A. Keep an eye on http://youtrack.jetbrains.com/issue/IDEA-53476
|
||||
|
||||
+6
-6
@@ -3,25 +3,25 @@ rootProject.name = "spring"
|
||||
include "spring-aop"
|
||||
include "spring-aspects"
|
||||
include "spring-beans"
|
||||
include "spring-beans-groovy"
|
||||
include "spring-context"
|
||||
include "spring-context-support"
|
||||
include "spring-context-indexer"
|
||||
include "spring-core"
|
||||
include "spring-expression"
|
||||
include "spring-instrument"
|
||||
include "spring-instrument-tomcat"
|
||||
include "spring-jdbc"
|
||||
include "spring-jms"
|
||||
include "spring-messaging"
|
||||
include "spring-orm"
|
||||
include "spring-orm-hibernate4"
|
||||
include "spring-oxm"
|
||||
include "spring-struts"
|
||||
include "spring-test"
|
||||
include "spring-test-mvc"
|
||||
include "spring-tx"
|
||||
include "spring-web"
|
||||
include "spring-webmvc"
|
||||
include "spring-web-reactive"
|
||||
include "spring-websocket"
|
||||
include "spring-framework-bom"
|
||||
include "spring-webmvc-portlet"
|
||||
include "spring-webmvc-tiles3"
|
||||
|
||||
// Exposes gradle buildSrc for IDE support
|
||||
include "buildSrc"
|
||||
|
||||
@@ -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 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,57 +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
|
||||
*/
|
||||
@FunctionalInterface
|
||||
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-2016 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ package org.springframework.aop;
|
||||
* @see Pointcut
|
||||
* @see MethodMatcher
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClassFilter {
|
||||
|
||||
/**
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -19,9 +19,9 @@ package org.springframework.aop;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* A specialized type of {@link MethodMatcher} that takes into account introductions
|
||||
* when matching methods. If there are no introductions on the target class,
|
||||
* a method matcher may be able to optimize matching more effectively for example.
|
||||
* A specialized type of MethodMatcher that takes into account introductions when
|
||||
* matching methods. If there are no introductions on the target class, a method
|
||||
* matcher may be able to optimize matching more effectively for example.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
@@ -39,6 +39,6 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
|
||||
* asking is the subject on one or more introductions; {@code false} otherwise
|
||||
* @return whether or not this method matches statically
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
|
||||
boolean matches(Method method, Class targetClass, boolean hasIntroductions);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,6 @@ public interface IntroductionInfo {
|
||||
* Return the additional interfaces introduced by this Advisor or Advice.
|
||||
* @return the introduced interfaces
|
||||
*/
|
||||
Class<?>[] getInterfaces();
|
||||
Class[] getInterfaces();
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -39,7 +39,6 @@ public interface TargetSource extends TargetClassAware {
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
@Override
|
||||
Class<?> getTargetClass();
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,8 +34,7 @@ class TrueClassFilter implements ClassFilter, Serializable {
|
||||
private TrueClassFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
public boolean matches(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,36 +29,25 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueMethodMatcher() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@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 +57,9 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,12 +34,10 @@ class TruePointcut implements Pointcut, Serializable {
|
||||
private TruePointcut() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFilter getClassFilter() {
|
||||
return ClassFilter.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
return MethodMatcher.TRUE;
|
||||
}
|
||||
|
||||
+54
-73
@@ -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.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;
|
||||
@@ -40,8 +37,9 @@ import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
import org.springframework.aop.support.ComposablePointcut;
|
||||
import org.springframework.aop.support.MethodMatchers;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PrioritizedParameterNameDiscoverer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -58,8 +56,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 +87,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;
|
||||
|
||||
@@ -126,9 +120,9 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
/** Non-null if after returning advice binds the return value */
|
||||
private String returningName = null;
|
||||
|
||||
private Class<?> discoveredReturningType = Object.class;
|
||||
private Class discoveredReturningType = Object.class;
|
||||
|
||||
private Class<?> discoveredThrowingType = Object.class;
|
||||
private Class discoveredThrowingType = Object.class;
|
||||
|
||||
/**
|
||||
* Index for thisJoinPoint argument (currently only
|
||||
@@ -142,7 +136,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 +155,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;
|
||||
}
|
||||
@@ -211,7 +203,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return this.aspectInstanceFactory.getAspectClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.aspectInstanceFactory.getOrder();
|
||||
}
|
||||
@@ -221,7 +212,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.aspectName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
@@ -233,7 +223,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.declarationOrder = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeclarationOrder() {
|
||||
return this.declarationOrder;
|
||||
}
|
||||
@@ -249,7 +238,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
setArgumentNamesFromStringArray(tokens);
|
||||
}
|
||||
|
||||
public void setArgumentNamesFromStringArray(String... args) {
|
||||
public void setArgumentNamesFromStringArray(String[] args) {
|
||||
this.argumentNames = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
|
||||
@@ -259,17 +248,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.getParameterCount() == 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,7 +290,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getDiscoveredReturningType() {
|
||||
protected Class getDiscoveredReturningType() {
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
@@ -335,7 +324,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getDiscoveredThrowingType() {
|
||||
protected Class getDiscoveredThrowingType() {
|
||||
return this.discoveredThrowingType;
|
||||
}
|
||||
|
||||
@@ -368,12 +357,12 @@ 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;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
int numUnboundArgs = this.adviceInvocationArgumentCount;
|
||||
Class[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
@@ -389,8 +378,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.argumentsIntrospected = true;
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
|
||||
if (JoinPoint.class == candidateParameterType) {
|
||||
private boolean maybeBindJoinPoint(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.class)) {
|
||||
this.joinPointArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -399,8 +388,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
|
||||
private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
|
||||
if (ProceedingJoinPoint.class == candidateParameterType) {
|
||||
private boolean maybeBindProceedingJoinPoint(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(ProceedingJoinPoint.class)) {
|
||||
if (!supportsProceedingJoinPoint()) {
|
||||
throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
|
||||
}
|
||||
@@ -416,8 +405,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
|
||||
if (JoinPoint.StaticPart.class == candidateParameterType) {
|
||||
private boolean maybeBindJoinPointStaticPart(Class candidateParameterType) {
|
||||
if (candidateParameterType.equals(JoinPoint.StaticPart.class)) {
|
||||
this.joinPointStaticPartArgumentIndex = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -443,13 +432,15 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
/**
|
||||
* Create a ParameterNameDiscoverer to be used for argument binding.
|
||||
* <p>The default implementation creates a {@link DefaultParameterNameDiscoverer}
|
||||
* and adds a specifically configured {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
* <p>The default implementation creates a {@link PrioritizedParameterNameDiscoverer}
|
||||
* containing a {@link LocalVariableTableParameterNameDiscoverer} and an
|
||||
* {@link AspectJAdviceParameterNameDiscoverer}.
|
||||
*/
|
||||
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
|
||||
// We need to discover them, or if that fails, guess,
|
||||
// and if we can't guess with 100% accuracy, fail.
|
||||
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
|
||||
PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
|
||||
discoverer.addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
|
||||
AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
|
||||
new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
|
||||
adviceParameterNameDiscoverer.setReturningName(this.returningName);
|
||||
@@ -461,17 +452,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
private void bindExplicitArguments(int numArgumentsLeftToBind) {
|
||||
this.argumentBindings = new HashMap<>();
|
||||
this.argumentBindings = new HashMap<String, Integer>();
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
|
||||
" arguments to bind by name in advice, but actually found " +
|
||||
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);
|
||||
@@ -518,8 +509,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
numParametersToRemove++;
|
||||
}
|
||||
String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
|
||||
Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
|
||||
Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
Class[] pointcutParameterTypes = new Class[pointcutParameterNames.length];
|
||||
Class[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
|
||||
int index = 0;
|
||||
for (int i = 0; i < this.argumentNames.length; i++) {
|
||||
@@ -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;
|
||||
@@ -620,7 +612,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
|
||||
Object[] actualArgs = args;
|
||||
if (this.aspectJAdviceMethod.getParameterCount() == 0) {
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
|
||||
actualArgs = null;
|
||||
}
|
||||
try {
|
||||
@@ -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.
|
||||
@@ -696,8 +678,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.adviceMethod = adviceMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return !this.adviceMethod.equals(method);
|
||||
}
|
||||
|
||||
|
||||
+16
-16
@@ -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.
|
||||
@@ -21,6 +21,7 @@ import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -130,8 +131,8 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
private static final int STEP_REFERENCE_PCUT_BINDING = 7;
|
||||
private static final int STEP_FINISHED = 8;
|
||||
|
||||
private static final Set<String> singleValuedAnnotationPcds = new HashSet<>();
|
||||
private static final Set<String> nonReferencePointcutTokens = new HashSet<>();
|
||||
private static final Set<String> singleValuedAnnotationPcds = new HashSet<String>();
|
||||
private static final Set<String> nonReferencePointcutTokens = new HashSet<String>();
|
||||
|
||||
|
||||
static {
|
||||
@@ -141,8 +142,9 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
singleValuedAnnotationPcds.add("@withincode");
|
||||
singleValuedAnnotationPcds.add("@annotation");
|
||||
|
||||
Set<PointcutPrimitive> pointcutPrimitives = PointcutParser.getAllSupportedPointcutPrimitives();
|
||||
for (PointcutPrimitive primitive : pointcutPrimitives) {
|
||||
Set pointcutPrimitives = PointcutParser.getAllSupportedPointcutPrimitives();
|
||||
for (Iterator iterator = pointcutPrimitives.iterator(); iterator.hasNext();) {
|
||||
PointcutPrimitive primitive = (PointcutPrimitive) iterator.next();
|
||||
nonReferencePointcutTokens.add(primitive.getName());
|
||||
}
|
||||
nonReferencePointcutTokens.add("&&");
|
||||
@@ -171,7 +173,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
*/
|
||||
private String pointcutExpression;
|
||||
|
||||
private Class<?>[] argumentTypes;
|
||||
private Class[] argumentTypes;
|
||||
|
||||
private String[] parameterNameBindings;
|
||||
|
||||
@@ -220,7 +222,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* @param method the target {@link Method}
|
||||
* @return the parameter names
|
||||
*/
|
||||
@Override
|
||||
public String[] getParameterNames(Method method) {
|
||||
this.argumentTypes = method.getParameterTypes();
|
||||
this.numberOfRemainingUnboundArguments = this.argumentTypes.length;
|
||||
@@ -308,8 +309,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* @throws UnsupportedOperationException if
|
||||
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
|
||||
*/
|
||||
@Override
|
||||
public String[] getParameterNames(Constructor<?> ctor) {
|
||||
public String[] getParameterNames(Constructor ctor) {
|
||||
if (this.raiseExceptions) {
|
||||
throw new UnsupportedOperationException("An advice method can never be a constructor");
|
||||
}
|
||||
@@ -414,7 +414,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* <p>Some more support from AspectJ in doing this exercise would be nice... :)
|
||||
*/
|
||||
private void maybeBindAnnotationsFromPointcutExpression() {
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
@@ -520,7 +520,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
+ " unbound args at this(),target(),args() binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("this") ||
|
||||
@@ -537,7 +537,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
else if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
PointcutBody body = getPointcutBody(tokens, i);
|
||||
i += body.numTokensConsumed;
|
||||
List<String> candidateVarNames = new ArrayList<>();
|
||||
List<String> candidateVarNames = new ArrayList<String>();
|
||||
maybeExtractVariableNamesFromArgs(body.text, candidateVarNames);
|
||||
// we may have found some var names that were bound in previous primitive args binding step,
|
||||
// filter them out...
|
||||
@@ -571,7 +571,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
+ " unbound args at reference pointcut binding stage, with no way to determine between them");
|
||||
}
|
||||
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
@@ -683,7 +683,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
if (numUnboundPrimitives == 1) {
|
||||
// Look for arg variable and bind it if we find exactly one...
|
||||
List<String> varNames = new ArrayList<>();
|
||||
List<String> varNames = new ArrayList<String>();
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
if (tokens[i].equals("args") || tokens[i].startsWith("args(")) {
|
||||
@@ -729,7 +729,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* Return {@code true} if the given argument type is a subclass
|
||||
* of the given supertype.
|
||||
*/
|
||||
private boolean isSubtypeOf(Class<?> supertype, int argumentNumber) {
|
||||
private boolean isSubtypeOf(Class supertype, int argumentNumber) {
|
||||
return supertype.isAssignableFrom(this.argumentTypes[argumentNumber]);
|
||||
}
|
||||
|
||||
@@ -757,7 +757,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* Find the argument index with the given type, and bind the given
|
||||
* {@code varName} in that position.
|
||||
*/
|
||||
private void findAndBind(Class<?> argumentType, String varName) {
|
||||
private void findAndBind(Class argumentType, String varName) {
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && isSubtypeOf(argumentType, i)) {
|
||||
bindParameterName(i, varName);
|
||||
|
||||
@@ -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,8 +37,6 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
try {
|
||||
return mi.proceed();
|
||||
@@ -51,12 +46,10 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
+5
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2010 the original author 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,13 +40,10 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
@@ -59,14 +53,12 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
setReturningNameNoCheck(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
|
||||
if (shouldInvokeOnReturnValueOf(method, returnValue)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -76,34 +68,12 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
* @return whether to invoke the advice method for the given return value
|
||||
*/
|
||||
private boolean shouldInvokeOnReturnValueOf(Method method, Object returnValue) {
|
||||
Class<?> type = getDiscoveredReturningType();
|
||||
Class type = getDiscoveredReturningType();
|
||||
Type genericType = getDiscoveredReturningGenericType();
|
||||
// If we aren't dealing with a raw type, check if generic parameters are assignable.
|
||||
return (matchesReturnValue(type, method, returnValue) &&
|
||||
// If we aren't dealing with a raw type, check if generic parameters are assignable.
|
||||
return (ClassUtils.isAssignableValue(type, returnValue) &&
|
||||
(genericType == null || genericType == type ||
|
||||
TypeUtils.isAssignable(genericType, method.getGenericReturnType())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Following AspectJ semantics, if a return value is null (or return type is void),
|
||||
* then the return type of target method should be used to determine whether advice
|
||||
* is invoked or not. Also, even if the return type is void, if the type of argument
|
||||
* declared in the advice method is Object, then the advice must still get invoked.
|
||||
* @param type the type of argument declared in advice method
|
||||
* @param method the advice method
|
||||
* @param returnValue the return value of the target method
|
||||
* @return whether to invoke the advice method for the given return value and type
|
||||
*/
|
||||
private boolean matchesReturnValue(Class<?> type, Method method, Object returnValue) {
|
||||
if (returnValue != null) {
|
||||
return ClassUtils.isAssignableValue(type, returnValue);
|
||||
}
|
||||
else if (Object.class == type && void.class == method.getReturnType()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return ClassUtils.isAssignable(type, method.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-15
@@ -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,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,13 +37,10 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
return true;
|
||||
}
|
||||
@@ -56,16 +50,15 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
setThrowingNameNoCheck(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
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 +66,9 @@ 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) {
|
||||
Class throwingType = getDiscoveredThrowingType();
|
||||
return throwingType.isAssignableFrom(t.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,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,13 +41,10 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
super(aspectJAroundAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
return false;
|
||||
}
|
||||
@@ -59,7 +54,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
|
||||
|
||||
+141
-167
@@ -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.
|
||||
@@ -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;
|
||||
@@ -30,6 +29,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.weaver.BCException;
|
||||
import org.aspectj.weaver.patterns.NamePattern;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
import org.aspectj.weaver.tools.ContextBasedMatcher;
|
||||
@@ -42,7 +42,6 @@ import org.aspectj.weaver.tools.PointcutParameter;
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAwareMethodMatcher;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
@@ -55,9 +54,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -83,7 +80,7 @@ import org.springframework.util.StringUtils;
|
||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||
|
||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
|
||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
|
||||
|
||||
static {
|
||||
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
|
||||
@@ -101,19 +98,17 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
|
||||
|
||||
private Class<?> pointcutDeclarationScope;
|
||||
private Class pointcutDeclarationScope;
|
||||
|
||||
private String[] pointcutParameterNames = new String[0];
|
||||
|
||||
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
|
||||
private Class[] pointcutParameterTypes = new Class[0];
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private transient ClassLoader pointcutClassLoader;
|
||||
|
||||
private transient PointcutExpression pointcutExpression;
|
||||
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
|
||||
|
||||
|
||||
/**
|
||||
@@ -128,7 +123,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* @param paramNames the parameter names for the pointcut
|
||||
* @param paramTypes the parameter types for the pointcut
|
||||
*/
|
||||
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
|
||||
public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) {
|
||||
this.pointcutDeclarationScope = declarationScope;
|
||||
if (paramNames.length != paramTypes.length) {
|
||||
throw new IllegalStateException(
|
||||
@@ -142,37 +137,34 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
/**
|
||||
* Set the declaration scope for the pointcut.
|
||||
*/
|
||||
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
|
||||
public void setPointcutDeclarationScope(Class pointcutDeclarationScope) {
|
||||
this.pointcutDeclarationScope = pointcutDeclarationScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter names for the pointcut.
|
||||
*/
|
||||
public void setParameterNames(String... names) {
|
||||
public void setParameterNames(String[] names) {
|
||||
this.pointcutParameterNames = names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter types for the pointcut.
|
||||
*/
|
||||
public void setParameterTypes(Class<?>... types) {
|
||||
public void setParameterTypes(Class[] types) {
|
||||
this.pointcutParameterTypes = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClassFilter getClassFilter() {
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
checkReadyToMatch();
|
||||
return this;
|
||||
@@ -188,13 +180,20 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
if (this.pointcutExpression == null) {
|
||||
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
|
||||
this.pointcutExpression = buildPointcutExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private PointcutExpression buildPointcutExpression() {
|
||||
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory)
|
||||
.getBeanClassLoader() : Thread.currentThread()
|
||||
.getContextClassLoader());
|
||||
return buildPointcutExpression(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
@@ -203,9 +202,11 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
|
||||
for (int i = 0; i < pointcutParameters.length; i++) {
|
||||
pointcutParameters[i] = parser.createPointcutParameter(
|
||||
this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
|
||||
this.pointcutParameterNames[i],
|
||||
this.pointcutParameterTypes[i]);
|
||||
}
|
||||
return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()),
|
||||
return parser.parsePointcutExpression(
|
||||
replaceBooleanOperators(getExpression()),
|
||||
this.pointcutDeclarationScope, pointcutParameters);
|
||||
}
|
||||
|
||||
@@ -216,7 +217,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
PointcutParser parser = PointcutParser
|
||||
.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
|
||||
SUPPORTED_PRIMITIVES, cl);
|
||||
parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
|
||||
parser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler());
|
||||
return parser;
|
||||
}
|
||||
|
||||
@@ -243,30 +244,30 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
return this.pointcutExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> targetClass) {
|
||||
public boolean matches(Class targetClass) {
|
||||
checkReadyToMatch();
|
||||
try {
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
} catch (ReflectionWorldException e) {
|
||||
logger.debug("PointcutExpression matching rejected target class", e);
|
||||
try {
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
|
||||
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
|
||||
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
|
||||
if (fallbackExpression != null) {
|
||||
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
// Actually this is still a "maybe" - treat the pointcut as dynamic if we
|
||||
// don't know enough yet
|
||||
return getFallbackPointcutExpression(targetClass).couldMatchJoinPointsInType(targetClass);
|
||||
} catch (BCException ex) {
|
||||
logger.debug(
|
||||
"Fallback PointcutExpression matching rejected target class",
|
||||
ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (BCException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
public boolean matches(Method method, Class targetClass, boolean beanHasIntroductions) {
|
||||
checkReadyToMatch();
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
|
||||
@@ -282,31 +283,20 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
else {
|
||||
// the maybe case
|
||||
if (beanHasIntroductions) {
|
||||
return true;
|
||||
}
|
||||
// A match test returned maybe - if there are any subtype sensitive variables
|
||||
// involved in the test (this, target, at_this, at_target, at_annotation) then
|
||||
// we say this is not a match as in Spring there will never be a different
|
||||
// runtime subtype.
|
||||
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
|
||||
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
|
||||
return (beanHasIntroductions || matchesIgnoringSubtypes(shadowMatch) || matchesTarget(shadowMatch, targetClass));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
return matches(method, targetClass, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
checkReadyToMatch();
|
||||
return this.pointcutExpression.mayNeedDynamicTest();
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -328,67 +318,64 @@ 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);
|
||||
}
|
||||
return false;
|
||||
if (joinPointMatch.matches() && pmi != null) {
|
||||
bindParameters(pmi, joinPointMatch);
|
||||
}
|
||||
return joinPointMatch.matches();
|
||||
}
|
||||
|
||||
|
||||
protected String getCurrentProxiedBeanName() {
|
||||
return ProxyCreationContext.getCurrentProxiedBeanName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a new pointcut expression based on a target class's loader rather than the default.
|
||||
* Get a new pointcut expression based on a target class's loader, rather
|
||||
* than the default.
|
||||
*/
|
||||
private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
|
||||
try {
|
||||
ClassLoader classLoader = targetClass.getClassLoader();
|
||||
if (classLoader != null && classLoader != this.pointcutClassLoader) {
|
||||
return buildPointcutExpression(classLoader);
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to create fallback PointcutExpression", ex);
|
||||
}
|
||||
return null;
|
||||
private PointcutExpression getFallbackPointcutExpression(
|
||||
Class<?> targetClass) {
|
||||
ClassLoader classLoader = targetClass.getClassLoader();
|
||||
return classLoader == null ? this.pointcutExpression : buildPointcutExpression(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* A match test returned maybe - if there are any subtype sensitive variables
|
||||
* involved in the test (this, target, at_this, at_target, at_annotation) then
|
||||
* we say this is not a match as in Spring there will never be a different
|
||||
* runtime subtype.
|
||||
*/
|
||||
private boolean matchesIgnoringSubtypes(ShadowMatch shadowMatch) {
|
||||
return !(getRuntimeTestWalker(shadowMatch).testsSubtypeSensitiveVars());
|
||||
}
|
||||
|
||||
private boolean matchesTarget(ShadowMatch shadowMatch, Class targetClass) {
|
||||
return getRuntimeTestWalker(shadowMatch).testTargetInstanceOfResidue(targetClass);
|
||||
}
|
||||
|
||||
private RuntimeTestWalker getRuntimeTestWalker(ShadowMatch shadowMatch) {
|
||||
if (shadowMatch instanceof DefensiveShadowMatch) {
|
||||
return new RuntimeTestWalker(((DefensiveShadowMatch) shadowMatch).primary);
|
||||
return new RuntimeTestWalker(((DefensiveShadowMatch)shadowMatch).primary);
|
||||
}
|
||||
return new RuntimeTestWalker(shadowMatch);
|
||||
}
|
||||
@@ -409,51 +396,44 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
if (shadowMatch == null) {
|
||||
synchronized (this.shadowMatchCache) {
|
||||
// Not found - now check again with full lock...
|
||||
PointcutExpression fallbackExpression = null;
|
||||
Method methodToMatch = targetMethod;
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
PointcutExpression fallbackPointcutExpression = null;
|
||||
shadowMatch = this.shadowMatchCache.get(methodToMatch);
|
||||
if (shadowMatch == null) {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
// in a special ClassLoader. Let's try the original method instead...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
} catch (ReflectionWorld.ReflectionWorldException e) {
|
||||
if (targetMethod == originalMethod) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
else {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex2) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's simply consider this method as non-matching.
|
||||
methodToMatch = originalMethod;
|
||||
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
try {
|
||||
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
} catch (ReflectionWorld.ReflectionWorldException e2) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
|
||||
if (shadowMatch.maybeMatches() && fallbackPointcutExpression!=null) {
|
||||
shadowMatch = new DefensiveShadowMatch(shadowMatch,
|
||||
fallbackExpression.matchesMethodExecution(methodToMatch));
|
||||
fallbackPointcutExpression.matchesMethodExecution(methodToMatch));
|
||||
}
|
||||
this.shadowMatchCache.put(targetMethod, shadowMatch);
|
||||
}
|
||||
@@ -522,18 +502,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* automatically by examining a thread local variable and therefore a matching
|
||||
* context need not be set on the pointcut.
|
||||
*/
|
||||
private class BeanPointcutDesignatorHandler implements PointcutDesignatorHandler {
|
||||
private class BeanNamePointcutDesignatorHandler implements PointcutDesignatorHandler {
|
||||
|
||||
private static final String BEAN_DESIGNATOR_NAME = "bean";
|
||||
|
||||
@Override
|
||||
public String getDesignatorName() {
|
||||
return BEAN_DESIGNATOR_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextBasedMatcher parse(String expression) {
|
||||
return new BeanContextMatcher(expression);
|
||||
return new BeanNameContextMatcher(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,44 +523,35 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* For static match tests, this matcher abstains to allow the overall
|
||||
* pointcut to match even when negation is used with the bean() pointcut.
|
||||
*/
|
||||
private class BeanContextMatcher implements ContextBasedMatcher {
|
||||
private class BeanNameContextMatcher implements ContextBasedMatcher {
|
||||
|
||||
private final NamePattern expressionPattern;
|
||||
|
||||
public BeanContextMatcher(String expression) {
|
||||
public BeanNameContextMatcher(String expression) {
|
||||
this.expressionPattern = new NamePattern(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Deprecated
|
||||
public boolean couldMatchJoinPointsInType(Class someClass) {
|
||||
return (contextMatch(someClass) == FuzzyBoolean.YES);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Deprecated
|
||||
public boolean couldMatchJoinPointsInType(Class someClass, MatchingContext context) {
|
||||
return (contextMatch(someClass) == FuzzyBoolean.YES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesDynamically(MatchingContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FuzzyBoolean matchesStatically(MatchingContext context) {
|
||||
return contextMatch(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayNeedDynamicTest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private FuzzyBoolean contextMatch(Class<?> targetType) {
|
||||
private FuzzyBoolean contextMatch(Class targetType) {
|
||||
String advisedBeanName = getCurrentProxiedBeanName();
|
||||
if (advisedBeanName == null) { // no proxy creation in progress
|
||||
// abstain; can't return YES, since that will make pointcut with negation fail
|
||||
@@ -594,16 +563,27 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
if (targetType != null) {
|
||||
boolean isFactory = FactoryBean.class.isAssignableFrom(targetType);
|
||||
return FuzzyBoolean.fromBoolean(
|
||||
matchesBean(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
|
||||
matchesBeanName(isFactory ? BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName : advisedBeanName));
|
||||
}
|
||||
else {
|
||||
return FuzzyBoolean.fromBoolean(matchesBean(advisedBeanName) ||
|
||||
matchesBean(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
|
||||
return FuzzyBoolean.fromBoolean(matchesBeanName(advisedBeanName) ||
|
||||
matchesBeanName(BeanFactory.FACTORY_BEAN_PREFIX + advisedBeanName));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesBean(String advisedBeanName) {
|
||||
return BeanFactoryAnnotationUtils.isQualifierMatch(this.expressionPattern::matches, advisedBeanName, beanFactory);
|
||||
private boolean matchesBeanName(String advisedBeanName) {
|
||||
if (this.expressionPattern.matches(advisedBeanName)) {
|
||||
return true;
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
String[] aliases = beanFactory.getAliases(advisedBeanName);
|
||||
for (String alias : aliases) {
|
||||
if (this.expressionPattern.matches(alias)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,14 +598,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
// Initialize transient fields.
|
||||
// pointcutExpression will be initialized lazily by checkReadyToMatch()
|
||||
this.shadowMatchCache = new ConcurrentHashMap<>(32);
|
||||
this.shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
|
||||
}
|
||||
|
||||
|
||||
private static class DefensiveShadowMatch implements ShadowMatch {
|
||||
|
||||
private final ShadowMatch primary;
|
||||
|
||||
private final ShadowMatch other;
|
||||
|
||||
public DefensiveShadowMatch(ShadowMatch primary, ShadowMatch other) {
|
||||
@@ -633,36 +611,32 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
this.other = other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean alwaysMatches() {
|
||||
return this.primary.alwaysMatches();
|
||||
return primary.alwaysMatches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean maybeMatches() {
|
||||
return this.primary.maybeMatches();
|
||||
return primary.maybeMatches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean neverMatches() {
|
||||
return this.primary.neverMatches();
|
||||
return primary.neverMatches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args) {
|
||||
public JoinPointMatch matchesJoinPoint(Object thisObject,
|
||||
Object targetObject, Object[] args) {
|
||||
try {
|
||||
return this.primary.matchesJoinPoint(thisObject, targetObject, args);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
return this.other.matchesJoinPoint(thisObject, targetObject, args);
|
||||
return primary.matchesJoinPoint(thisObject, targetObject, args);
|
||||
} catch (ReflectionWorldException e) {
|
||||
return other.matchesJoinPoint(thisObject, targetObject, args);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMatchingContext(MatchingContext aMatchContext) {
|
||||
this.primary.setMatchingContext(aMatchContext);
|
||||
this.other.setMatchingContext(aMatchContext);
|
||||
primary.setMatchingContext(aMatchContext);
|
||||
other.setMatchingContext(aMatchContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-12
@@ -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.
|
||||
@@ -31,7 +31,6 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
|
||||
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
@@ -40,24 +39,24 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.pointcut.setLocation(location);
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class[] types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
public void setParameterNames(String[] names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class<?>[] types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
public void setParameterNames(String... names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -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,18 +35,14 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,22 +56,18 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.order != null) {
|
||||
return this.order;
|
||||
|
||||
-4
@@ -48,7 +48,6 @@ public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
private static final Log logger = LogFactory.getLog("AspectJ Weaver");
|
||||
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(IMessage message) throws AbortException {
|
||||
Kind messageKind = message.getKind();
|
||||
if (messageKind == IMessage.DEBUG) {
|
||||
@@ -88,18 +87,15 @@ public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
return AJ_ID + aMessage.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIgnoring(Kind messageKind) {
|
||||
// We want to see everything, and allow configuration of log levels dynamically.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dontIgnore(Kind messageKind) {
|
||||
// We weren't ignoring anything anyway...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ignore(Kind kind) {
|
||||
// We weren't ignoring anything anyway...
|
||||
}
|
||||
|
||||
+8
-14
@@ -34,7 +34,7 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
*/
|
||||
public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
|
||||
private final Class<?> introducedInterface;
|
||||
private final Class introducedInterface;
|
||||
|
||||
private final ClassFilter typePatternClassFilter;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param defaultImpl the default implementation class
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
|
||||
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Class defaultImpl) {
|
||||
this(interfaceType, typePattern, defaultImpl,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
}
|
||||
@@ -58,27 +58,26 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param delegateRef the delegate implementation object
|
||||
*/
|
||||
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
|
||||
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Object delegateRef) {
|
||||
this(interfaceType, typePattern, delegateRef.getClass(),
|
||||
new DelegatingIntroductionInterceptor(delegateRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to share common code between impl-based delegate and reference-based delegate
|
||||
* (cannot use method such as init() to share common code, due the use of final fields)
|
||||
* (cannot use method such as init() to share common code, due the the use of final fields)
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param implementationClass implementation class
|
||||
* @param advice delegation advice
|
||||
*/
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> implementationClass, Advice advice) {
|
||||
private DeclareParentsAdvisor(Class interfaceType, String typePattern, Class implementationClass, Advice advice) {
|
||||
this.introducedInterface = interfaceType;
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
|
||||
// Excludes methods implemented.
|
||||
ClassFilter exclusion = new ClassFilter() {
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
public boolean matches(Class clazz) {
|
||||
return !(introducedInterface.isAssignableFrom(clazz));
|
||||
}
|
||||
};
|
||||
@@ -88,29 +87,24 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ClassFilter getClassFilter() {
|
||||
return this.typePatternClassFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateInterfaces() throws IllegalArgumentException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getInterfaces() {
|
||||
return new Class<?>[] {this.introducedInterface};
|
||||
public Class[] getInterfaces() {
|
||||
return new Class[] {this.introducedInterface};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-47
@@ -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,8 +27,7 @@ import org.aspectj.lang.reflect.SourceLocation;
|
||||
import org.aspectj.runtime.internal.AroundClosure;
|
||||
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -52,8 +51,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
|
||||
|
||||
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
@@ -75,17 +72,14 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
this.methodInvocation = methodInvocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set$AroundClosure(AroundClosure aroundClosure) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object proceed() throws Throwable {
|
||||
return this.methodInvocation.invocableClone().proceed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object proceed(Object[] arguments) throws Throwable {
|
||||
Assert.notNull(arguments, "Argument array passed to proceed cannot be null");
|
||||
if (arguments.length != this.methodInvocation.getArguments().length) {
|
||||
@@ -100,7 +94,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
/**
|
||||
* Returns the Spring AOP proxy. Cannot be {@code null}.
|
||||
*/
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return this.methodInvocation.getProxy();
|
||||
}
|
||||
@@ -108,12 +101,10 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
/**
|
||||
* Returns the Spring AOP target. May be {@code null} if there is no target.
|
||||
*/
|
||||
@Override
|
||||
public Object getTarget() {
|
||||
return this.methodInvocation.getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArgs() {
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
@@ -123,7 +114,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
return this.defensiveCopyOfArgs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Signature getSignature() {
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
@@ -131,7 +121,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceLocation getSourceLocation() {
|
||||
if (this.sourceLocation == null) {
|
||||
this.sourceLocation = new SourceLocationImpl();
|
||||
@@ -139,33 +128,27 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
return this.sourceLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKind() {
|
||||
return ProceedingJoinPoint.METHOD_EXECUTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
// TODO: It's just an adapter but returning 0 might still have side effects...
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JoinPoint.StaticPart getStaticPart() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toShortString() {
|
||||
return "execution(" + getSignature().toShortString() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLongString() {
|
||||
return "execution(" + getSignature().toLongString() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "execution(" + getSignature().toString() + ")";
|
||||
}
|
||||
@@ -178,72 +161,59 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
private volatile String[] parameterNames;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return methodInvocation.getMethod().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModifiers() {
|
||||
return methodInvocation.getMethod().getModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getDeclaringType() {
|
||||
public Class getDeclaringType() {
|
||||
return methodInvocation.getMethod().getDeclaringClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeclaringTypeName() {
|
||||
return methodInvocation.getMethod().getDeclaringClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getReturnType() {
|
||||
public Class getReturnType() {
|
||||
return methodInvocation.getMethod().getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getMethod() {
|
||||
return methodInvocation.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParameterTypes() {
|
||||
public Class[] getParameterTypes() {
|
||||
return methodInvocation.getMethod().getParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterNames() {
|
||||
if (this.parameterNames == null) {
|
||||
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||
this.parameterNames = (new LocalVariableTableParameterNameDiscoverer()).getParameterNames(getMethod());
|
||||
}
|
||||
return this.parameterNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getExceptionTypes() {
|
||||
public Class[] getExceptionTypes() {
|
||||
return methodInvocation.getMethod().getExceptionTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toShortString() {
|
||||
return toString(false, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toLongString() {
|
||||
return toString(true, true, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(false, true, false, true);
|
||||
}
|
||||
|
||||
private String toString(boolean includeModifier, boolean includeReturnTypeAndArgs,
|
||||
boolean useLongReturnAndArgumentTypeName, boolean useLongTypeName) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (includeModifier) {
|
||||
sb.append(Modifier.toString(getModifiers()));
|
||||
@@ -257,15 +227,14 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
sb.append(".");
|
||||
sb.append(getMethod().getName());
|
||||
sb.append("(");
|
||||
Class<?>[] parametersTypes = getParameterTypes();
|
||||
Class[] parametersTypes = getParameterTypes();
|
||||
appendTypes(sb, parametersTypes, includeReturnTypeAndArgs, useLongReturnAndArgumentTypeName);
|
||||
sb.append(")");
|
||||
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);
|
||||
@@ -298,26 +267,21 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
*/
|
||||
private class SourceLocationImpl implements SourceLocation {
|
||||
|
||||
@Override
|
||||
public Class<?> getWithinType() {
|
||||
public Class getWithinType() {
|
||||
if (methodInvocation.getThis() == null) {
|
||||
throw new UnsupportedOperationException("No source location joinpoint available: target is null");
|
||||
}
|
||||
return methodInvocation.getThis().getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLine() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getColumn() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,6 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.aspectj.weaver.ReferenceType;
|
||||
import org.aspectj.weaver.ReferenceTypeDelegate;
|
||||
import org.aspectj.weaver.ResolvedType;
|
||||
import org.aspectj.weaver.ast.And;
|
||||
import org.aspectj.weaver.ast.Call;
|
||||
@@ -32,7 +30,6 @@ import org.aspectj.weaver.ast.Not;
|
||||
import org.aspectj.weaver.ast.Or;
|
||||
import org.aspectj.weaver.ast.Test;
|
||||
import org.aspectj.weaver.internal.tools.MatchingContextBasedTest;
|
||||
import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate;
|
||||
import org.aspectj.weaver.reflect.ReflectionVar;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
@@ -50,7 +47,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
|
||||
@@ -58,36 +55,25 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
class RuntimeTestWalker {
|
||||
|
||||
private static final Field residualTestField;
|
||||
|
||||
private static final Field varTypeField;
|
||||
|
||||
private static final Field myClassField;
|
||||
|
||||
|
||||
static {
|
||||
try {
|
||||
residualTestField = ShadowMatchImpl.class.getDeclaredField("residualTest");
|
||||
varTypeField = ReflectionVar.class.getDeclaredField("varType");
|
||||
myClassField = ReflectionBasedReferenceTypeDelegate.class.getDeclaredField("myClass");
|
||||
}
|
||||
catch (NoSuchFieldException ex) {
|
||||
throw new IllegalStateException("The version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
"on the classpath is incompatible with this version of Spring: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Test runtimeTest;
|
||||
|
||||
|
||||
public RuntimeTestWalker(ShadowMatch shadowMatch) {
|
||||
ShadowMatchImpl shadowMatchImplementation = (ShadowMatchImpl) shadowMatch;
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(residualTestField);
|
||||
this.runtimeTest = (Test) residualTestField.get(shadowMatch);
|
||||
Field testField = shadowMatchImplementation.getClass().getDeclaredField("residualTest");
|
||||
ReflectionUtils.makeAccessible(testField);
|
||||
this.runtimeTest = (Test) testField.get(shadowMatch);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("The version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
"on the classpath is incompatible with this version of Spring: Expected field " +
|
||||
"'runtimeTest' is not present on ShadowMatchImpl class.");
|
||||
}
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ShadowMatchImpl.residualTest field");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,12 +87,12 @@ class RuntimeTestWalker {
|
||||
new SubtypeSensitiveVarTypeTestVisitor().testsSubtypeSensitiveVars(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testThisInstanceOfResidue(Class<?> thisClass) {
|
||||
public boolean testThisInstanceOfResidue(Class thisClass) {
|
||||
return (this.runtimeTest != null &&
|
||||
new ThisInstanceOfResidueTestVisitor(thisClass).thisInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
|
||||
public boolean testTargetInstanceOfResidue(Class<?> targetClass) {
|
||||
public boolean testTargetInstanceOfResidue(Class targetClass) {
|
||||
return (this.runtimeTest != null &&
|
||||
new TargetInstanceOfResidueTestVisitor(targetClass).targetInstanceOfMatches(this.runtimeTest));
|
||||
}
|
||||
@@ -120,54 +106,53 @@ class RuntimeTestWalker {
|
||||
protected static final int AT_TARGET_VAR = 4;
|
||||
protected static final int AT_ANNOTATION_VAR = 8;
|
||||
|
||||
@Override
|
||||
public void visit(And e) {
|
||||
e.getLeft().accept(this);
|
||||
e.getRight().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Or e) {
|
||||
e.getLeft().accept(this);
|
||||
e.getRight().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Not e) {
|
||||
e.getBody().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Instanceof i) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Literal literal) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Call call) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FieldGetCall fieldGetCall) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(HasAnnotation hasAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MatchingContextBasedTest matchingContextTest) {
|
||||
}
|
||||
|
||||
protected int getVarType(ReflectionVar v) {
|
||||
try {
|
||||
Field varTypeField = ReflectionVar.class.getDeclaredField("varType");
|
||||
ReflectionUtils.makeAccessible(varTypeField);
|
||||
return (Integer) varTypeField.get(v);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
catch (NoSuchFieldException noSuchFieldEx) {
|
||||
throw new IllegalStateException("the version of aspectjtools.jar / aspectjweaver.jar " +
|
||||
"on the classpath is incompatible with this version of Spring:- expected field " +
|
||||
"'varType' is not present on ReflectionVar class");
|
||||
}
|
||||
catch (IllegalAccessException illegalAccessEx) {
|
||||
// Famous last words... but I don't see how this can happen given the
|
||||
// makeAccessible call above
|
||||
throw new IllegalStateException("Unable to access ReflectionVar.varType field");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,13 +160,11 @@ class RuntimeTestWalker {
|
||||
|
||||
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private final Class<?> matchClass;
|
||||
|
||||
private Class matchClass;
|
||||
private boolean matches;
|
||||
private int matchVarType;
|
||||
|
||||
private final int matchVarType;
|
||||
|
||||
public InstanceOfResidueTestVisitor(Class<?> matchClass, boolean defaultMatches, int matchVarType) {
|
||||
public InstanceOfResidueTestVisitor(Class matchClass, boolean defaultMatches, int matchVarType) {
|
||||
this.matchClass = matchClass;
|
||||
this.matches = defaultMatches;
|
||||
this.matchVarType = matchVarType;
|
||||
@@ -189,34 +172,19 @@ class RuntimeTestWalker {
|
||||
|
||||
public boolean instanceOfMatches(Test test) {
|
||||
test.accept(this);
|
||||
return this.matches;
|
||||
return matches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(Instanceof i) {
|
||||
ResolvedType type = (ResolvedType) i.getType();
|
||||
int varType = getVarType((ReflectionVar) i.getVar());
|
||||
if (varType != this.matchVarType) {
|
||||
return;
|
||||
}
|
||||
Class<?> typeClass = null;
|
||||
ResolvedType type = (ResolvedType) i.getType();
|
||||
if (type instanceof ReferenceType) {
|
||||
ReferenceTypeDelegate delegate = ((ReferenceType) type).getDelegate();
|
||||
if (delegate instanceof ReflectionBasedReferenceTypeDelegate) {
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(myClassField);
|
||||
typeClass = (Class<?>) myClassField.get(delegate);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Don't use ResolvedType.isAssignableFrom() as it won't be aware of (Spring) mixins
|
||||
if (typeClass == null) {
|
||||
typeClass = ClassUtils.forName(type.getName(), this.matchClass.getClassLoader());
|
||||
}
|
||||
Class typeClass = ClassUtils.forName(type.getName(), this.matchClass.getClassLoader());
|
||||
// Don't use ReflectionType.isAssignableFrom() as it won't be aware of (Spring) mixins
|
||||
this.matches = typeClass.isAssignableFrom(this.matchClass);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
@@ -231,7 +199,7 @@ class RuntimeTestWalker {
|
||||
*/
|
||||
private static class TargetInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
|
||||
|
||||
public TargetInstanceOfResidueTestVisitor(Class<?> targetClass) {
|
||||
public TargetInstanceOfResidueTestVisitor(Class targetClass) {
|
||||
super(targetClass, false, TARGET_VAR);
|
||||
}
|
||||
|
||||
@@ -246,7 +214,7 @@ class RuntimeTestWalker {
|
||||
*/
|
||||
private static class ThisInstanceOfResidueTestVisitor extends InstanceOfResidueTestVisitor {
|
||||
|
||||
public ThisInstanceOfResidueTestVisitor(Class<?> thisClass) {
|
||||
public ThisInstanceOfResidueTestVisitor(Class thisClass) {
|
||||
super(thisClass, true, THIS_VAR);
|
||||
}
|
||||
|
||||
@@ -260,11 +228,8 @@ class RuntimeTestWalker {
|
||||
private static class SubtypeSensitiveVarTypeTestVisitor extends TestVisitorAdapter {
|
||||
|
||||
private final Object thisObj = new Object();
|
||||
|
||||
private final Object targetObj = new Object();
|
||||
|
||||
private final Object[] argsObjs = new Object[0];
|
||||
|
||||
private boolean testsSubtypeSensitiveVars = false;
|
||||
|
||||
public boolean testsSubtypeSensitiveVars(Test aTest) {
|
||||
@@ -275,8 +240,8 @@ class RuntimeTestWalker {
|
||||
@Override
|
||||
public void visit(Instanceof i) {
|
||||
ReflectionVar v = (ReflectionVar) i.getVar();
|
||||
Object varUnderTest = v.getBindingAtJoinPoint(this.thisObj, this.targetObj, this.argsObjs);
|
||||
if (varUnderTest == this.thisObj || varUnderTest == this.targetObj) {
|
||||
Object varUnderTest = v.getBindingAtJoinPoint(thisObj,targetObj,argsObjs);
|
||||
if ((varUnderTest == thisObj) || (varUnderTest == targetObj)) {
|
||||
this.testsSubtypeSensitiveVars = true;
|
||||
}
|
||||
}
|
||||
@@ -286,7 +251,7 @@ class RuntimeTestWalker {
|
||||
// If you thought things were bad before, now we sink to new levels of horror...
|
||||
ReflectionVar v = (ReflectionVar) hasAnn.getVar();
|
||||
int varType = getVarType(v);
|
||||
if (varType == AT_THIS_VAR || varType == AT_TARGET_VAR || varType == AT_ANNOTATION_VAR) {
|
||||
if ((varType == AT_THIS_VAR) || (varType == AT_TARGET_VAR) || (varType == AT_ANNOTATION_VAR)) {
|
||||
this.testsSubtypeSensitiveVars = true;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-23
@@ -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,12 +16,9 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AspectInstanceFactory} that creates a new instance
|
||||
@@ -32,14 +29,14 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
|
||||
private final Class<?> aspectClass;
|
||||
private final Class aspectClass;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SimpleAspectInstanceFactory for the given aspect class.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
public SimpleAspectInstanceFactory(Class<?> aspectClass) {
|
||||
public SimpleAspectInstanceFactory(Class aspectClass) {
|
||||
Assert.notNull(aspectClass, "Aspect class must not be null");
|
||||
this.aspectClass = aspectClass;
|
||||
}
|
||||
@@ -47,35 +44,23 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
/**
|
||||
* Return the specified aspect class (never {@code null}).
|
||||
*/
|
||||
public final Class<?> getAspectClass() {
|
||||
public final Class getAspectClass() {
|
||||
return this.aspectClass;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Object getAspectInstance() {
|
||||
try {
|
||||
return ReflectionUtils.accessibleConstructor(this.aspectClass).newInstance();
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new AopConfigException(
|
||||
"No default constructor on aspect class: " + this.aspectClass.getName(), ex);
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new AopConfigException(
|
||||
"Failed to invoke aspect constructor: " + this.aspectClass.getName(), ex.getTargetException());
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectClass.getClassLoader();
|
||||
}
|
||||
@@ -88,7 +73,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see #getOrderForAspectClass
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return getOrderForAspectClass(this.aspectClass);
|
||||
}
|
||||
|
||||
+2
-8
@@ -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;
|
||||
|
||||
@@ -47,12 +44,10 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Object getAspectInstance() {
|
||||
return this.aspectInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectInstance.getClass().getClassLoader();
|
||||
}
|
||||
@@ -65,7 +60,6 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see #getOrderForAspectClass
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.aspectInstance instanceof Ordered) {
|
||||
return ((Ordered) this.aspectInstance).getOrder();
|
||||
|
||||
+1
-2
@@ -93,8 +93,7 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* @return whether the advice should apply to this candidate target class
|
||||
* @throws IllegalStateException if no {@link #setTypePattern(String)} has been set
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
public boolean matches(Class clazz) {
|
||||
if (this.aspectJTypePatternMatcher == null) {
|
||||
throw new IllegalStateException("No 'typePattern' has been set via ctor/setter.");
|
||||
}
|
||||
|
||||
+47
-43
@@ -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.
|
||||
@@ -41,6 +41,7 @@ import org.aspectj.lang.reflect.PerClauseKind;
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PrioritizedParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -58,22 +59,58 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
|
||||
|
||||
protected static final ParameterNameDiscoverer ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER =
|
||||
new AspectJAnnotationParameterNameDiscoverer();
|
||||
|
||||
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<? extends Annotation>[] classesToLookFor = new Class[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<? extends Annotation> c : classesToLookFor) {
|
||||
AspectJAnnotation foundAnnotation = findAnnotation(method, 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());
|
||||
|
||||
protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();
|
||||
protected final ParameterNameDiscoverer parameterNameDiscoverer;
|
||||
|
||||
|
||||
protected AbstractAspectJAdvisorFactory() {
|
||||
PrioritizedParameterNameDiscoverer prioritizedParameterNameDiscoverer = new PrioritizedParameterNameDiscoverer();
|
||||
prioritizedParameterNameDiscoverer.addDiscoverer(ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER);
|
||||
this.parameterNameDiscoverer = prioritizedParameterNameDiscoverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* We consider something to be an AspectJ aspect suitable for use by the Spring AOP system
|
||||
* if it has the @Aspect annotation, and was not compiled by ajc. The reason for this latter test
|
||||
* is that aspects written in the code-style (AspectJ language) also have the annotation present
|
||||
* when compiled by ajc with the -1.5 flag, yet they cannot be consumed by Spring AOP.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAspect(Class<?> clazz) {
|
||||
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
|
||||
}
|
||||
@@ -98,7 +135,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Class<?> aspectClass) throws AopConfigException {
|
||||
// If the parent has the annotation and isn't abstract it's an error
|
||||
if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
|
||||
@@ -127,7 +163,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
* formal parameters for the pointcut.
|
||||
*/
|
||||
protected AspectJExpressionPointcut createPointcutExpression(
|
||||
Method annotatedMethod, Class<?> declarationScope, String[] pointcutParameterNames) {
|
||||
Method annotatedMethod, Class declarationScope, String[] pointcutParameterNames) {
|
||||
|
||||
Class<?> [] pointcutParameterTypes = new Class<?>[0];
|
||||
if (pointcutParameterNames != null) {
|
||||
@@ -153,7 +189,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 +199,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<>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
@@ -211,8 +217,8 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
|
||||
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypes =
|
||||
new HashMap<>();
|
||||
private static Map<Class, AspectJAnnotationType> annotationTypes =
|
||||
new HashMap<Class, AspectJAnnotationType>();
|
||||
|
||||
static {
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
@@ -246,7 +252,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
private AspectJAnnotationType determineAnnotationType(A annotation) {
|
||||
for (Class<?> type : annotationTypes.keySet()) {
|
||||
for (Class type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(annotation)) {
|
||||
return annotationTypes.get(type);
|
||||
}
|
||||
@@ -303,12 +309,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
*/
|
||||
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
|
||||
@Override
|
||||
public String[] getParameterNames(Method method) {
|
||||
if (method.getParameterCount() == 0) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
return new String[0];
|
||||
}
|
||||
AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
|
||||
AspectJAnnotation annotation = findAspectJAnnotationOnMethod(method);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -325,8 +330,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterNames(Constructor<?> ctor) {
|
||||
public String[] getParameterNames(Constructor ctor) {
|
||||
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,14 +60,14 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
* <p>Default is to consider all @AspectJ beans as eligible.
|
||||
*/
|
||||
public void setIncludePatterns(List<String> patterns) {
|
||||
this.includePatterns = new ArrayList<>(patterns.size());
|
||||
this.includePatterns = new ArrayList<Pattern>(patterns.size());
|
||||
for (String patternText : patterns) {
|
||||
this.includePatterns.add(Pattern.compile(patternText));
|
||||
}
|
||||
}
|
||||
|
||||
public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
|
||||
Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
|
||||
Assert.notNull(this.aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
|
||||
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInfrastructureClass(Class<?> beanClass) {
|
||||
protected boolean isInfrastructureClass(Class beanClass) {
|
||||
// Previously we setProxyTargetClass(true) in the constructor, but that has too
|
||||
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
|
||||
// aspects. I'm not entirely happy with that as there is no good reason not
|
||||
|
||||
+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);
|
||||
|
||||
}
|
||||
|
||||
+22
-14
@@ -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.
|
||||
@@ -24,10 +24,10 @@ import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.aspectj.SimpleAspectInstanceFactory;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyCreatorSupport;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.springframework.util.ClassUtils;
|
||||
public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/** Cache for singleton aspect instances */
|
||||
private static final Map<Class<?>, Object> aspectCache = new HashMap<>();
|
||||
private static final Map<Class, Object> aspectCache = new HashMap<Class, Object>();
|
||||
|
||||
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* @param aspectInstance the AspectJ aspect instance
|
||||
*/
|
||||
public void addAspect(Object aspectInstance) {
|
||||
Class<?> aspectClass = aspectInstance.getClass();
|
||||
Class aspectClass = aspectInstance.getClass();
|
||||
String aspectName = aspectClass.getName();
|
||||
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
|
||||
if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) {
|
||||
@@ -104,7 +104,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* Add an aspect of the supplied type to the end of the advice chain.
|
||||
* @param aspectClass the AspectJ aspect class
|
||||
*/
|
||||
public void addAspect(Class<?> aspectClass) {
|
||||
public void addAspect(Class aspectClass) {
|
||||
String aspectName = aspectClass.getName();
|
||||
AspectMetadata am = createAspectMetadata(aspectClass, aspectName);
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName);
|
||||
@@ -121,14 +121,14 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link AspectMetadata} instance for the supplied aspect type.
|
||||
*/
|
||||
private AspectMetadata createAspectMetadata(Class<?> aspectClass, String aspectName) {
|
||||
private AspectMetadata createAspectMetadata(Class aspectClass, String aspectName) {
|
||||
AspectMetadata am = new AspectMetadata(aspectClass, aspectName);
|
||||
if (!am.getAjType().isAspect()) {
|
||||
throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type");
|
||||
@@ -142,7 +142,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* a {@link PrototypeAspectInstanceFactory} is returned.
|
||||
*/
|
||||
private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
|
||||
AspectMetadata am, Class<?> aspectClass, String aspectName) {
|
||||
AspectMetadata am, Class aspectClass, String aspectName) {
|
||||
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = null;
|
||||
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
@@ -161,15 +161,23 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* Get the singleton aspect instance for the supplied aspect type. An instance
|
||||
* is created if one cannot be found in the instance cache.
|
||||
*/
|
||||
private Object getSingletonAspectInstance(Class<?> aspectClass) {
|
||||
private Object getSingletonAspectInstance(Class aspectClass) {
|
||||
synchronized (aspectCache) {
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-37
@@ -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.
|
||||
@@ -83,9 +71,9 @@ public class AspectMetadata implements Serializable {
|
||||
this.aspectName = aspectName;
|
||||
|
||||
Class<?> currClass = aspectClass;
|
||||
AjType<?> ajType = null;
|
||||
while (currClass != Object.class) {
|
||||
AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
|
||||
AjType ajType = null;
|
||||
while (!currClass.equals(Object.class)) {
|
||||
AjType ajTypeToCheck = AjTypeSystem.getAjType(currClass);
|
||||
if (ajTypeToCheck.isAspect()) {
|
||||
ajType = ajTypeToCheck;
|
||||
break;
|
||||
@@ -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 :
|
||||
@@ -137,15 +124,15 @@ public class AspectMetadata implements Serializable {
|
||||
/**
|
||||
* Return AspectJ reflection information.
|
||||
*/
|
||||
public AjType<?> getAjType() {
|
||||
public AjType getAjType() {
|
||||
return this.ajType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public Class<?> getAspectClass() {
|
||||
return this.aspectClass;
|
||||
public Class getAspectClass() {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-24
@@ -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,13 +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.util.Assert;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -40,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;
|
||||
|
||||
@@ -69,38 +66,30 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
* @param name the name of the bean
|
||||
* @param type the type that should be introspected by AspectJ
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(name, "Bean name must not be null");
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class type) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.name = name;
|
||||
this.aspectMetadata = new AspectMetadata(type, name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
return this.beanFactory.getBean(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
}
|
||||
else {
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AspectMetadata getAspectMetadata() {
|
||||
return this.aspectMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's target aspect, either
|
||||
* an instance-specific order expressed through implementing the
|
||||
@@ -111,14 +100,16 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.core.annotation.Order
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
Class<?> type = this.beanFactory.getType(this.name);
|
||||
if (type != null) {
|
||||
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;
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,10 +45,10 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private List<String> aspectBeanNames;
|
||||
|
||||
private final Map<String, List<Advisor>> advisorsCache = new HashMap<>();
|
||||
private final Map<String, List<Advisor>> advisorsCache = new HashMap<String, List<Advisor>>();
|
||||
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
|
||||
new HashMap<>();
|
||||
new HashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -85,8 +85,8 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<>();
|
||||
aspectNames = new LinkedList<>();
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
@@ -96,7 +96,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
// We must be careful not to instantiate beans eagerly as in this
|
||||
// case they would be cached by the Spring container but would not
|
||||
// have been weaved
|
||||
Class<?> beanType = this.beanFactory.getType(beanName);
|
||||
Class beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -134,9 +134,9 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
}
|
||||
|
||||
if (aspectNames.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
List<Advisor> advisors = new LinkedList<>();
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (String aspectName : aspectNames) {
|
||||
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
|
||||
if (cachedAdvisors != null) {
|
||||
|
||||
+29
-65
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +97,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
|
||||
* depending on the state of the advice.
|
||||
*/
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
@@ -122,7 +106,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
* are much richer. In AspectJ terminology, all a return of {@code true}
|
||||
* means here is that the aspect is not a SINGLETON.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
|
||||
}
|
||||
@@ -137,7 +120,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
@@ -145,20 +127,18 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return this.atAspectJAdvisorFactory.getAdvice(
|
||||
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
@@ -169,22 +149,18 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.declaredPointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.aspectInstanceFactory.getOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeclarationOrder() {
|
||||
return this.declarationOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
if (this.isBeforeAdvice == null) {
|
||||
determineAdviceType();
|
||||
@@ -192,7 +168,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.isBeforeAdvice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
if (this.isAfterAdvice == null) {
|
||||
determineAdviceType();
|
||||
@@ -206,7 +181,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 +210,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.
|
||||
@@ -274,14 +239,13 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
public boolean matches(Method method, Class targetClass) {
|
||||
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
|
||||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
+4
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2009 the original author 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;
|
||||
|
||||
@@ -45,10 +42,9 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
public synchronized Object getAspectInstance() {
|
||||
if (this.materialized == null) {
|
||||
synchronized (this.maaif.getAspectCreationMutex()) {
|
||||
synchronized (this) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
@@ -61,22 +57,14 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
return (this.materialized != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.maaif.getAspectClassLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AspectMetadata getAspectMetadata() {
|
||||
return this.maaif.getAspectMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this.maaif.getAspectCreationMutex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.maaif.getOrder();
|
||||
}
|
||||
|
||||
+1
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,11 +39,4 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
|
||||
*/
|
||||
AspectMetadata getAspectMetadata();
|
||||
|
||||
/**
|
||||
* Return the best possible creation mutex for this factory.
|
||||
* @return the mutex object (never {@code null})
|
||||
* @since 4.3
|
||||
*/
|
||||
Object getAspectCreationMutex();
|
||||
|
||||
}
|
||||
|
||||
+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
|
||||
|
||||
+34
-52
@@ -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,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,27 +65,23 @@ 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;
|
||||
|
||||
static {
|
||||
CompoundComparator<Method> comparator = new CompoundComparator<>();
|
||||
comparator.addComparator(new ConvertingComparator<>(
|
||||
new InstanceComparator<>(
|
||||
CompoundComparator<Method> comparator = new CompoundComparator<Method>();
|
||||
comparator.addComparator(new ConvertingComparator<Method, Annotation>(
|
||||
new InstanceComparator<Annotation>(
|
||||
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
|
||||
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<>(
|
||||
comparator.addComparator(new ConvertingComparator<Method, String>(
|
||||
new Converter<Method, String>() {
|
||||
@Override
|
||||
public String convert(Method method) {
|
||||
return method.getName();
|
||||
}
|
||||
@@ -95,18 +90,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<>();
|
||||
final List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
@@ -132,9 +126,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
|
||||
final List<Method> methods = new LinkedList<>();
|
||||
final List<Method> methods = new LinkedList<Method>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
@@ -160,7 +153,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");
|
||||
@@ -171,20 +164,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,19 +184,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
if (aspectJAnnotation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
|
||||
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
|
||||
@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 +219,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 +248,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 +262,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synthetic advisor that instantiates the aspect.
|
||||
* Triggered by per-clause pointcut on non-singleton aspect.
|
||||
@@ -289,7 +272,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
|
||||
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
|
||||
@Override
|
||||
public void before(Method method, Object[] args, Object target) {
|
||||
// Simply instantiate the aspect
|
||||
aif.getAspectInstance();
|
||||
|
||||
+16
-10
@@ -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.
|
||||
@@ -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
|
||||
@@ -39,25 +40,30 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
|
||||
* @param aspectClass the aspect class
|
||||
* @param aspectName the aspect name
|
||||
*/
|
||||
public SimpleMetadataAwareAspectInstanceFactory(Class<?> aspectClass, String aspectName) {
|
||||
public SimpleMetadataAwareAspectInstanceFactory(Class aspectClass, String aspectName) {
|
||||
super(aspectClass);
|
||||
this.metadata = new AspectMetadata(aspectClass, aspectName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final AspectMetadata getAspectMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
-13
@@ -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,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;
|
||||
|
||||
@@ -50,19 +48,23 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final AspectMetadata getAspectMetadata() {
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
||||
+5
-7
@@ -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.
|
||||
@@ -46,7 +46,7 @@ import org.springframework.util.ClassUtils;
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
|
||||
|
||||
private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
|
||||
private static final Comparator DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
|
||||
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
|
||||
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
|
||||
new ArrayList<>(advisors.size());
|
||||
new ArrayList<PartiallyComparableAdvisorHolder>(advisors.size());
|
||||
for (Advisor element : advisors) {
|
||||
partiallyComparableAdvisors.add(
|
||||
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
|
||||
@@ -76,7 +76,7 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
List<PartiallyComparableAdvisorHolder> sorted =
|
||||
PartialOrder.sort(partiallyComparableAdvisors);
|
||||
if (sorted != null) {
|
||||
List<Advisor> result = new ArrayList<>(advisors.size());
|
||||
List<Advisor> result = new ArrayList<Advisor>(advisors.size());
|
||||
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
|
||||
result.add(pcAdvisor.getAdvisor());
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
|
||||
protected boolean shouldSkip(Class beanClass, String beanName) {
|
||||
// TODO: Consider optimization by caching the list of the aspect names
|
||||
List<Advisor> candidateAdvisors = findCandidateAdvisors();
|
||||
for (Advisor advisor : candidateAdvisors) {
|
||||
@@ -126,13 +126,11 @@ public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProx
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object obj) {
|
||||
Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
|
||||
return this.comparator.compare(this.advisor, otherAdvisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fallbackCompareTo(Object obj) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+25
-19
@@ -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
|
||||
@@ -46,15 +48,12 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
class AspectJPrecedenceComparator implements Comparator {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,11 +75,18 @@ class AspectJPrecedenceComparator implements Comparator<Advisor> {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compare(Advisor o1, Advisor o2) {
|
||||
int advisorPrecedence = this.advisorComparator.compare(o1, o2);
|
||||
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
|
||||
advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
|
||||
public int compare(Object o1, Object o2) {
|
||||
if (!(o1 instanceof Advisor && o2 instanceof Advisor)) {
|
||||
throw new IllegalArgumentException(
|
||||
"AspectJPrecedenceComparator can only compare the order of Advisors, " +
|
||||
"but was passed [" + o1 + "] and [" + o2 + "]");
|
||||
}
|
||||
|
||||
Advisor advisor1 = (Advisor) o1;
|
||||
Advisor advisor2 = (Advisor) o2;
|
||||
int advisorPrecedence = this.advisorComparator.compare(advisor1, advisor2);
|
||||
if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(advisor1, advisor2)) {
|
||||
advisorPrecedence = comparePrecedenceWithinAspect(advisor1, advisor2);
|
||||
}
|
||||
return advisorPrecedence;
|
||||
}
|
||||
|
||||
@@ -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
@@ -58,7 +58,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
|
||||
@Override
|
||||
public final BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definitionHolder, ParserContext parserContext) {
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
|
||||
|
||||
+1
-3
@@ -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
|
||||
@@ -91,7 +91,6 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.advisorBeanName;
|
||||
}
|
||||
@@ -111,7 +110,6 @@ public class AdvisorComponentDefinition extends AbstractComponentDefinition {
|
||||
return this.beanReferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return this.advisorDefinition.getSource();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -54,7 +54,7 @@ public abstract class AopConfigUtils {
|
||||
/**
|
||||
* Stores the auto proxy creator classes in escalation order.
|
||||
*/
|
||||
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();
|
||||
private static final List<Class> APC_PRIORITY_LIST = new ArrayList<Class>();
|
||||
|
||||
/**
|
||||
* Setup the escalation list.
|
||||
@@ -97,7 +97,7 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
|
||||
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
|
||||
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
|
||||
@@ -105,7 +105,7 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
|
||||
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
|
||||
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
|
||||
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
|
||||
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
|
||||
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
@@ -126,13 +126,13 @@ public abstract class AopConfigUtils {
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
private static int findPriorityForClass(Class<?> clazz) {
|
||||
private static int findPriorityForClass(Class clazz) {
|
||||
return APC_PRIORITY_LIST.indexOf(clazz);
|
||||
}
|
||||
|
||||
private static int findPriorityForClass(String className) {
|
||||
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
|
||||
Class<?> clazz = APC_PRIORITY_LIST.get(i);
|
||||
Class clazz = APC_PRIORITY_LIST.get(i);
|
||||
if (clazz.getName().equals(className)) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -59,7 +59,6 @@ public class AopNamespaceHandler extends NamespaceHandlerSupport {
|
||||
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
|
||||
* and '{@code scoped-proxy}' tags.
|
||||
*/
|
||||
@Override
|
||||
public void init() {
|
||||
// In 2.0 XSD as well as in 2.1 XSD.
|
||||
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -79,6 +79,28 @@ public abstract class AopNamespaceUtils {
|
||||
registerComponentIfNecessary(beanDefinition, parserContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Spring 2.5, in favor of
|
||||
* {@link #registerAutoProxyCreatorIfNecessary(ParserContext, Element)} and
|
||||
* {@link AopConfigUtils#registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry, Object)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Object source) {
|
||||
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
|
||||
parserContext.getRegistry(), source);
|
||||
registerComponentIfNecessary(beanDefinition, parserContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Spring 2.5, in favor of
|
||||
* {@link AopConfigUtils#forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
|
||||
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
|
||||
}
|
||||
|
||||
|
||||
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
|
||||
if (sourceElement != null) {
|
||||
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
|
||||
|
||||
+2
-3
@@ -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.
|
||||
@@ -37,7 +37,6 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
*/
|
||||
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
|
||||
extendBeanDefinition(element, parserContext);
|
||||
@@ -53,7 +52,7 @@ class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
|
||||
ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
|
||||
ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
|
||||
+8
-9
@@ -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.
|
||||
@@ -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
|
||||
@@ -95,7 +95,6 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
private ParseState parseState = new ParseState();
|
||||
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
CompositeComponentDefinition compositeDef =
|
||||
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
|
||||
@@ -123,7 +122,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 +131,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}.
|
||||
*/
|
||||
@@ -199,8 +198,8 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
try {
|
||||
this.parseState.push(new AspectEntry(aspectId, aspectName));
|
||||
List<BeanDefinition> beanDefinitions = new ArrayList<>();
|
||||
List<BeanReference> beanReferences = new ArrayList<>();
|
||||
List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
|
||||
List<BeanReference> beanReferences = new ArrayList<BeanReference>();
|
||||
|
||||
List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS);
|
||||
for (int i = METHOD_INDEX; i < declareParents.size(); i++) {
|
||||
@@ -405,7 +404,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
/**
|
||||
* Gets the advice implementation class corresponding to the supplied {@link Element}.
|
||||
*/
|
||||
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
|
||||
private Class getAdviceClass(Element adviceElement, ParserContext parserContext) {
|
||||
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
|
||||
if (BEFORE.equals(elementName)) {
|
||||
return AspectJMethodBeforeAdvice.class;
|
||||
@@ -428,7 +427,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) {
|
||||
|
||||
+2
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2009 the original author 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,7 +57,6 @@ public class MethodLocatingFactoryBean implements FactoryBean<Method>, BeanFacto
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (!StringUtils.hasText(this.targetBeanName)) {
|
||||
throw new IllegalArgumentException("Property 'targetBeanName' is required");
|
||||
@@ -66,7 +65,7 @@ public class MethodLocatingFactoryBean implements FactoryBean<Method>, BeanFacto
|
||||
throw new IllegalArgumentException("Property 'methodName' is required");
|
||||
}
|
||||
|
||||
Class<?> beanClass = beanFactory.getType(this.targetBeanName);
|
||||
Class beanClass = beanFactory.getType(this.targetBeanName);
|
||||
if (beanClass == null) {
|
||||
throw new IllegalArgumentException("Can't determine type of bean with name '" + this.targetBeanName + "'");
|
||||
}
|
||||
@@ -79,17 +78,14 @@ public class MethodLocatingFactoryBean implements FactoryBean<Method>, BeanFacto
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Method getObject() throws Exception {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Method> getObjectType() {
|
||||
return Method.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -46,7 +46,6 @@ public class PointcutComponentDefinition extends AbstractComponentDefinition {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.pointcutBeanName;
|
||||
}
|
||||
@@ -61,7 +60,6 @@ public class PointcutComponentDefinition extends AbstractComponentDefinition {
|
||||
return new BeanDefinition[] {this.pointcutDefinition};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return this.pointcutDefinition.getSource();
|
||||
}
|
||||
|
||||
+1
-2
@@ -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
|
||||
@@ -39,7 +39,6 @@ class ScopedProxyBeanDefinitionDecorator implements BeanDefinitionDecorator {
|
||||
private static final String PROXY_TARGET_CLASS = "proxy-target-class";
|
||||
|
||||
|
||||
@Override
|
||||
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
|
||||
boolean proxyTargetClass = true;
|
||||
if (node instanceof Element) {
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -47,7 +47,6 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
this.aspectBeanName = aspectBeanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
if (!StringUtils.hasText(this.aspectBeanName)) {
|
||||
@@ -60,12 +59,10 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
* Look up the aspect bean from the {@link BeanFactory} and returns it.
|
||||
* @see #setAspectBeanName
|
||||
*/
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
return this.beanFactory.getBean(this.aspectBeanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
@@ -75,7 +72,6 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
if (this.beanFactory.isSingleton(this.aspectBeanName) &&
|
||||
this.beanFactory.isTypeMatch(this.aspectBeanName, Ordered.class)) {
|
||||
|
||||
+1
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,6 @@ class SpringConfiguredBeanDefinitionParser implements BeanDefinitionParser {
|
||||
"org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect";
|
||||
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_CONFIGURER_ASPECT_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition();
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* Support package for declarative AOP configuration,
|
||||
* with XML schema being the primary configuration format.
|
||||
*
|
||||
*/
|
||||
package org.springframework.aop.config;
|
||||
|
||||
|
||||
+44
-75
@@ -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.
|
||||
@@ -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<>(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,23 +65,31 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
this.beforeExistingAdvisors = beforeExistingAdvisors;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof AopInfrastructureBean) {
|
||||
// Ignore AOP infrastructure such as scoped proxies.
|
||||
return bean;
|
||||
}
|
||||
|
||||
if (bean instanceof Advised) {
|
||||
Advised advised = (Advised) bean;
|
||||
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
|
||||
// Add our local Advisor to the existing proxy's Advisor chain...
|
||||
if (isEligible(bean, beanName)) {
|
||||
if (bean instanceof Advised) {
|
||||
Advised advised = (Advised) bean;
|
||||
if (this.beforeExistingAdvisors) {
|
||||
advised.addAdvisor(0, this.advisor);
|
||||
}
|
||||
@@ -78,49 +98,32 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEligible(bean, beanName)) {
|
||||
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
|
||||
else {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
return proxyFactory.getProxy(this.beanClassLoader);
|
||||
}
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
customizeProxyFactory(proxyFactory);
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
}
|
||||
|
||||
// No async proxy needed.
|
||||
return bean;
|
||||
else {
|
||||
// No async proxy needed.
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given bean is eligible for advising with this
|
||||
* post-processor's {@link Advisor}.
|
||||
* <p>Delegates to {@link #isEligible(Class)} for target class checking.
|
||||
* <p>Implements caching of {@code canApply} results per bean target class.
|
||||
* Can be overridden e.g. to specifically exclude certain beans by name.
|
||||
* <p>Note: Only called for regular bean instances but not for existing
|
||||
* proxy instances which implement {@link Advised} and allow for adding
|
||||
* the local {@link Advisor} to the existing proxy's {@link Advisor} chain.
|
||||
* For the latter, {@link #isEligible(Class)} is being called directly,
|
||||
* with the actual target class behind the existing proxy (as determined
|
||||
* by {@link AopUtils#getTargetClass(Object)}).
|
||||
* @param bean the bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @see #isEligible(Class)
|
||||
*/
|
||||
protected boolean isEligible(Object bean, String beanName) {
|
||||
return isEligible(bean.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given class is eligible for advising with this
|
||||
* post-processor's {@link Advisor}.
|
||||
* <p>Implements caching of {@code canApply} results per bean target class.
|
||||
* @param targetClass the class to check against
|
||||
* @see AopUtils#getTargetClass(Object)
|
||||
* @see AopUtils#canApply(Advisor, Class)
|
||||
*/
|
||||
protected boolean isEligible(Class<?> targetClass) {
|
||||
protected boolean isEligible(Object bean, String beanName) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
Boolean eligible = this.eligibleBeans.get(targetClass);
|
||||
if (eligible != null) {
|
||||
return eligible;
|
||||
@@ -130,38 +133,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
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2011 the original author 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;
|
||||
@@ -122,7 +122,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
this.proxyClassLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
if (this.proxyClassLoader == null) {
|
||||
this.proxyClassLoader = classLoader;
|
||||
@@ -130,7 +129,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (this.target == null) {
|
||||
throw new IllegalArgumentException("Property 'target' is required");
|
||||
@@ -173,8 +171,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
|
||||
}
|
||||
|
||||
postProcessProxyFactory(proxyFactory);
|
||||
|
||||
this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
|
||||
}
|
||||
|
||||
@@ -193,17 +189,7 @@ 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() {
|
||||
if (this.proxy == null) {
|
||||
throw new FactoryBeanNotInitializedException();
|
||||
@@ -211,7 +197,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
if (this.proxy != null) {
|
||||
return this.proxy.getClass();
|
||||
@@ -228,7 +213,6 @@ public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -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,45 +49,44 @@ 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();
|
||||
Class[] getProxiedInterfaces();
|
||||
|
||||
/**
|
||||
* Determine whether the given interface is proxied.
|
||||
* @param intf the interface to check
|
||||
*/
|
||||
boolean isInterfaceProxied(Class<?> intf);
|
||||
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-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.
|
||||
@@ -58,6 +58,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @see org.springframework.aop.framework.AopProxy
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
/** use serialVersionUID from Spring 2.0 for interoperability */
|
||||
@@ -87,13 +88,13 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Interfaces to be implemented by the proxy. Held in List to keep the order
|
||||
* of registration, to create JDK proxy with specified order of interfaces.
|
||||
*/
|
||||
private List<Class<?>> interfaces = new ArrayList<>();
|
||||
private List<Class> interfaces = new ArrayList<Class>();
|
||||
|
||||
/**
|
||||
* List of Advisors. If an Advice is added, it will be wrapped
|
||||
* in an Advisor before being added to this List.
|
||||
*/
|
||||
private List<Advisor> advisors = new LinkedList<>();
|
||||
private List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
|
||||
/**
|
||||
* Array updated on changes to the advisors list, which is easier
|
||||
@@ -113,7 +114,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);
|
||||
}
|
||||
@@ -122,7 +123,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Initialize the method cache.
|
||||
*/
|
||||
private void initMethodCache() {
|
||||
this.methodCache = new ConcurrentHashMap<>(32);
|
||||
this.methodCache = new ConcurrentHashMap<MethodCacheKey, List<Object>>(32);
|
||||
}
|
||||
|
||||
|
||||
@@ -136,12 +137,10 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
setTargetSource(new SingletonTargetSource(target));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTargetSource(TargetSource targetSource) {
|
||||
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetSource getTargetSource() {
|
||||
return this.targetSource;
|
||||
}
|
||||
@@ -159,21 +158,18 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @see #setTargetSource
|
||||
* @see #setTarget
|
||||
*/
|
||||
public void setTargetClass(Class<?> targetClass) {
|
||||
public void setTargetClass(Class targetClass) {
|
||||
this.targetSource = EmptyTargetSource.forClass(targetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetSource.getTargetClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreFiltered(boolean preFiltered) {
|
||||
this.preFiltered = preFiltered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreFiltered() {
|
||||
return this.preFiltered;
|
||||
}
|
||||
@@ -198,10 +194,10 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
/**
|
||||
* Set the interfaces to be proxied.
|
||||
*/
|
||||
public void setInterfaces(Class<?>... interfaces) {
|
||||
public void setInterfaces(Class[] interfaces) {
|
||||
Assert.notNull(interfaces, "Interfaces must not be null");
|
||||
this.interfaces.clear();
|
||||
for (Class<?> ifc : interfaces) {
|
||||
for (Class ifc : interfaces) {
|
||||
addInterface(ifc);
|
||||
}
|
||||
}
|
||||
@@ -210,7 +206,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Add a new proxied interface.
|
||||
* @param intf the additional interface to proxy
|
||||
*/
|
||||
public void addInterface(Class<?> intf) {
|
||||
public void addInterface(Class intf) {
|
||||
Assert.notNull(intf, "Interface must not be null");
|
||||
if (!intf.isInterface()) {
|
||||
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
|
||||
@@ -228,18 +224,16 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @return {@code true} if the interface was removed; {@code false}
|
||||
* if the interface was not found and hence could not be removed
|
||||
*/
|
||||
public boolean removeInterface(Class<?> intf) {
|
||||
public boolean removeInterface(Class intf) {
|
||||
return this.interfaces.remove(intf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getProxiedInterfaces() {
|
||||
return this.interfaces.toArray(new Class<?>[this.interfaces.size()]);
|
||||
public Class[] getProxiedInterfaces() {
|
||||
return this.interfaces.toArray(new Class[this.interfaces.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterfaceProxied(Class<?> intf) {
|
||||
for (Class<?> proxyIntf : this.interfaces) {
|
||||
public boolean isInterfaceProxied(Class intf) {
|
||||
for (Class proxyIntf : this.interfaces) {
|
||||
if (intf.isAssignableFrom(proxyIntf)) {
|
||||
return true;
|
||||
}
|
||||
@@ -248,18 +242,15 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Advisor[] getAdvisors() {
|
||||
return this.advisorArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdvisor(Advisor advisor) {
|
||||
int pos = this.advisors.size();
|
||||
addAdvisor(pos, advisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
|
||||
@@ -267,7 +258,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
addAdvisorInternal(pos, advisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAdvisor(Advisor advisor) {
|
||||
int index = indexOf(advisor);
|
||||
if (index == -1) {
|
||||
@@ -279,7 +269,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAdvisor(int index) throws AopConfigException {
|
||||
if (isFrozen()) {
|
||||
throw new AopConfigException("Cannot remove Advisor: Configuration is frozen.");
|
||||
@@ -303,13 +292,11 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
adviceChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Advisor advisor) {
|
||||
Assert.notNull(advisor, "Advisor must not be null");
|
||||
return this.advisors.indexOf(advisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException {
|
||||
Assert.notNull(a, "Advisor a must not be null");
|
||||
Assert.notNull(b, "Advisor b must not be null");
|
||||
@@ -322,6 +309,16 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all of the given advisors to this proxy configuration.
|
||||
* @param advisors the advisors to register
|
||||
* @deprecated as of Spring 3.0, in favor of {@link #addAdvisors}
|
||||
*/
|
||||
@Deprecated
|
||||
public void addAllAdvisors(Advisor[] advisors) {
|
||||
addAdvisors(Arrays.asList(advisors));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all of the given advisors to this proxy configuration.
|
||||
* @param advisors the advisors to register
|
||||
@@ -354,8 +351,8 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
private void validateIntroductionAdvisor(IntroductionAdvisor advisor) {
|
||||
advisor.validateInterfaces();
|
||||
// If the advisor passed validation, we can make the change.
|
||||
Class<?>[] ifcs = advisor.getInterfaces();
|
||||
for (Class<?> ifc : ifcs) {
|
||||
Class[] ifcs = advisor.getInterfaces();
|
||||
for (Class ifc : ifcs) {
|
||||
addInterface(ifc);
|
||||
}
|
||||
}
|
||||
@@ -391,7 +388,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAdvice(Advice advice) throws AopConfigException {
|
||||
int pos = this.advisors.size();
|
||||
addAdvice(pos, advice);
|
||||
@@ -400,7 +396,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
/**
|
||||
* Cannot add introductions this way unless the advice implements IntroductionInfo.
|
||||
*/
|
||||
@Override
|
||||
public void addAdvice(int pos, Advice advice) throws AopConfigException {
|
||||
Assert.notNull(advice, "Advice must not be null");
|
||||
if (advice instanceof IntroductionInfo) {
|
||||
@@ -417,7 +412,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAdvice(Advice advice) throws AopConfigException {
|
||||
int index = indexOf(advice);
|
||||
if (index == -1) {
|
||||
@@ -429,7 +423,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Advice advice) {
|
||||
Assert.notNull(advice, "Advice must not be null");
|
||||
for (int i = 0; i < this.advisors.size(); i++) {
|
||||
@@ -462,7 +455,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param adviceClass the advice class to check
|
||||
* @return the count of the interceptors of this class or subclasses
|
||||
*/
|
||||
public int countAdvicesOfType(Class<?> adviceClass) {
|
||||
public int countAdvicesOfType(Class adviceClass) {
|
||||
int count = 0;
|
||||
if (adviceClass != null) {
|
||||
for (Advisor advisor : this.advisors) {
|
||||
@@ -482,7 +475,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param targetClass the target class
|
||||
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
*/
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
|
||||
MethodCacheKey cacheKey = new MethodCacheKey(method);
|
||||
List<Object> cached = this.methodCache.get(cacheKey);
|
||||
if (cached == null) {
|
||||
@@ -506,7 +499,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* @param other the AdvisedSupport object to copy configuration from
|
||||
*/
|
||||
protected void copyConfigurationFrom(AdvisedSupport other) {
|
||||
copyConfigurationFrom(other, other.targetSource, new ArrayList<>(other.advisors));
|
||||
copyConfigurationFrom(other, other.targetSource, new ArrayList<Advisor>(other.advisors));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -520,7 +513,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
copyFrom(other);
|
||||
this.targetSource = targetSource;
|
||||
this.advisorChainFactory = other.advisorChainFactory;
|
||||
this.interfaces = new ArrayList<>(other.interfaces);
|
||||
this.interfaces = new ArrayList<Class>(other.interfaces);
|
||||
for (Advisor advisor : advisors) {
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
|
||||
@@ -561,7 +554,6 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toProxyConfigString() {
|
||||
return toString();
|
||||
}
|
||||
@@ -586,7 +578,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 +591,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-2014 the original author or authors.
|
||||
* Copyright 2002-2008 the original author 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,10 +32,10 @@ public interface AdvisorChainFactory {
|
||||
* for the given advisor chain configuration.
|
||||
* @param config the AOP configuration in the form of an Advised object
|
||||
* @param method the proxied method
|
||||
* @param targetClass the target class (may be {@code null} to indicate a proxy without
|
||||
* target object, in which case the method's declaring class is the next best option)
|
||||
* @param targetClass the target class
|
||||
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
*/
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(
|
||||
Advised config, Method method, Class targetClass);
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -46,7 +46,7 @@ public abstract class AopContext {
|
||||
* the controlling proxy configuration has been set to "true".
|
||||
* @see ProxyConfig#setExposeProxy
|
||||
*/
|
||||
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");
|
||||
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy");
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
public static Class[] completeProxiedInterfaces(AdvisedSupport advised) {
|
||||
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();
|
||||
Class targetClass = advised.getTargetClass();
|
||||
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];
|
||||
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;
|
||||
}
|
||||
@@ -154,8 +115,8 @@ public abstract class AopProxyUtils {
|
||||
* in the original order (never {@code null} or empty)
|
||||
* @see Advised
|
||||
*/
|
||||
public static Class<?>[] proxiedUserInterfaces(Object proxy) {
|
||||
Class<?>[] proxyInterfaces = proxy.getClass().getInterfaces();
|
||||
public static Class[] proxiedUserInterfaces(Object proxy) {
|
||||
Class[] proxyInterfaces = proxy.getClass().getInterfaces();
|
||||
int nonUserIfcCount = 0;
|
||||
if (proxy instanceof SpringProxy) {
|
||||
nonUserIfcCount++;
|
||||
@@ -163,10 +124,7 @@ public abstract class AopProxyUtils {
|
||||
if (proxy instanceof Advised) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
if (proxy instanceof DecoratingProxy) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - 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");
|
||||
return userInterfaces;
|
||||
@@ -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-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.
|
||||
@@ -25,20 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.AopInvocationException;
|
||||
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;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
import org.springframework.cglib.proxy.Dispatcher;
|
||||
@@ -47,7 +34,18 @@ import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy;
|
||||
import org.springframework.cglib.transform.impl.MemorySafeUndeclaredThrowableStrategy;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.AopInvocationException;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.SmartClassLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -81,7 +79,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @see DefaultAopProxyFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class CglibAopProxy implements AopProxy, Serializable {
|
||||
final class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
// Constants for CGLIB callback array indices
|
||||
private static final int AOP_PROXY = 0;
|
||||
@@ -94,18 +92,18 @@ 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<>();
|
||||
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<Class<?>, Boolean>();
|
||||
|
||||
|
||||
/** 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;
|
||||
@@ -148,12 +146,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getProxy() {
|
||||
return getProxy(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProxy(ClassLoader classLoader) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
|
||||
@@ -173,7 +169,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();
|
||||
@@ -185,22 +181,31 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
enhancer.setSuperclass(proxySuperClass);
|
||||
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
|
||||
enhancer.setInterceptDuringConstruction(false);
|
||||
|
||||
Callback[] callbacks = getCallbacks(rootClass);
|
||||
Class<?>[] types = new Class<?>[callbacks.length];
|
||||
enhancer.setCallbacks(callbacks);
|
||||
enhancer.setCallbackFilter(new ProxyCallbackFilter(
|
||||
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
|
||||
|
||||
Class<?>[] types = new Class[callbacks.length];
|
||||
for (int x = 0; x < types.length; x++) {
|
||||
types[x] = callbacks[x].getClass();
|
||||
}
|
||||
// fixedInterceptorMap only populated at this point, after getCallbacks call above
|
||||
enhancer.setCallbackFilter(new ProxyCallbackFilter(
|
||||
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
|
||||
enhancer.setCallbackTypes(types);
|
||||
|
||||
// Generate the proxy class and create a proxy instance.
|
||||
return createProxyClassAndInstance(enhancer, callbacks);
|
||||
Object proxy;
|
||||
if (this.constructorArgs != null) {
|
||||
proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
|
||||
}
|
||||
else {
|
||||
proxy = enhancer.create();
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
||||
catch (CodeGenerationException ex) {
|
||||
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
|
||||
@@ -220,14 +225,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
|
||||
enhancer.setInterceptDuringConstruction(false);
|
||||
enhancer.setCallbacks(callbacks);
|
||||
return (this.constructorArgs != null ?
|
||||
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
|
||||
enhancer.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the CGLIB {@link Enhancer}. Subclasses may wish to override this to return a custom
|
||||
* {@link Enhancer} implementation.
|
||||
@@ -240,11 +237,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 +249,16 @@ 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();
|
||||
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.");
|
||||
}
|
||||
}
|
||||
private void doValidateClass(Class<?> proxySuperClass) {
|
||||
Method[] methods = proxySuperClass.getMethods();
|
||||
for (Method method : methods) {
|
||||
if (!Object.class.equals(method.getDeclaringClass()) && Modifier.isFinal(method.getModifiers())) {
|
||||
logger.warn("Unable to proxy method [" + method + "] because it is final: " +
|
||||
"All calls to this method via a proxy will be routed directly to the proxy.");
|
||||
}
|
||||
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,13 +290,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;
|
||||
@@ -322,9 +307,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (isStatic && isFrozen) {
|
||||
Method[] methods = rootClass.getMethods();
|
||||
Callback[] fixedCallbacks = new Callback[methods.length];
|
||||
this.fixedInterceptorMap = new HashMap<>(methods.length);
|
||||
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
|
||||
|
||||
// TODO: small memory optimisation here (can skip creation for methods with no advice)
|
||||
// TODO: small memory optimisation here (can skip creation for
|
||||
// methods with no advice)
|
||||
for (int x = 0; x < methods.length; x++) {
|
||||
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
|
||||
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
|
||||
@@ -351,15 +337,16 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
private static Object processReturnType(Object proxy, Object target, Method method, Object retVal) {
|
||||
// Massage return value if necessary
|
||||
if (retVal != null && retVal == target && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this". Note that we can't help
|
||||
// if the target sets a reference to itself in another returned object.
|
||||
if (retVal != null && retVal == target &&
|
||||
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this".
|
||||
// Note that we can't help if the target sets a reference
|
||||
// to itself in another returned object.
|
||||
retVal = proxy;
|
||||
}
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
|
||||
throw new AopInvocationException(
|
||||
"Null return value from advice does not match primitive return type for: " + method);
|
||||
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
@@ -399,7 +386,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object retVal = methodProxy.invoke(this.target, args);
|
||||
return processReturnType(proxy, this.target, method, retVal);
|
||||
@@ -419,7 +405,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object oldProxy = null;
|
||||
try {
|
||||
@@ -447,7 +432,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.targetSource = targetSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object target = this.targetSource.getTarget();
|
||||
try {
|
||||
@@ -472,7 +456,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.targetSource = targetSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object oldProxy = null;
|
||||
Object target = this.targetSource.getTarget();
|
||||
@@ -502,7 +485,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object loadObject() {
|
||||
return this.target;
|
||||
}
|
||||
@@ -520,7 +502,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.advised = advised;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object loadObject() throws Exception {
|
||||
return this.advised;
|
||||
}
|
||||
@@ -539,7 +520,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.advised = advised;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
|
||||
Object other = args[0];
|
||||
if (proxy == other) {
|
||||
@@ -572,7 +552,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.advised = advised;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) {
|
||||
return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
|
||||
}
|
||||
@@ -596,7 +575,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
MethodInvocation invocation = new CglibMethodInvocation(proxy, this.target, method, args,
|
||||
this.targetClass, this.adviceChain, methodProxy);
|
||||
@@ -614,13 +592,12 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
|
||||
|
||||
private final AdvisedSupport advised;
|
||||
private AdvisedSupport advised;
|
||||
|
||||
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
|
||||
this.advised = advised;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
|
||||
Object oldProxy = null;
|
||||
boolean setProxyContext = false;
|
||||
@@ -632,8 +609,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
setProxyContext = true;
|
||||
}
|
||||
// May be null. Get as late as possible to minimize the time we
|
||||
// "own" the target, in case it comes from a pool...
|
||||
// May be null Get as late as possible to minimize the time we
|
||||
// "own" the target, in case it comes from a pool.
|
||||
target = getTarget();
|
||||
if (target != null) {
|
||||
targetClass = target.getClass();
|
||||
@@ -647,8 +624,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...
|
||||
@@ -700,14 +676,13 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
private final MethodProxy methodProxy;
|
||||
|
||||
private final boolean publicMethod;
|
||||
private boolean protectedMethod;
|
||||
|
||||
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());
|
||||
this.protectedMethod = Modifier.isProtected(method.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -716,11 +691,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeJoinpoint() throws Throwable {
|
||||
if (this.publicMethod) {
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
if (this.protectedMethod) {
|
||||
return super.invokeJoinpoint();
|
||||
}
|
||||
else {
|
||||
return super.invokeJoinpoint();
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,7 +754,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* DynamicUnadvisedInterceptor already considers this.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
@Override
|
||||
public int accept(Method method) {
|
||||
if (AopUtils.isFinalizeMethod(method)) {
|
||||
logger.debug("Found finalize() method - using NO_OVERRIDE");
|
||||
@@ -824,7 +798,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);
|
||||
}
|
||||
@@ -840,8 +815,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// of the target type. If so we know it never needs to have return type
|
||||
// massage and can use a dispatcher.
|
||||
// If the proxy is being exposed, then must use the interceptor the
|
||||
// correct one is already configured. If the target is not static, then
|
||||
// cannot use a dispatcher because the target cannot be released.
|
||||
// correct one is already configured. If the target is not static cannot
|
||||
// use a Dispatcher because the target can not then be released.
|
||||
if (exposeProxy || !isStatic) {
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
@@ -873,7 +848,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof ProxyCallbackFilter)) {
|
||||
@@ -922,7 +897,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 +926,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-14
@@ -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.
|
||||
@@ -46,25 +46,22 @@ import org.springframework.aop.support.MethodMatchers;
|
||||
@SuppressWarnings("serial")
|
||||
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
|
||||
|
||||
@Override
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
|
||||
Advised config, Method method, Class<?> targetClass) {
|
||||
Advised config, Method method, Class targetClass) {
|
||||
|
||||
// This is somewhat tricky... We have to process introductions first,
|
||||
// This is somewhat tricky... we have to process introductions first,
|
||||
// but we need to preserve order in the ultimate list.
|
||||
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
|
||||
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
|
||||
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
|
||||
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
|
||||
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
|
||||
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
|
||||
|
||||
for (Advisor advisor : config.getAdvisors()) {
|
||||
if (advisor instanceof PointcutAdvisor) {
|
||||
// Add it conditionally.
|
||||
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
|
||||
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
|
||||
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
|
||||
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
|
||||
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
|
||||
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
|
||||
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
|
||||
if (mm.isRuntime()) {
|
||||
// Creating a new object instance in the getInterceptors() method
|
||||
// isn't a problem as we normally cache created chains.
|
||||
@@ -80,7 +77,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
}
|
||||
else if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
|
||||
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
|
||||
Interceptor[] interceptors = registry.getInterceptors(advisor);
|
||||
interceptorList.addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
@@ -90,19 +87,18 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
interceptorList.addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
}
|
||||
|
||||
return interceptorList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the Advisors contain matching introductions.
|
||||
*/
|
||||
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
|
||||
private static boolean hasMatchingIntroductions(Advised config, Class targetClass) {
|
||||
for (int i = 0; i < config.getAdvisors().length; i++) {
|
||||
Advisor advisor = config.getAdvisors()[i];
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (ia.getClassFilter().matches(actualClass)) {
|
||||
if (ia.getClassFilter().matches(targetClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-15
@@ -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,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
|
||||
@@ -46,18 +48,18 @@ import org.springframework.aop.SpringProxy;
|
||||
@SuppressWarnings("serial")
|
||||
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
|
||||
|
||||
@Override
|
||||
|
||||
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
|
||||
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
|
||||
Class<?> targetClass = config.getTargetClass();
|
||||
Class targetClass = config.getTargetClass();
|
||||
if (targetClass == null) {
|
||||
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);
|
||||
return CglibProxyFactory.createCglibProxy(config);
|
||||
}
|
||||
else {
|
||||
return new JdkDynamicAopProxy(config);
|
||||
@@ -70,8 +72,20 @@ 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])));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner factory class used to just introduce a CGLIB dependency
|
||||
* when actually creating a CGLIB proxy.
|
||||
*/
|
||||
private static class CglibProxyFactory {
|
||||
|
||||
public static AopProxy createCglibProxy(AdvisedSupport advisedSupport) {
|
||||
return new CglibAopProxy(advisedSupport);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-22
@@ -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.
|
||||
@@ -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;
|
||||
|
||||
@@ -76,7 +75,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
*/
|
||||
|
||||
/** We use a static Log to avoid serialization issues */
|
||||
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
|
||||
private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
|
||||
|
||||
/** Config used to configure this proxy */
|
||||
private final AdvisedSupport advised;
|
||||
@@ -107,17 +106,15 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getProxy() {
|
||||
return getProxy(ClassUtils.getDefaultClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProxy(ClassLoader classLoader) {
|
||||
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);
|
||||
}
|
||||
@@ -127,8 +124,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
* on the supplied set of interfaces.
|
||||
* @param proxiedInterfaces the interfaces to introspect
|
||||
*/
|
||||
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
|
||||
for (Class<?> proxiedInterface : proxiedInterfaces) {
|
||||
private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {
|
||||
for (Class proxiedInterface : proxiedInterfaces) {
|
||||
Method[] methods = proxiedInterface.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (AopUtils.isEqualsMethod(method)) {
|
||||
@@ -150,14 +147,13 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
* <p>Callers will see exactly the exception thrown by the target,
|
||||
* unless a hook method throws an exception.
|
||||
*/
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
MethodInvocation invocation;
|
||||
Object oldProxy = null;
|
||||
boolean setProxyContext = false;
|
||||
|
||||
TargetSource targetSource = this.advised.targetSource;
|
||||
Class<?> targetClass = null;
|
||||
Class targetClass = null;
|
||||
Object target = null;
|
||||
|
||||
try {
|
||||
@@ -165,15 +161,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 +195,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...
|
||||
@@ -221,10 +212,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// is type-compatible. Note that we can't help if the target sets
|
||||
// a reference to itself in another returned object.
|
||||
retVal = proxy;
|
||||
}
|
||||
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
|
||||
throw new AopInvocationException(
|
||||
"Null return value from advice does not match primitive return type for: " + method);
|
||||
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
|
||||
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
-91
@@ -1,91 +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.springframework.aop.framework;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
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.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* 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")
|
||||
class ObjenesisCglibAopProxy extends CglibAopProxy {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ObjenesisCglibAopProxy.class);
|
||||
|
||||
private static final SpringObjenesis objenesis = new SpringObjenesis();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ObjenesisCglibAopProxy for the given AOP configuration.
|
||||
* @param config the AOP configuration as AdvisedSupport object
|
||||
*/
|
||||
public ObjenesisCglibAopProxy(AdvisedSupport config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
if (proxyInstance == null) {
|
||||
// Regular instantiation via default constructor...
|
||||
try {
|
||||
Constructor<?> ctor = (this.constructorArgs != null ?
|
||||
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
|
||||
proxyClass.getDeclaredConstructor());
|
||||
ReflectionUtils.makeAccessible(ctor);
|
||||
proxyInstance = (this.constructorArgs != null ?
|
||||
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
|
||||
"and regular proxy instantiation via default constructor fails as well", ex);
|
||||
}
|
||||
}
|
||||
|
||||
((Factory) proxyInstance).setCallbacks(callbacks);
|
||||
return proxyInstance;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user