mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
4.3.x
..
v3.2.0.RC2
| Author | SHA1 | Date | |
|---|---|---|---|
| 25db8f2ca7 |
+6
-18
@@ -4,36 +4,24 @@
|
||||
.DS_Store
|
||||
.settings
|
||||
.springBeans
|
||||
target
|
||||
bin
|
||||
build.sh
|
||||
integration-repo
|
||||
ivy-cache
|
||||
jxl.log
|
||||
jmx.log
|
||||
derby.log
|
||||
spring-jdbc/derby.log
|
||||
spring-test/test-output/
|
||||
.gradle
|
||||
argfile*
|
||||
pom.xml
|
||||
activemq-data/
|
||||
|
||||
/build
|
||||
buildSrc/build
|
||||
/spring-*/build
|
||||
/src/asciidoc/build
|
||||
target/
|
||||
|
||||
# Eclipse artifacts, including WTP generated manifests
|
||||
build
|
||||
.classpath
|
||||
.project
|
||||
spring-*/src/main/java/META-INF/MANIFEST.MF
|
||||
argfile*
|
||||
pom.xml
|
||||
|
||||
# IDEA artifacts and output dirs
|
||||
# IDEA metadata and output dirs
|
||||
*.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
|
||||
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
https://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 https://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
|
||||
https://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
|
||||
* https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[Asciidoctor Quick Reference]
|
||||
* https://asciidoctor.org/docs/user-manual/[Asciidoctor Manual]
|
||||
* https://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoctor Writers Guide]
|
||||
|
||||
+98
-110
@@ -1,107 +1,103 @@
|
||||
_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 Individual Contributor License Agreement (ICLA)
|
||||
If you're considering anything more than correcting a typo or fixing a minor
|
||||
bug, please discuss it on the [spring-framework-contrib][] mailing list before
|
||||
submitting a pull request. We're happy to provide guidance but please spend an
|
||||
hour or two researching the subject on your own including searching the mailing
|
||||
list for prior discussions.
|
||||
|
||||
## Sign the Contributor License Agreement
|
||||
|
||||
If you have not previously done so, please fill out and submit the
|
||||
[Spring ICLA form][]. You'll receive a token when this process is complete.
|
||||
Keep track of this; you may be asked for it later!
|
||||
[SpringSource CLA form][]. You'll receive a token when this process is complete.
|
||||
Keep track of this, you may be asked for it later!
|
||||
|
||||
Note that emailing/postal mailing a signed copy is _not_ necessary. Submission
|
||||
of the web form is all that is required.
|
||||
|
||||
Once you've completed the web form, simply add the following in a comment on
|
||||
When you've completed the web form, simply add the following in a comment on
|
||||
your pull request:
|
||||
|
||||
I have signed and agree to the terms of the Spring Individual Contributor
|
||||
License Agreement.
|
||||
I have signed and agree to the terms of the SpringSource Individual
|
||||
Contributor License Agreement.
|
||||
|
||||
You do not need to include your token/id. Please add the above statement to all
|
||||
future pull requests as well, simply so that the Spring Framework team knows
|
||||
You do not need to include your token/id. Please add the statement above to all
|
||||
future pull requests as well, simply so the Spring Framework team knows
|
||||
immediately that this process is complete.
|
||||
|
||||
## Create a Branch
|
||||
|
||||
### Branch from `master`
|
||||
## Create your branch from `master`
|
||||
|
||||
Master currently represents work toward Spring Framework 4.0. Please submit
|
||||
all pull requests there, even bug fixes and minor improvements. Backports to
|
||||
`3.2.x` will be considered on a case-by-case basis.
|
||||
At any given time, Spring Framework's `master` branch represents the version
|
||||
currently under development. For example, if 3.1.1 was the latest Spring
|
||||
Framework release, `master` represents 3.2.0 development, and the `3.1.x`
|
||||
branch represents 3.1.2 development.
|
||||
|
||||
Create your topic branch to be submitted as a pull request from `master`. The
|
||||
Spring team will consider your pull request for backporting to maintenance
|
||||
versions (e.g. 3.1.2) on a case-by-case basis; you don't need to worry about
|
||||
submitting anything for backporting.
|
||||
|
||||
|
||||
### Use short branch names
|
||||
## 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.
|
||||
|
||||
1. Tabs, not spaces
|
||||
1. Unix (LF), not DOS (CRLF) line endings
|
||||
1. Unix (LF), not dos (CRLF) line endings
|
||||
1. Eliminate all trailing whitespace
|
||||
1. Wrap Javadoc at 90 characters
|
||||
1. Aim to wrap code at 90 characters, but favor readability over wrapping
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. UTF-8 encoding for Java sources
|
||||
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-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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -113,44 +109,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 2012 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 2012 appropriately
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 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;
|
||||
@@ -175,15 +167,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:
|
||||
@@ -191,30 +183,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):
|
||||
@@ -238,34 +230,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. Mention associated JIRA issue(s) at the end of the commit comment, prefixed
|
||||
with "Issue: " as above.
|
||||
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
|
||||
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:
|
||||
|
||||
@@ -277,10 +267,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
|
||||
@@ -288,12 +278,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,
|
||||
@@ -305,15 +295,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/send-pull-requests
|
||||
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
|
||||
[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
|
||||
[Spring ICLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[SpringSource CLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
|
||||
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
|
||||
[Rewriting History section of Pro Git]: https://git-scm.com/book/en/Git-Tools-Rewriting-History
|
||||
[Commit Guidelines section of Pro Git]: https://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]: https://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]: https://docs.spring.io/spring-framework/docs/current/javadoc-api/
|
||||
[reference docs]: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
|
||||
[spring tags]: https://spring.io/questions
|
||||
[Stack Overflow]: https://stackoverflow.com/faq
|
||||
[Commercial support]: https://spring.io/services
|
||||
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
|
||||
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[Gradle]: https://gradle.org
|
||||
[`./gradlew`]: https://vimeo.com/34436402
|
||||
[Git]: https://help.github.com/set-up-git-redirect
|
||||
[JDK8 build]: https://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/send-pull-requests
|
||||
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@SpringFramework]: https://twitter.com/springframework
|
||||
[@SpringCentral]: https://twitter.com/springcentral
|
||||
[team members]: https://twitter.com/springframework/lists/team/members
|
||||
[The Spring Blog]: https://spring.io/blog/
|
||||
[news feed]: https://spring.io/blog/category/news
|
||||
[Apache License]: https://www.apache.org/licenses/LICENSE-2.0
|
||||
[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://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
|
||||
[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
|
||||
|
||||
+768
-1288
File diff suppressed because it is too large
Load Diff
-158
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.gradle
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that detects identically named, non-empty packages split across multiple
|
||||
* subprojects, e.g. "org.springframework.context.annotation" existing in both spring-core
|
||||
* and spring-aspects. Adds a 'detectSplitPackages' task to the current project's task
|
||||
* collection. If the project already contains a 'check' task (i.e. is a typical Gradle
|
||||
* project with the "java" plugin applied), the 'check' task will be updated to depend on
|
||||
* the execution of 'detectSplitPackages'.
|
||||
*
|
||||
* By default, all subprojects will be scanned. Use the 'projectsToScan' task property to
|
||||
* modify this value. Example usage:
|
||||
*
|
||||
* apply plugin: 'detect-split-packages // typically applied to root project
|
||||
*
|
||||
* detectSplitPackages {
|
||||
* packagesToScan -= project(":spring-xyz") // scan every project but spring-xyz
|
||||
* }
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Glyn Normington
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class DetectSplitPackagesPlugin implements Plugin<Project> {
|
||||
public void apply(Project project) {
|
||||
def tasks = project.tasks
|
||||
Task detectSplitPackages = tasks.create("detectSplitPackages", DetectSplitPackagesTask.class)
|
||||
if (tasks.asMap.containsKey("check")) {
|
||||
tasks.getByName("check").dependsOn detectSplitPackages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DetectSplitPackagesTask extends DefaultTask {
|
||||
|
||||
private static final String JAVA_FILE_SUFFIX = ".java"
|
||||
private static final String PACKAGE_SEPARATOR = "."
|
||||
private static final String HIDDEN_DIRECTORY_PREFIX = "."
|
||||
|
||||
@Input
|
||||
Set<Project> projectsToScan = project.subprojects
|
||||
|
||||
public DetectSplitPackagesTask() {
|
||||
this.group = "Verification"
|
||||
this.description = "Detects packages split across two or more subprojects."
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void detectSplitPackages() {
|
||||
def splitPackages = doDetectSplitPackages()
|
||||
if (!splitPackages.isEmpty()) {
|
||||
def message = "The following split package(s) have been detected:\n"
|
||||
splitPackages.each { pkg, mod ->
|
||||
message += " - ${pkg} (split across ${mod[0].name} and ${mod[1].name})\n"
|
||||
}
|
||||
throw new GradleException(message)
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<Project>> doDetectSplitPackages() {
|
||||
def splitPackages = [:]
|
||||
def mergedProjects = findMergedProjects()
|
||||
def packagesByProject = mapPackagesByProject()
|
||||
|
||||
def projects = packagesByProject.keySet().toArray()
|
||||
def nProjects = projects.length
|
||||
|
||||
for (int i = 0; i < nProjects - 1; i++) {
|
||||
for (int j = i + 1; j < nProjects - 1; j++) {
|
||||
def prj_i = projects[i]
|
||||
def prj_j = projects[j]
|
||||
|
||||
def pkgs_i = new HashSet(packagesByProject.get(prj_i))
|
||||
def pkgs_j = packagesByProject.get(prj_j)
|
||||
pkgs_i.retainAll(pkgs_j)
|
||||
|
||||
if (!pkgs_i.isEmpty()
|
||||
&& mergedProjects.get(prj_i) != prj_j
|
||||
&& mergedProjects.get(prj_j) != prj_i) {
|
||||
pkgs_i.each { pkg ->
|
||||
def readablePkg = pkg.substring(1).replaceAll(File.separator, PACKAGE_SEPARATOR)
|
||||
splitPackages[readablePkg] = [prj_i, prj_j]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return splitPackages;
|
||||
}
|
||||
|
||||
private Map<Project, Set<String>> mapPackagesByProject() {
|
||||
def packagesByProject = [:]
|
||||
this.projectsToScan.each { Project p ->
|
||||
def packages = new HashSet<String>()
|
||||
p.sourceSets.main.java.srcDirs.each { File dir ->
|
||||
findPackages(packages, dir, "")
|
||||
}
|
||||
if (!packages.isEmpty()) {
|
||||
packagesByProject.put(p, packages)
|
||||
}
|
||||
}
|
||||
return packagesByProject;
|
||||
}
|
||||
|
||||
private Map<Project, Project> findMergedProjects() {
|
||||
def mergedProjects = [:]
|
||||
this.projectsToScan.findAll { p ->
|
||||
p.plugins.findPlugin(MergePlugin)
|
||||
}.findAll { p ->
|
||||
p.merge.into
|
||||
}.each { p ->
|
||||
mergedProjects.put(p, p.merge.into)
|
||||
}
|
||||
return mergedProjects
|
||||
}
|
||||
|
||||
private static void findPackages(Set<String> packages, File dir, String packagePath) {
|
||||
def scanDir = new File(dir, packagePath)
|
||||
def File[] javaFiles = scanDir.listFiles({ file ->
|
||||
!file.isDirectory() && file.name.endsWith(JAVA_FILE_SUFFIX)
|
||||
} as FileFilter)
|
||||
|
||||
if (javaFiles != null && javaFiles.length != 0) {
|
||||
packages.add(packagePath)
|
||||
}
|
||||
|
||||
scanDir.listFiles({ File file ->
|
||||
file.isDirectory() && !file.name.startsWith(HIDDEN_DIRECTORY_PREFIX)
|
||||
} as FileFilter).each { File subDir ->
|
||||
findPackages(packages, dir, packagePath + File.separator + subDir.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.gradle
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
|
||||
import org.gradle.api.plugins.MavenPlugin
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
import org.gradle.api.invocation.*
|
||||
|
||||
/**
|
||||
* Gradle plugin that allows projects to merged together. Primarily developed to
|
||||
* allow Spring to support multiple incompatible versions of third-party
|
||||
* dependencies (for example Hibernate v3 and v4).
|
||||
* <p>
|
||||
* The 'merge' extension should be used to define how projects are merged, for example:
|
||||
* <pre class="code">
|
||||
* configure(subprojects) {
|
||||
* apply plugin: MergePlugin
|
||||
* }
|
||||
*
|
||||
* project("myproject") {
|
||||
* }
|
||||
*
|
||||
* project("myproject-extra") {
|
||||
* merge.into = project("myproject")
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* This plugin adds two new configurations:
|
||||
* <ul>
|
||||
* <li>merging - Contains the projects being merged into this project<li>
|
||||
* <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
|
||||
* to allow an IDE to reference merge projects.</li>
|
||||
* <ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MergePlugin implements Plugin<Project> {
|
||||
|
||||
private static boolean attachedProjectsEvaluated;
|
||||
|
||||
public void apply(Project project) {
|
||||
project.plugins.apply(MavenPlugin)
|
||||
project.plugins.apply(EclipsePlugin)
|
||||
project.plugins.apply(IdeaPlugin)
|
||||
|
||||
MergeModel model = project.extensions.create("merge", MergeModel)
|
||||
project.configurations.create("merging")
|
||||
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
|
||||
|
||||
// Ensure the IDE can reference merged projects
|
||||
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
|
||||
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
if (it.merge.into != null) {
|
||||
setup(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to build runtimeMerge dependencies
|
||||
if (!attachedProjectsEvaluated) {
|
||||
project.gradle.projectsEvaluated{
|
||||
postProcessProjects(it)
|
||||
}
|
||||
attachedProjectsEvaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(Project project) {
|
||||
project.merge.into.dependencies.add("merging", project)
|
||||
project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
|
||||
project.dependencies.add("runtimeMerge", project.merge.into)
|
||||
setupTaskDependencies(project)
|
||||
setupMaven(project)
|
||||
}
|
||||
|
||||
private void setupTaskDependencies(Project project) {
|
||||
// invoking a task will invoke the task with the same name on 'into' project
|
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
|
||||
def task = project.tasks.findByPath(it)
|
||||
if (task) {
|
||||
task.enabled = false
|
||||
task.dependsOn(project.merge.into.tasks.findByPath(it))
|
||||
}
|
||||
}
|
||||
|
||||
// update 'into' project artifacts to contain the source artifact contents
|
||||
project.merge.into.sourcesJar.from(project.sourcesJar.source)
|
||||
project.merge.into.jar.from(project.sourceSets.main.output)
|
||||
project.merge.into.javadoc {
|
||||
source += project.javadoc.source
|
||||
classpath += project.javadoc.classpath
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMaven(Project project) {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if (mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.create(
|
||||
project.name + "-" + configuration.name)
|
||||
configuration.excludeRules.each {
|
||||
configuration.exclude([
|
||||
(ExcludeRule.GROUP_KEY) : it.group,
|
||||
(ExcludeRule.MODULE_KEY) : it.module])
|
||||
}
|
||||
configuration.dependencies.each {
|
||||
def intoCompile = project.merge.into.configurations.getByName("compile")
|
||||
// Protect against changing a compile scope dependency (SPR-10218)
|
||||
if (!intoCompile.dependencies.contains(it)) {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100 + index, intoConfiguration, mapping.scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private postProcessProjects(Gradle gradle) {
|
||||
gradle.allprojects(new Action<Project>() {
|
||||
public void execute(Project project) {
|
||||
project.configurations.getByName("runtime").allDependencies.withType(ProjectDependency).each{
|
||||
Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
|
||||
dependsOnMergedFrom.dependencies.each{ dep ->
|
||||
project.dependencies.add("runtimeMerge", dep.dependencyProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class MergeModel {
|
||||
Project into;
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.build.gradle
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
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.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class TestSourceSetDependenciesPlugin implements Plugin<Project> {
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.afterEvaluate {
|
||||
Set<ProjectDependency> projectDependencies = new LinkedHashSet<ProjectDependency>()
|
||||
collectProjectDependencies(projectDependencies, project)
|
||||
projectDependencies.each {
|
||||
project.dependencies.add("testCompile", it.dependencyProject.sourceSets.test.output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
|
||||
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
|
||||
Configuration configuration = project.getConfigurations().findByName(configurationName)
|
||||
if (configuration) {
|
||||
configuration.dependencies.findAll { it instanceof ProjectDependency }.each {
|
||||
projectDependencies.add(it)
|
||||
collectProjectDependencies(projectDependencies, it.dependencyProject)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin
|
||||
@@ -1 +0,0 @@
|
||||
implementation-class=org.springframework.build.gradle.MergePlugin
|
||||
-1
@@ -1 +0,0 @@
|
||||
implementation-class=org.springframework.build.gradle.TestSourceSetDependenciesPlugin
|
||||
+2
-1
@@ -1 +1,2 @@
|
||||
version=4.3.31.BUILD-SNAPSHOT
|
||||
previousVersion=3.2.0.RC1
|
||||
version=3.2.0.RC2
|
||||
|
||||
+22
-110
@@ -1,114 +1,26 @@
|
||||
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
||||
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)
|
||||
// https://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) {
|
||||
def projectName = matcher[0][1]
|
||||
def path = "/${projectName}"
|
||||
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
||||
def dependency = new ProjectDependency(path)
|
||||
dependency.exported = true
|
||||
classpath.entries.add(dependency)
|
||||
}
|
||||
classpath.entries.remove(entry)
|
||||
}
|
||||
}
|
||||
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
||||
}
|
||||
// servlet-api (2.5) and tomcat-servlet-api (3.0) classpath entries should not be
|
||||
// exported to dependent projects in Eclipse to avoid false compilation errors due
|
||||
// to changing APIs across these versions
|
||||
classpath.entries.findAll { entry -> entry.path.contains('servlet-api') }*.exported = false
|
||||
|
||||
|
||||
// Use separate main/test outputs (prevents WTP from packaging test classes)
|
||||
eclipse.classpath.defaultOutputDir = file(project.name+"/bin/eclipse")
|
||||
eclipse.classpath.file.beforeMerged { classpath ->
|
||||
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||
if(it.output.startsWith("bin/")) {
|
||||
it.output = null
|
||||
}
|
||||
}
|
||||
}
|
||||
eclipse.classpath.file.whenMerged { classpath ->
|
||||
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||
it.output = "bin/" + it.path.split("/")[1]
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
|
||||
|
||||
// Include project specific settings
|
||||
task eclipseSettings(type: Copy) {
|
||||
from rootProject.files(
|
||||
"src/eclipse/org.eclipse.jdt.ui.prefs",
|
||||
"src/eclipse/org.eclipse.wst.common.project.facet.core.xml")
|
||||
into project.file('.settings/')
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
task eclipseWstComponent(type: Copy) {
|
||||
from rootProject.files(
|
||||
"src/eclipse/org.eclipse.wst.common.component")
|
||||
into project.file('.settings/')
|
||||
expand(deployname: project.name)
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
task eclipseJdtPrepare(type: Copy) {
|
||||
from rootProject.file("src/eclipse/org.eclipse.jdt.core.prefs")
|
||||
into project.file(".settings/")
|
||||
outputs.upToDateWhen { false }
|
||||
}
|
||||
|
||||
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(".settings/org.eclipse.wst.common.component")
|
||||
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
|
||||
}
|
||||
|
||||
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
|
||||
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
|
||||
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||
|
||||
|
||||
// Filter 'build' folder
|
||||
eclipse.project.file.withXml {
|
||||
def node = it.asNode()
|
||||
|
||||
def filteredResources = node.get("filteredResources")
|
||||
if(filteredResources) {
|
||||
node.remove(filteredResources)
|
||||
}
|
||||
def filterNode = node.appendNode("filteredResources").appendNode("filter")
|
||||
filterNode.appendNode("id", "1359048889071")
|
||||
filterNode.appendNode("name", "")
|
||||
filterNode.appendNode("type", "30")
|
||||
def matcherNode = filterNode.appendNode("matcher")
|
||||
matcherNode.appendNode("id", "org.eclipse.ui.ide.multiFilter")
|
||||
matcherNode.appendNode("arguments", "1.0-projectRelativePath-matches-false-false-build")
|
||||
}
|
||||
// GRADLE-1116
|
||||
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) {
|
||||
def projectName = matcher[0][1]
|
||||
def path = "/${projectName}"
|
||||
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
|
||||
def dependency = new ProjectDependency(path, project(":${projectName}").path)
|
||||
dependency.exported = true
|
||||
classpath.entries.add(dependency)
|
||||
}
|
||||
classpath.entries.remove(entry)
|
||||
}
|
||||
}
|
||||
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
||||
}
|
||||
+54
-55
@@ -2,74 +2,73 @@
|
||||
* Generate a JDiff report between the current version and an older version.
|
||||
*
|
||||
* Usage:
|
||||
* gradle jdiff -D OLD_VERSION=3.1.3.RELEASE -D OLD_VERSION_ROOT=/path/to/3.1.3.RELEASE
|
||||
* gradle jdiff [-D OLD_VERSION=3.1.3.RELEASE] -D OLD_VERSION_ROOT=/path/to/3.1.3.RELEASE
|
||||
*
|
||||
* View generated report at:
|
||||
* build/reports/jdiff/changes.html
|
||||
*
|
||||
* @param OLD_VERSION required
|
||||
* @param OLD_VERSION optional, defaulting to value of `previousVersion` in gradle.properties
|
||||
* @param OLD_VERSION_ROOT required, typically pointing to a separate git clone dir
|
||||
*/
|
||||
task jdiff {
|
||||
description = "Generates a JDiff report"
|
||||
group = "Documentation"
|
||||
description = 'Generates a JDiff report'
|
||||
group = 'Documentation'
|
||||
|
||||
def jdiffHome = "${rootProject.rootDir}/gradle/jdiff"
|
||||
def jdiffHome = "${rootProject.rootDir}/gradle/jdiff"
|
||||
|
||||
ant.taskdef(
|
||||
name: "jdiff",
|
||||
classname: "jdiff.JDiffAntTask",
|
||||
classpath: "${jdiffHome}/antjdiff.jar")
|
||||
ant.taskdef(
|
||||
name: 'jdiff',
|
||||
classname: 'jdiff.JDiffAntTask',
|
||||
classpath: "${jdiffHome}/antjdiff.jar")
|
||||
|
||||
def currentVersion = rootProject.version
|
||||
def currentVersionRoot = rootProject.rootDir
|
||||
def previousVersion = rootProject.previousVersion
|
||||
|
||||
def oldVersion = System.getProperty("OLD_VERSION")
|
||||
def oldVersionRoot = System.getProperty("OLD_VERSION_ROOT")
|
||||
def currentVersion = rootProject.version
|
||||
def currentVersionRoot = rootProject.rootDir
|
||||
|
||||
def outputDir = "${rootProject.buildDir}/reports/jdiff/${oldVersion}_to_${currentVersion}"
|
||||
def oldVersion = System.getProperty("OLD_VERSION") ?: previousVersion
|
||||
def oldVersionRoot = System.getProperty("OLD_VERSION_ROOT")
|
||||
|
||||
doLast {
|
||||
if (oldVersion == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Set OLD_VERSION property to indicate older of the two versions being compared")
|
||||
if (oldVersionRoot == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Set OLD_VERSION_ROOT property to indicate the root directory for ${oldVersion}")
|
||||
def outputDir = "${rootProject.buildDir}/reports/jdiff/${oldVersion}_to_${currentVersion}"
|
||||
|
||||
oldVersionRoot = new File(oldVersionRoot)
|
||||
doLast {
|
||||
if (oldVersionRoot == null)
|
||||
throw new IllegalArgumentException(
|
||||
"Set OLD_VERSION_ROOT property to indicate the root directory for ${oldVersion}")
|
||||
|
||||
ant.property(name: "JDIFF_HOME", value: jdiffHome)
|
||||
ant.mkdir(dir: outputDir)
|
||||
ant.jdiff(
|
||||
destdir: outputDir,
|
||||
verbose: "off",
|
||||
stats: "on",
|
||||
docchanges: "off") {
|
||||
old(name: "Spring Framework ${oldVersion}") {
|
||||
oldVersionRoot.eachDirMatch( {
|
||||
def candidate = new File(it)
|
||||
candidate.name.matches("org.springframework.*") ||
|
||||
candidate.name.matches("spring-.*") }) { match ->
|
||||
match.eachDirRecurse { subdir ->
|
||||
if (subdir.path ==~ '.*/src/main/java$') {
|
||||
dirset(dir: subdir.path, includes: "org/**")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"new"(name: "Spring Framework ${currentVersion}") {
|
||||
currentVersionRoot.eachDirMatch( {
|
||||
def candidate = new File(it)
|
||||
candidate.name.matches("org.springframework.*") ||
|
||||
candidate.name.matches("spring-.*") }) { match ->
|
||||
match.eachDirRecurse { subdir ->
|
||||
if (subdir.path ==~ '.*/src/main/java$') {
|
||||
dirset(dir: subdir.path, includes: "org/**")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
oldVersionRoot = new File(oldVersionRoot)
|
||||
|
||||
ant.property(name: 'JDIFF_HOME', value: jdiffHome)
|
||||
ant.mkdir(dir: outputDir)
|
||||
ant.jdiff(
|
||||
destdir: outputDir,
|
||||
verbose: 'off',
|
||||
stats: 'on',
|
||||
docchanges: 'on') {
|
||||
old(name: "Spring Framework ${oldVersion}") {
|
||||
oldVersionRoot.eachDirMatch( {
|
||||
def candidate = new File(it)
|
||||
candidate.name.matches("org.springframework.*") ||
|
||||
candidate.name.matches("spring-.*") }) { match ->
|
||||
match.eachDirRecurse { subdir ->
|
||||
if (subdir.path ==~ '.*/src/main/java$') {
|
||||
dirset(dir: subdir.path, includes: 'org/**')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'new'(name: "Spring Framework ${currentVersion}") {
|
||||
currentVersionRoot.eachDirMatch( {
|
||||
def candidate = new File(it)
|
||||
candidate.name.matches("org.springframework.*") ||
|
||||
candidate.name.matches("spring-.*") }) { match ->
|
||||
match.eachDirRecurse { subdir ->
|
||||
if (subdir.path ==~ '.*/src/main/java$') {
|
||||
dirset(dir: subdir.path, includes: 'org/**')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
/**
|
||||
* This class is used only as a "null" argument for Javadoc when comparing
|
||||
* two API files. Javadoc has to have a package, .java or .class file as an
|
||||
* two API files. Javadoc has to have a package, .java or .class file as an
|
||||
* argument, even though JDiff doesn't use it.
|
||||
*/
|
||||
public class Null {
|
||||
|
||||
@@ -11,7 +11,7 @@ difference between two public Java APIs.
|
||||
|
||||
The file jdiff.html contains the reference page for JDiff. The latest
|
||||
version of JDiff can be downloaded at:
|
||||
https://sourceforge.net/projects/javadiff
|
||||
http://sourceforge.net/projects/javadiff
|
||||
|
||||
To use the Ant task on your own project, see example.xml. More examples
|
||||
of using JDiff to compare the public APIs of J2SE1.3 and J2SE1.4 can
|
||||
@@ -40,7 +40,7 @@ Acknowledgements
|
||||
JDiff uses Stuart D. Gathman's Java translation of Gene Myers' O(ND)
|
||||
difference algorithm.
|
||||
|
||||
JDiff uses Xerces 1.4.2 from https://www.apache.org.
|
||||
JDiff uses Xerces 1.4.2 from http://www.apache.org.
|
||||
|
||||
JDiff also includes a script to use the classdoc application from
|
||||
http://classdoc.sourceforge.net or http://www.jensgulden.de, by Jens
|
||||
@@ -56,4 +56,4 @@ much of this work.
|
||||
Footnote:
|
||||
|
||||
If you are looking for a generalized diff tool for XML, try diffmk from
|
||||
https://wwws.sun.com/software/xml/developers/diffmk/
|
||||
http://wwws.sun.com/software/xml/developers/diffmk/
|
||||
|
||||
+11
-11
@@ -7,10 +7,10 @@
|
||||
<BODY BGCOLOR="#ffffff">
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td align="left"><A href="https://sourceforge.net/projects/javadiff/">
|
||||
<td align="left"><A href="http://sourceforge.net/projects/javadiff/">
|
||||
<IMG src="http://javadiff.cvs.sourceforge.net/*checkout*/javadiff/jdiff/lib/jdiff_logo.gif"
|
||||
width="88" height="31" border="0" alt="JDiff Logo"></A></td>
|
||||
<td align="right"><A href="https://sourceforge.net"> <IMG src="https://sourceforge.net/sflogo.php?group_id=37160" width="88" height="31" border="0" alt="SourceForge Logo"></A></td>
|
||||
<td align="right"><A href="http://sourceforge.net"> <IMG src="http://sourceforge.net/sflogo.php?group_id=37160" width="88" height="31" border="0" alt="SourceForge Logo"></A></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -21,7 +21,7 @@ width="88" height="31" border="0" alt="JDiff Logo"></A></td>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<b>JDiff</b> is a Javadoc <a
|
||||
href="https://java.sun.com/j2se/javadoc">doclet</a> which generates an
|
||||
href="http://java.sun.com/j2se/javadoc">doclet</a> which generates an
|
||||
HTML report of all the packages, classes, constructors, methods, and
|
||||
fields which have been removed, added or changed in any way, including
|
||||
their documentation, when two APIs are compared. This is very useful
|
||||
@@ -312,7 +312,7 @@ the HTML output to the given directory.
|
||||
<code>-javadocnew</code> <<i>javadoc files location for the new API</i>></DT>
|
||||
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
|
||||
The location of existing Javadoc files
|
||||
for the new API, e.g. "https://java.sun.com/j2se/<b>1.5.0</b>/docs/api/" for the
|
||||
for the new API, e.g. "http://java.sun.com/j2se/<b>1.5.0</b>/docs/api/" for the
|
||||
public documentation for J2SE1.5.0. The default value is "../", which implies
|
||||
that the documentation directory generated by Javadoc is at the same level as
|
||||
the "changes.html" file generated by JDiff. Slashes are always
|
||||
@@ -325,7 +325,7 @@ the HTML output to the given directory.
|
||||
<DT STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
|
||||
<code>-javadocold</code> <<i>javadoc files location for the old API</i>></DT>
|
||||
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm"> The location of existing
|
||||
Javadoc files for the old API, e.g. "https://java.sun.com/j2se/<b>1.5.0</b>/docs/API/"
|
||||
Javadoc files for the old API, e.g. "http://java.sun.com/j2se/<b>1.5.0</b>/docs/API/"
|
||||
for the public documentation for J2SE1.5.0. The default value is null, which
|
||||
results in no links to Javadoc-generated documentation for the previous
|
||||
release. Slashes are always forward in the argument, since this is an HTML
|
||||
@@ -426,7 +426,7 @@ the HTML output to the given directory.
|
||||
<code>-showallchanges</code></DT>
|
||||
<DD STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
|
||||
If this argument is used, JDiff will show changes in
|
||||
native and synchronized modifiers. See <a href="https://java.sun.com/j2se/1.4.1/docs/tooldocs/solaris/javadoc.html#generatedapideclarations">here</a> for why these are not shown by default.
|
||||
native and synchronized modifiers. See <a href="http://java.sun.com/j2se/1.4.1/docs/tooldocs/solaris/javadoc.html#generatedapideclarations">here</a> for why these are not shown by default.
|
||||
</DD>
|
||||
|
||||
<DT STYLE="margin-right: 2cm; margin-bottom: 0.5cm">
|
||||
@@ -547,7 +547,7 @@ moved to the end of the file and placed inside XML comments.
|
||||
|
||||
<BLOCKQUOTE> The text which is added can be HTML text if necessary, but if the
|
||||
HTML is incorrect, JDiff may fail to read the comments file and exit. Note that
|
||||
the required HTML is in fact <a href="https://www.w3.org/TR/xhtml1/diffs.html">XHTML</a>. Since this HTML is stored in an XML document, single tags without their closing ("slash") element are not permitted.
|
||||
the required HTML is in fact <a href="http://www.w3.org/TR/xhtml1/diffs.html">XHTML</a>. Since this HTML is stored in an XML document, single tags without their closing ("slash") element are not permitted.
|
||||
For example, most browsers permit HTML which looks like "<p>Here is some
|
||||
text.", with no closing tag. XML requires that either a closing tag exists ("</p>"),
|
||||
or that the single tag is closed, e.g. "<p/>Here is some text.".
|
||||
@@ -988,7 +988,7 @@ it can tell you how the content has changed.
|
||||
Nor does it
|
||||
compare what the methods in an API do; if JDiff could tell you what had changed about the way two
|
||||
versions of an API execute, the <a
|
||||
href="https://en.wikipedia.org/wiki/Halting_Problem">Halting
|
||||
href="http://en.wikipedia.org/wiki/Halting_Problem">Halting
|
||||
Problem</a> would be solved, and our lives would be very different.</li>
|
||||
<li>On a P3 450MHz machine, to scan all of the J2SE <code>Java</code>
|
||||
and <code>javax</code> packages and generate XML takes about 2 minutes
|
||||
@@ -1002,14 +1002,14 @@ per version. To generate a report from the XML files takes about 30s</li>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<UL>
|
||||
<LI><A HREF="https://www.sys-con.com/java">Java Developer's Journal
|
||||
<LI><A HREF="http://www.sys-con.com/java">Java Developer's Journal
|
||||
</A>, April 2002 contained an article about JDiff. The article
|
||||
can also be <a
|
||||
href="http://javadiff.cvs.sourceforge.net/*checkout*/javadiff/jdiff/doc/JDiffArticle.pdf">found
|
||||
here</a>.</LI>
|
||||
<LI><A HREF="https://java.sun.com/j2se/javadoc/">Javadoc</A> and Doclet
|
||||
<LI><A HREF="http://java.sun.com/j2se/javadoc/">Javadoc</A> and Doclet
|
||||
documentation from Sun.</LI>
|
||||
<LI><A HREF="https://java.sun.com/j2se/javadoc/faq.html#doclets">Third-party
|
||||
<LI><A HREF="http://java.sun.com/j2se/javadoc/faq.html#doclets">Third-party
|
||||
doclets</a> as listed by Sun.</LI>
|
||||
<LI><A HREF="http://www.doclet.com">Third-party doclets</a> as listed by others.</LI>
|
||||
</UL>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Will merge the artifacts of the current project into mergeIntoProject. For example, to
|
||||
* bundle spring-test-mvc in spring-test's jars. This script will perform the following
|
||||
* steps:
|
||||
*
|
||||
* - Ensure that jar tasks of the project being merged from will execute the tasks of the
|
||||
* project being merged into
|
||||
*
|
||||
* - Add the project being merged into to the classpath of the project being merged from
|
||||
*
|
||||
* - Update the pom.xml of the project being merged into to contain the entries from the
|
||||
* project being merged from
|
||||
*
|
||||
* Example Usage:
|
||||
*
|
||||
* ext.mergeIntoProject = project(':spring-test')
|
||||
* apply from: "${rootProject.projectDir}/gradle/merge-artifacts.gradle"
|
||||
*/
|
||||
|
||||
def mergeFromProject = project
|
||||
|
||||
// invoking a task on mergeFromProject will invoke the task with the same name on mergeIntoProject
|
||||
def taskNamesToMerge = ['sourcesJar','jar','javadocJar','javadoc','install','artifactoryPublish']
|
||||
taskNamesToMerge.each { taskName ->
|
||||
def taskToRemove = mergeFromProject.tasks.findByPath(taskName)
|
||||
if(taskToRemove) {
|
||||
taskToRemove.enabled = false
|
||||
taskToRemove.dependsOn mergeIntoProject."$taskName"
|
||||
}
|
||||
}
|
||||
|
||||
// update mergeIntoProject artifacts to contain the mergeFromProject artifact contents
|
||||
mergeIntoProject."sourcesJar" {
|
||||
from mergeFromProject.sourcesJar.source
|
||||
}
|
||||
mergeIntoProject."jar" {
|
||||
from mergeFromProject.jar.source
|
||||
}
|
||||
mergeIntoProject."javadoc" {
|
||||
source += mergeFromProject.javadoc.source
|
||||
classpath += mergeFromProject.javadoc.classpath
|
||||
}
|
||||
|
||||
// Update mergeIntoProject to contain additional configurations that contains all the dependencies from mergeFromProject
|
||||
// so that Maven pom generation works
|
||||
gradle.taskGraph.whenReady {
|
||||
mergeFromProject.configurations.archives.artifacts.clear()
|
||||
|
||||
mergeFromProject.configurations.each { config->
|
||||
def mapping = mergeFromProject.conf2ScopeMappings.getMapping([config])
|
||||
if(mapping.scope) {
|
||||
def newConfigName = mergeFromProject.name + "-"+ config.name
|
||||
mergeIntoProject.configurations.add(newConfigName)
|
||||
config.dependencies.each { dependency ->
|
||||
mergeIntoProject.dependencies.add(newConfigName, dependency)
|
||||
}
|
||||
configure(mergeIntoProject.install.repositories.mavenInstaller.pom.scopeMappings) {
|
||||
addMapping(mapping.priority + 100, mergeIntoProject.configurations."$newConfigName", mapping.scope)
|
||||
}
|
||||
mergeIntoProject.optionalDeps += mergeFromProject.optionalDeps
|
||||
mergeIntoProject.providedDeps += mergeFromProject.providedDeps
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-47
@@ -1,55 +1,60 @@
|
||||
apply plugin: "propdeps-maven"
|
||||
apply plugin: 'maven'
|
||||
|
||||
ext.optionalDeps = []
|
||||
ext.providedDeps = []
|
||||
|
||||
ext.optional = { optionalDeps << it }
|
||||
ext.provided = { providedDeps << it }
|
||||
|
||||
install {
|
||||
repositories.mavenInstaller {
|
||||
customizePom(pom, project)
|
||||
}
|
||||
repositories.mavenInstaller {
|
||||
customizePom(pom, project)
|
||||
}
|
||||
}
|
||||
|
||||
def customizePom(pom, gradleProject) {
|
||||
pom.whenConfigured { generatedPom ->
|
||||
// eliminate test-scoped dependencies (no need in maven central poms)
|
||||
generatedPom.dependencies.removeAll { dep ->
|
||||
dep.scope == "test"
|
||||
}
|
||||
pom.whenConfigured { generatedPom ->
|
||||
// respect 'optional' and 'provided' dependencies
|
||||
gradleProject.optionalDeps.each { dep ->
|
||||
generatedPom.dependencies.findAll { it.artifactId == dep.name }*.optional = true
|
||||
}
|
||||
gradleProject.providedDeps.each { dep ->
|
||||
generatedPom.dependencies.findAll { it.artifactId == dep.name }*.scope = 'provided'
|
||||
}
|
||||
|
||||
// sort to make pom dependencies order consistent to ease comparison of older poms
|
||||
generatedPom.dependencies = generatedPom.dependencies.sort { dep ->
|
||||
"$dep.scope:$dep.groupId:$dep.artifactId"
|
||||
}
|
||||
// eliminate test-scoped dependencies (no need in maven central poms)
|
||||
generatedPom.dependencies.removeAll { dep ->
|
||||
dep.scope == 'test'
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
description = gradleProject.description
|
||||
url = "https://github.com/spring-projects/spring-framework"
|
||||
organization {
|
||||
name = "Spring IO"
|
||||
url = "https://projects.spring.io/spring-framework"
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name "Apache License, Version 2.0"
|
||||
url "https://www.apache.org/licenses/LICENSE-2.0"
|
||||
distribution "repo"
|
||||
}
|
||||
}
|
||||
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"
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = "jhoeller"
|
||||
name = "Juergen Hoeller"
|
||||
email = "jhoeller@pivotal.io"
|
||||
}
|
||||
}
|
||||
issueManagement {
|
||||
system = "Jira"
|
||||
url = "https://jira.springsource.org/browse/SPR"
|
||||
}
|
||||
}
|
||||
}
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
description = gradleProject.description
|
||||
url = 'https://github.com/SpringSource/spring-framework'
|
||||
organization {
|
||||
name = 'SpringSource'
|
||||
url = 'http://springsource.org/spring-framework'
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name 'The Apache Software License, Version 2.0'
|
||||
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
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@vmware.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-1
@@ -1,5 +1,6 @@
|
||||
#Thu Nov 01 10:28:17 PDT 2012
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.2-bin.zip
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -6,6 +6,48 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# 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"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=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"
|
||||
@@ -20,50 +62,9 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
cd "`dirname \"$PRG\"`/"
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
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"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
cd "$SAVED"
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@@ -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`
|
||||
@@ -155,19 +155,11 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
|
||||
Vendored
+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 https://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: https://download.eclipse.org/eclipse/downloads
|
||||
- STS downloads: https://spring.io/tools/sts/all
|
||||
- STS nightly builds: https://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.
|
||||
|
||||
|
||||
+16
-17
@@ -1,33 +1,32 @@
|
||||
The following has been tested against Intellij IDEA 13.1
|
||||
The following has been tested against Intellij IDEA 11.0.1
|
||||
|
||||
## Steps
|
||||
|
||||
_Within your locally cloned spring-framework working directory:_
|
||||
|
||||
1. Pre-compile `spring-oxm` with `./gradlew cleanIdea :spring-oxm:compileTestJava`
|
||||
2. Import into IDEA (File->import project->import from external model->Gradle)
|
||||
3. Set the Project JDK as appropriate (1.8+)
|
||||
4. Exclude the `spring-aspects` module (Go to File->Project Structure->Modules)
|
||||
1. Generate IDEA metadata with `./gradlew cleanIdea idea`
|
||||
2. Import into IDEA as usual
|
||||
3. Set the Project JDK as appropriate
|
||||
4. Add git support
|
||||
5. Code away
|
||||
|
||||
## Known issues
|
||||
|
||||
1. `spring-oxm` should be pre-compiled since it's using repackaged dependencies (see *RepackJar tasks)
|
||||
2. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
|
||||
See https://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the 'spring-aspects'
|
||||
should be excluded from the overall project to avoid compilation errors.
|
||||
3. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
|
||||
likely need to set the following VM options to avoid out of memory errors:
|
||||
-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
|
||||
1. MockServletContext and friends will fail to compile in spring-web. To fix this, uncheck the 'export' setting for all servlet-api and tomcat-servlet-api jars. The problem is that spring-web needs Servlet 2.5, but it's picking up Servlet 3.0 from projects that it depends on.
|
||||
2. spring-context will fail to build because there's a duplicate instance of GroovyMessenger in spring-context/src/test/java/org/springframework/scripting/groovy/Messenger.groovy. The solution to this is not known. It's not a problem on Eclipse, because Eclipse doesn't automatically compile .groovy files like IDEA (apparently) does.
|
||||
|
||||
There are no other known problems at this time. Please add to this list, and if you're ambitious, consider playing with the Gradle IDEA generation DSL to fix these problems automatically, e.g.:
|
||||
|
||||
* http://gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaProject.html
|
||||
* http://gradle.org/docs/current/dsl/org.gradle.plugins.ide.idea.model.IdeaModule.html
|
||||
* http://gradle.org/docs/current/groovydoc/org/gradle/plugins/ide/idea/model/IdeaModule.html
|
||||
|
||||
## Tips
|
||||
|
||||
In any case, please do not check in your own generated .iml, .ipr, or .iws files.
|
||||
You'll notice these files are already intentionally in .gitignore. The same policy goes for eclipse metadata.
|
||||
In any case, please do not check in your own generated .iml, .ipr, or .iws files. You'll notice these files are already intentionally in .gitignore. The same policy goes for eclipse metadata.
|
||||
|
||||
## FAQ
|
||||
|
||||
Q. What about IDEA's own [Gradle support](https://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 https://youtrack.jetbrains.com/issue/IDEA-53476
|
||||
A. Unknown. Please report back if you try it and it goes well for you.
|
||||
|
||||
+23
-30
@@ -1,31 +1,24 @@
|
||||
rootProject.name = "spring"
|
||||
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-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-orm-hibernate5"
|
||||
include "spring-oxm"
|
||||
include "spring-test"
|
||||
include "spring-tx"
|
||||
include "spring-web"
|
||||
include "spring-webmvc"
|
||||
include "spring-webmvc-portlet"
|
||||
include "spring-webmvc-tiles2"
|
||||
include "spring-websocket"
|
||||
include "spring-framework-bom"
|
||||
|
||||
// Exposes gradle buildSrc for IDE support
|
||||
include "buildSrc"
|
||||
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
|
||||
include 'spring-aop'
|
||||
include 'spring-aspects'
|
||||
include 'spring-beans'
|
||||
include 'spring-context'
|
||||
include 'spring-context-support'
|
||||
include 'spring-core'
|
||||
include 'spring-expression'
|
||||
include 'spring-instrument'
|
||||
include 'spring-instrument-tomcat'
|
||||
include 'spring-jdbc'
|
||||
include 'spring-jms'
|
||||
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-webmvc-portlet'
|
||||
include 'spring-webmvc-tiles3'
|
||||
|
||||
@@ -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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
|
||||
/**
|
||||
* This interface represents a generic runtime joinpoint (in the AOP
|
||||
* terminology).
|
||||
*
|
||||
* <p>A runtime joinpoint is an <i>event</i> that occurs on a static
|
||||
* joinpoint (i.e. a location in a the program). For instance, an
|
||||
* invocation is the runtime joinpoint on a method (static joinpoint).
|
||||
* The static part of a given joinpoint can be generically retrieved
|
||||
* using the {@link #getStaticPart()} method.
|
||||
*
|
||||
* <p>In the context of an interception framework, a runtime joinpoint
|
||||
* is then the reification of an access to an accessible object (a
|
||||
* method, a constructor, a field), i.e. the static part of the
|
||||
* joinpoint. It is passed to the interceptors that are installed on
|
||||
* the static joinpoint.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Interceptor
|
||||
*/
|
||||
public interface Joinpoint {
|
||||
|
||||
/**
|
||||
* Proceed to the next interceptor in the chain.
|
||||
* <p>The implementation and the semantics of this method depends
|
||||
* on the actual joinpoint type (see the children interfaces).
|
||||
* @return see the children interfaces' proceed definition
|
||||
* @throws Throwable if the joinpoint throws an exception
|
||||
*/
|
||||
Object proceed() throws Throwable;
|
||||
|
||||
/**
|
||||
* Return the object that holds the current joinpoint's static part.
|
||||
* <p>For instance, the target object for an invocation.
|
||||
* @return the object (can be null if the accessible object is static)
|
||||
*/
|
||||
Object getThis();
|
||||
|
||||
/**
|
||||
* Return the static part of this joinpoint.
|
||||
* <p>The static part is an accessible object on which a chain of
|
||||
* interceptors are installed.
|
||||
*/
|
||||
AccessibleObject getStaticPart();
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* Intercepts calls on an interface on its way to the target. These
|
||||
* are nested "on top" of the target.
|
||||
*
|
||||
* <p>The user should implement the {@link #invoke(MethodInvocation)}
|
||||
* method to modify the original behavior. E.g. the following class
|
||||
* implements a tracing interceptor (traces all the calls on the
|
||||
* intercepted method(s)):
|
||||
*
|
||||
* <pre class=code>
|
||||
* class TracingInterceptor implements MethodInterceptor {
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
* System.out.println("method "+i.getMethod()+" is called on "+
|
||||
* i.getThis()+" with args "+i.getArguments());
|
||||
* Object ret=i.proceed();
|
||||
* System.out.println("method "+i.getMethod()+" returns "+ret);
|
||||
* return ret;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodInterceptor extends Interceptor {
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed()};
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
*/
|
||||
Object invoke(MethodInvocation invocation) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.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,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,14 +18,14 @@ package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Base interface holding AOP <b>advice</b> (action to take at a joinpoint)
|
||||
* and a filter determining the applicability of the advice (such as
|
||||
* and a filter determining the applicability of the advice (such as
|
||||
* a pointcut). <i>This interface is not for use by Spring users, but to
|
||||
* allow for commonality in support for different types of advice.</i>
|
||||
*
|
||||
* <p>Spring AOP is based around <b>around advice</b> delivered via method
|
||||
* <b>interception</b>, compliant with the AOP Alliance interception API.
|
||||
* <b>interception</b>, compliant with the AOP Alliance interception API.
|
||||
* The Advisor interface allows support for different types of advice,
|
||||
* such as <b>before</b> and <b>after</b> advice, which need not be
|
||||
* implemented using interception.
|
||||
@@ -50,7 +50,7 @@ public interface Advisor {
|
||||
* (for example, creating a mixin) or shared with all instances of
|
||||
* the advised class obtained from the same Spring bean factory.
|
||||
* <p><b>Note that this method is not currently used by the framework.</b>
|
||||
* Typical Advisor implementations always return {@code true}.
|
||||
* Typical Advisor implementations always return <code>true</code>.
|
||||
* Use singleton/prototype bean definitions or appropriate programmatic
|
||||
* proxy creation to ensure that Advisors have the correct lifecycle model.
|
||||
* @return whether this advice is associated with a particular target instance
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -33,7 +33,7 @@ public interface AfterReturningAdvice extends AfterAdvice {
|
||||
* @param returnValue the value returned by the method, if any
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be {@code null}.
|
||||
* @param target target of the method invocation. May be <code>null</code>.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -25,7 +25,6 @@ import org.springframework.core.NestedRuntimeException;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AopInvocationException extends NestedRuntimeException {
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,7 +18,7 @@ package org.springframework.aop;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Subinterface of AOP Alliance Advice that allows additional interfaces
|
||||
* to be implemented by an Advice, and available via a proxy using that
|
||||
* interceptor. This is a fundamental AOP concept called <b>introduction</b>.
|
||||
@@ -37,7 +37,7 @@ import org.aopalliance.aop.Advice;
|
||||
* @see IntroductionAdvisor
|
||||
*/
|
||||
public interface DynamicIntroductionAdvice extends Advice {
|
||||
|
||||
|
||||
/**
|
||||
* Does this introduction advice implement the given interface?
|
||||
* @param intf the interface to check
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -30,7 +30,7 @@ package org.springframework.aop;
|
||||
* @see IntroductionInterceptor
|
||||
*/
|
||||
public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
|
||||
|
||||
|
||||
/**
|
||||
* Return the filter determining which target classes this introduction
|
||||
* should apply to.
|
||||
@@ -39,7 +39,7 @@ public interface IntroductionAdvisor extends Advisor, IntroductionInfo {
|
||||
* @return the class filter
|
||||
*/
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
|
||||
/**
|
||||
* Can the advised interfaces be implemented by the introduction advice?
|
||||
* Invoked before adding an IntroductionAdvisor.
|
||||
|
||||
+9
-9
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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
|
||||
@@ -33,12 +33,12 @@ public interface IntroductionAwareMethodMatcher extends MethodMatcher {
|
||||
* instead of the 2-arg {@link #matches(java.lang.reflect.Method, Class)} method
|
||||
* if the caller supports the extended IntroductionAwareMethodMatcher interface.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param hasIntroductions {@code true} if the object on whose behalf we are
|
||||
* asking is the subject on one or more introductions; {@code false} otherwise
|
||||
* @param hasIntroductions <code>true</code> if the object on whose behalf we are
|
||||
* asking is the subject on one or more introductions; <code>false</code> 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -29,11 +29,11 @@ package org.springframework.aop;
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public interface IntroductionInfo {
|
||||
|
||||
|
||||
/**
|
||||
* Return the additional interfaces introduced by this Advisor or Advice.
|
||||
* @return the introduced interfaces
|
||||
*/
|
||||
Class<?>[] getInterfaces();
|
||||
Class[] getInterfaces();
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -28,12 +28,12 @@ import java.lang.reflect.Method;
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodBeforeAdvice extends BeforeAdvice {
|
||||
|
||||
|
||||
/**
|
||||
* Callback before a given method is invoked.
|
||||
* @param method method being invoked
|
||||
* @param args arguments to the method
|
||||
* @param target target of the method invocation. May be {@code null}.
|
||||
* @param target target of the method invocation. May be <code>null</code>.
|
||||
* @throws Throwable if this object wishes to abort the call.
|
||||
* Any exception thrown will be returned to the caller if it's
|
||||
* allowed by the method signature. Otherwise the exception
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -26,15 +26,15 @@ import java.lang.reflect.Method;
|
||||
* also makes arguments for a particular call available, and any effects of running
|
||||
* previous advice applying to the joinpoint.
|
||||
*
|
||||
* <p>If an implementation returns {@code false} from its {@link #isRuntime()}
|
||||
* <p>If an implementation returns <code>false</code> from its {@link #isRuntime()}
|
||||
* method, evaluation can be performed statically, and the result will be the same
|
||||
* for all invocations of this method, whatever their arguments. This means that
|
||||
* if the {@link #isRuntime()} method returns {@code false}, the 3-arg
|
||||
* if the {@link #isRuntime()} method returns <code>false</code>, the 3-arg
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method will never be invoked.
|
||||
*
|
||||
* <p>If an implementation returns {@code true} from its 2-arg
|
||||
* <p>If an implementation returns <code>true</code> from its 2-arg
|
||||
* {@link #matches(java.lang.reflect.Method, Class)} method and its {@link #isRuntime()} method
|
||||
* returns {@code true}, the 3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}
|
||||
* returns <code>true</code>, the 3-arg {@link #matches(java.lang.reflect.Method, Class, Object[])}
|
||||
* method will be invoked <i>immediately before each potential execution of the related advice</i>,
|
||||
* to decide whether the advice should run. All previous advice, such as earlier interceptors
|
||||
* in an interceptor chain, will have run, so any state changes they have produced in
|
||||
@@ -48,13 +48,12 @@ import java.lang.reflect.Method;
|
||||
public interface MethodMatcher {
|
||||
|
||||
/**
|
||||
* Perform static checking whether the given method matches.
|
||||
* <p>If this returns {@code false} or if the {@link #isRuntime()}
|
||||
* method returns {@code false}, no runtime check (i.e. no
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
|
||||
* will be made.
|
||||
* Perform static checking whether the given method matches. If this
|
||||
* returns <code>false</code> or if the {@link #isRuntime()} method
|
||||
* returns <code>false</code>, no runtime check (i.e. no.
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @return whether or not this method matches statically
|
||||
*/
|
||||
@@ -63,7 +62,7 @@ public interface MethodMatcher {
|
||||
/**
|
||||
* Is this MethodMatcher dynamic, that is, must a final call be made on the
|
||||
* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at
|
||||
* runtime even if the 2-arg matches method returns {@code true}?
|
||||
* runtime even if the 2-arg matches method returns <code>true</code>?
|
||||
* <p>Can be invoked when an AOP proxy is created, and need not be invoked
|
||||
* again before each method invocation,
|
||||
* @return whether or not a runtime match via the 3-arg
|
||||
@@ -76,18 +75,18 @@ public interface MethodMatcher {
|
||||
* Check whether there a runtime (dynamic) match for this method,
|
||||
* which must have matched statically.
|
||||
* <p>This method is invoked only if the 2-arg matches method returns
|
||||
* {@code true} for the given method and target class, and if the
|
||||
* {@link #isRuntime()} method returns {@code true}. Invoked
|
||||
* <code>true</code> for the given method and target class, and if the
|
||||
* {@link #isRuntime()} method returns <code>true</code>. Invoked
|
||||
* immediately before potential running of the advice, after any
|
||||
* advice earlier in the advice chain has run.
|
||||
* @param method the candidate method
|
||||
* @param targetClass the target class (may be {@code null}, in which case
|
||||
* @param targetClass the target class (may be <code>null</code>, in which case
|
||||
* the candidate class must be taken to be the method's declaring class)
|
||||
* @param args arguments to the method
|
||||
* @return whether there's a runtime match
|
||||
* @see MethodMatcher#matches(Method, Class)
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass, Object... args);
|
||||
boolean matches(Method method, Class<?> targetClass, Object[] args);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -34,13 +34,13 @@ public interface Pointcut {
|
||||
|
||||
/**
|
||||
* Return the ClassFilter for this pointcut.
|
||||
* @return the ClassFilter (never {@code null})
|
||||
* @return the ClassFilter (never <code>null</code>)
|
||||
*/
|
||||
ClassFilter getClassFilter();
|
||||
|
||||
/**
|
||||
* Return the MethodMatcher for this pointcut.
|
||||
* @return the MethodMatcher (never {@code null})
|
||||
* @return the MethodMatcher (never <code>null</code>)
|
||||
*/
|
||||
MethodMatcher getMethodMatcher();
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -40,45 +40,45 @@ public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
Object getProxy();
|
||||
|
||||
/**
|
||||
* Create a clone of this object. If cloning is done before {@code proceed()}
|
||||
* is invoked on this object, {@code proceed()} can be invoked once per clone
|
||||
* Create a clone of this object. If cloning is done before <code>proceed()</code>
|
||||
* is invoked on this object, <code>proceed()</code> can be invoked once per clone
|
||||
* to invoke the joinpoint (and the rest of the advice chain) more than once.
|
||||
* @return an invocable clone of this invocation.
|
||||
* {@code proceed()} can be called once per clone.
|
||||
* <code>proceed()</code> can be called once per clone.
|
||||
*/
|
||||
MethodInvocation invocableClone();
|
||||
|
||||
/**
|
||||
* Create a clone of this object. If cloning is done before {@code proceed()}
|
||||
* is invoked on this object, {@code proceed()} can be invoked once per clone
|
||||
* Create a clone of this object. If cloning is done before <code>proceed()</code>
|
||||
* is invoked on this object, <code>proceed()</code> can be invoked once per clone
|
||||
* to invoke the joinpoint (and the rest of the advice chain) more than once.
|
||||
* @param arguments the arguments that the cloned invocation is supposed to use,
|
||||
* overriding the original arguments
|
||||
* @return an invocable clone of this invocation.
|
||||
* {@code proceed()} can be called once per clone.
|
||||
* <code>proceed()</code> 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.
|
||||
* <p>Such attributes are not used within the AOP framework itself. They are
|
||||
* just kept as part of the invocation object, for use in special interceptors.
|
||||
* @param key the name of the attribute
|
||||
* @param value the value of the attribute, or {@code null} to reset it
|
||||
* @param value the value of the attribute, or <code>null</code> to reset it
|
||||
*/
|
||||
void setUserAttribute(String key, Object value);
|
||||
|
||||
/**
|
||||
* Return the value of the specified user attribute.
|
||||
* @param key the name of the attribute
|
||||
* @return the value of the attribute, or {@code null} if not set
|
||||
* @return the value of the attribute, or <code>null</code> if not set
|
||||
* @see #setUserAttribute
|
||||
*/
|
||||
Object getUserAttribute(String key);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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
|
||||
@@ -32,7 +32,7 @@ public interface TargetClassAware {
|
||||
/**
|
||||
* Return the target class behind the implementing object
|
||||
* (typically a proxy configuration or an actual proxy).
|
||||
* @return the target Class, or {@code null} if not known
|
||||
* @return the target Class, or <code>null</code> if not known
|
||||
*/
|
||||
Class<?> getTargetClass();
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*<
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,16 +17,16 @@
|
||||
package org.springframework.aop;
|
||||
|
||||
/**
|
||||
* A {@code TargetSource} is used to obtain the current "target" of
|
||||
* A <code>TargetSource</code> is used to obtain the current "target" of
|
||||
* an AOP invocation, which will be invoked via reflection if no around
|
||||
* advice chooses to end the interceptor chain itself.
|
||||
*
|
||||
* <p>If a {@code TargetSource} is "static", it will always return
|
||||
* <p>If a <code>TargetSource</code> is "static", it will always return
|
||||
* the same target, allowing optimizations in the AOP framework. Dynamic
|
||||
* target sources can support pooling, hot swapping, etc.
|
||||
*
|
||||
* <p>Application developers don't usually need to work with
|
||||
* {@code TargetSources} directly: this is an AOP framework interface.
|
||||
* <code>TargetSources</code> directly: this is an AOP framework interface.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@@ -34,18 +34,19 @@ public interface TargetSource extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Return the type of targets returned by this {@link TargetSource}.
|
||||
* <p>Can return {@code null}, although certain usages of a {@code TargetSource}
|
||||
* might just work with a predetermined target class.
|
||||
* <p>Can return <code>null</code>, although certain usages of a
|
||||
* <code>TargetSource</code> might just work with a predetermined
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
@Override
|
||||
Class<?> getTargetClass();
|
||||
|
||||
/**
|
||||
* Will all calls to {@link #getTarget()} return the same object?
|
||||
* <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
|
||||
* and the AOP framework can cache the return value of {@link #getTarget()}.
|
||||
* @return {@code true} if the target is immutable
|
||||
* <p>In that case, there will be no need to invoke
|
||||
* {@link #releaseTarget(Object)}, and the AOP framework can cache
|
||||
* the return value of {@link #getTarget()}.
|
||||
* @return <code>true</code> if the target is immutable
|
||||
* @see #getTarget
|
||||
*/
|
||||
boolean isStatic();
|
||||
@@ -53,15 +54,14 @@ public interface TargetSource extends TargetClassAware {
|
||||
/**
|
||||
* Return a target instance. Invoked immediately before the
|
||||
* AOP framework calls the "target" of an AOP method invocation.
|
||||
* @return the target object which contains the joinpoint,
|
||||
* or {@code null} if there is no actual target instance
|
||||
* @return the target object, which contains the joinpoint
|
||||
* @throws Exception if the target object can't be resolved
|
||||
*/
|
||||
Object getTarget() throws Exception;
|
||||
|
||||
/**
|
||||
* Release the given target object obtained from the
|
||||
* {@link #getTarget()} method, if any.
|
||||
* {@link #getTarget()} method.
|
||||
* @param target object obtained from a call to {@link #getTarget()}
|
||||
* @throws Exception if the object can't be released
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -23,26 +23,24 @@ import java.io.Serializable;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class TrueClassFilter implements ClassFilter, Serializable {
|
||||
|
||||
|
||||
public static final TrueClassFilter INSTANCE = new TrueClassFilter();
|
||||
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueClassFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
public boolean matches(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding {@code equals()}.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -24,48 +24,41 @@ import java.lang.reflect.Method;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding {@code equals()}.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -23,31 +23,28 @@ import java.io.Serializable;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class TruePointcut implements Pointcut, Serializable {
|
||||
|
||||
|
||||
public static final TruePointcut INSTANCE = new TruePointcut();
|
||||
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TruePointcut() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassFilter getClassFilter() {
|
||||
return ClassFilter.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMatcher getMethodMatcher() {
|
||||
return MethodMatcher.TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
* Alternative to overriding {@code equals()}.
|
||||
* Alternative to overriding <code>equals()</code>.
|
||||
*/
|
||||
private Object readResolve() {
|
||||
return INSTANCE;
|
||||
|
||||
+80
-114
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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,21 +87,18 @@ 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;
|
||||
|
||||
private final AspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
/**
|
||||
* The name of the aspect (ref bean) in which this advice was defined
|
||||
* (used when determining advice precedence so that we can determine
|
||||
* The name of the aspect (ref bean) in which this advice was defined (used
|
||||
* when determining advice precedence so that we can determine
|
||||
* whether two pieces of advice come from the same aspect).
|
||||
*/
|
||||
private String aspectName;
|
||||
@@ -118,17 +112,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* This will be non-null if the creator of this advice object knows the argument names
|
||||
* and sets them explicitly
|
||||
*/
|
||||
private String[] argumentNames;
|
||||
private String[] argumentNames = null;
|
||||
|
||||
/** Non-null if after throwing advice binds the thrown value */
|
||||
private String throwingName;
|
||||
private String throwingName = null;
|
||||
|
||||
/** Non-null if after returning advice binds the return value */
|
||||
private String returningName;
|
||||
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();
|
||||
}
|
||||
@@ -220,20 +211,18 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
public void setAspectName(String name) {
|
||||
this.aspectName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the declaration order of this advice within the aspect.
|
||||
* Sets the <b>declaration order</b> of this advice within the aspect
|
||||
*/
|
||||
public void setDeclarationOrder(int order) {
|
||||
this.declarationOrder = order;
|
||||
}
|
||||
|
||||
@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.getParameterTypes().length == this.argumentNames.length + 1) {
|
||||
if (argumentNames != null) {
|
||||
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
Class firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = this.argumentNames;
|
||||
this.argumentNames = new String[oldNames.length + 1];
|
||||
this.argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
|
||||
String[] oldNames = argumentNames;
|
||||
argumentNames = new String[oldNames.length + 1];
|
||||
argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,7 +268,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* We need to hold the returning name at this level for argument binding calculations,
|
||||
* this method allows the afterReturning advice subclass to set the name.
|
||||
*/
|
||||
@@ -295,13 +284,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Returning name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getDiscoveredReturningType() {
|
||||
protected Class getDiscoveredReturningType() {
|
||||
return this.discoveredReturningType;
|
||||
}
|
||||
|
||||
@@ -313,7 +302,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* We need to hold the throwing name at this level for argument binding calculations,
|
||||
* this method allows the afterThrowing advice subclass to set the name.
|
||||
*/
|
||||
@@ -329,13 +318,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Throwing name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getDiscoveredThrowingType() {
|
||||
protected Class getDiscoveredThrowingType() {
|
||||
return this.discoveredThrowingType;
|
||||
}
|
||||
|
||||
@@ -358,27 +347,29 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* on subsequent advice invocations can be as fast as possible.
|
||||
* <p>If the first argument is of type JoinPoint or ProceedingJoinPoint then we
|
||||
* pass a JoinPoint in that position (ProceedingJoinPoint for around advice).
|
||||
* <p>If the first argument is of type {@code JoinPoint.StaticPart}
|
||||
* then we pass a {@code JoinPoint.StaticPart} in that position.
|
||||
* <p>If the first argument is of type <code>JoinPoint.StaticPart</code>
|
||||
* then we pass a <code>JoinPoint.StaticPart</code> in that position.
|
||||
* <p>Remaining arguments have to be bound by pointcut evaluation at
|
||||
* a given join point. We will get back a map from argument name to
|
||||
* value. We need to calculate which advice parameter needs to be bound
|
||||
* to which argument name. There are multiple strategies for determining
|
||||
* this binding, which are arranged in a ChainOfResponsibility.
|
||||
*/
|
||||
public final synchronized void calculateArgumentBindings() {
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
|
||||
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numUnboundArgs = this.parameterTypes.length;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
|
||||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
int numUnboundArgs = this.adviceInvocationArgumentCount;
|
||||
Class[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
}
|
||||
|
||||
|
||||
if (numUnboundArgs > 0) {
|
||||
// need to bind arguments by name as returned from the pointcut match
|
||||
bindArgumentsByName(numUnboundArgs);
|
||||
@@ -387,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;
|
||||
}
|
||||
@@ -397,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");
|
||||
}
|
||||
@@ -407,18 +398,18 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean supportsProceedingJoinPoint() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
@@ -431,7 +422,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
if (this.argumentNames != null) {
|
||||
// We have been able to determine the arg names.
|
||||
bindExplicitArguments(numArgumentsExpectingToBind);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
|
||||
"requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
|
||||
@@ -441,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);
|
||||
@@ -463,13 +456,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
|
||||
" arguments to bind by name in advice, but actually found " +
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
|
||||
+ " arguments to bind by name in advice, but actually found " +
|
||||
this.argumentNames.length + " arguments.");
|
||||
}
|
||||
|
||||
// So we match in number...
|
||||
int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
|
||||
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
|
||||
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
|
||||
this.argumentBindings.put(this.argumentNames[i], i);
|
||||
}
|
||||
@@ -478,9 +471,9 @@ 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);
|
||||
this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index];
|
||||
@@ -489,9 +482,9 @@ 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);
|
||||
this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index];
|
||||
@@ -516,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++) {
|
||||
@@ -532,7 +525,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
pointcutParameterTypes[index] = methodParameterTypes[i];
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
this.pointcut.setParameterNames(pointcutParameterNames);
|
||||
this.pointcut.setParameterTypes(pointcutParameterTypes);
|
||||
}
|
||||
@@ -550,13 +543,13 @@ 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) {
|
||||
adviceInvocationArgs[this.joinPointArgumentIndex] = jp;
|
||||
numBound++;
|
||||
}
|
||||
}
|
||||
else if (this.joinPointStaticPartArgumentIndex != -1) {
|
||||
adviceInvocationArgs[this.joinPointStaticPartArgumentIndex] = jp.getStaticPart();
|
||||
numBound++;
|
||||
@@ -587,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;
|
||||
@@ -671,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.
|
||||
@@ -694,27 +678,9 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AdviceExcludingMethodMatcher)) {
|
||||
return false;
|
||||
}
|
||||
AdviceExcludingMethodMatcher otherMm = (AdviceExcludingMethodMatcher) other;
|
||||
return this.adviceMethod.equals(otherMm.adviceMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.adviceMethod.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -34,13 +34,13 @@ public interface AspectInstanceFactory extends Ordered {
|
||||
|
||||
/**
|
||||
* Create an instance of this factory's aspect.
|
||||
* @return the aspect instance (never {@code null})
|
||||
* @return the aspect instance (never <code>null</code>)
|
||||
*/
|
||||
Object getAspectInstance();
|
||||
|
||||
/**
|
||||
* Expose the aspect class loader that this factory uses.
|
||||
* @return the aspect class loader (never {@code null})
|
||||
* @return the aspect class loader (never <code>null</code>)
|
||||
*/
|
||||
ClassLoader getAspectClassLoader();
|
||||
|
||||
|
||||
+72
-70
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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;
|
||||
|
||||
@@ -35,85 +36,84 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* {@link ParameterNameDiscoverer} implementation that tries to deduce parameter names
|
||||
* for an advice method from the pointcut expression, returning, and throwing clauses.
|
||||
* If an unambiguous interpretation is not available, it returns {@code null}.
|
||||
* If an unambiguous interpretation is not available, it returns <code>null</code>.
|
||||
*
|
||||
* <p>This class interprets arguments in the following way:
|
||||
* <ol>
|
||||
* <li>If the first parameter of the method is of type {@link JoinPoint}
|
||||
* or {@link ProceedingJoinPoint}, it is assumed to be for passing
|
||||
* {@code thisJoinPoint} to the advice, and the parameter name will
|
||||
* be assigned the value {@code "thisJoinPoint"}.</li>
|
||||
* <code>thisJoinPoint</code> to the advice, and the parameter name will
|
||||
* be assigned the value <code>"thisJoinPoint"</code>.</li>
|
||||
* <li>If the first parameter of the method is of type
|
||||
* {@code JoinPoint.StaticPart}, it is assumed to be for passing
|
||||
* {@code "thisJoinPointStaticPart"} to the advice, and the parameter name
|
||||
* will be assigned the value {@code "thisJoinPointStaticPart"}.</li>
|
||||
* <code>JoinPoint.StaticPart</code>, it is assumed to be for passing
|
||||
* <code>"thisJoinPointStaticPart"</code> to the advice, and the parameter name
|
||||
* will be assigned the value <code>"thisJoinPointStaticPart"</code>.</li>
|
||||
* <li>If a {@link #setThrowingName(String) throwingName} has been set, and
|
||||
* there are no unbound arguments of type {@code Throwable+}, then an
|
||||
* there are no unbound arguments of type <code>Throwable+</code>, then an
|
||||
* {@link IllegalArgumentException} is raised. If there is more than one
|
||||
* unbound argument of type {@code Throwable+}, then an
|
||||
* unbound argument of type <code>Throwable+</code>, then an
|
||||
* {@link AmbiguousBindingException} is raised. If there is exactly one
|
||||
* unbound argument of type {@code Throwable+}, then the corresponding
|
||||
* unbound argument of type <code>Throwable+</code>, then the corresponding
|
||||
* parameter name is assigned the value <throwingName>.</li>
|
||||
* <li>If there remain unbound arguments, then the pointcut expression is
|
||||
* examined. Let {@code a} be the number of annotation-based pointcut
|
||||
* examined. Let <code>a</code> be the number of annotation-based pointcut
|
||||
* expressions (@annotation, @this, @target, @args,
|
||||
* @within, @withincode) that are used in binding form. Usage in
|
||||
* binding form has itself to be deduced: if the expression inside the
|
||||
* pointcut is a single string literal that meets Java variable name
|
||||
* conventions it is assumed to be a variable name. If {@code a} is
|
||||
* zero we proceed to the next stage. If {@code a} > 1 then an
|
||||
* {@code AmbiguousBindingException} is raised. If {@code a} == 1,
|
||||
* and there are no unbound arguments of type {@code Annotation+},
|
||||
* then an {@code IllegalArgumentException} is raised. if there is
|
||||
* conventions it is assumed to be a variable name. If <code>a</code> is
|
||||
* zero we proceed to the next stage. If <code>a</code> > 1 then an
|
||||
* <code>AmbiguousBindingException</code> is raised. If <code>a</code> == 1,
|
||||
* and there are no unbound arguments of type <code>Annotation+</code>,
|
||||
* then an <code>IllegalArgumentException</code> is raised. if there is
|
||||
* exactly one such argument, then the corresponding parameter name is
|
||||
* assigned the value from the pointcut expression.</li>
|
||||
* <li>If a returningName has been set, and there are no unbound arguments
|
||||
* then an {@code IllegalArgumentException} is raised. If there is
|
||||
* then an <code>IllegalArgumentException</code> is raised. If there is
|
||||
* more than one unbound argument then an
|
||||
* {@code AmbiguousBindingException} is raised. If there is exactly
|
||||
* <code>AmbiguousBindingException</code> is raised. If there is exactly
|
||||
* one unbound argument then the corresponding parameter name is assigned
|
||||
* the value <returningName>.</li>
|
||||
* <li>If there remain unbound arguments, then the pointcut expression is
|
||||
* examined once more for {@code this}, {@code target}, and
|
||||
* {@code args} pointcut expressions used in the binding form (binding
|
||||
* examined once more for <code>this</code>, <code>target</code>, and
|
||||
* <code>args</code> pointcut expressions used in the binding form (binding
|
||||
* forms are deduced as described for the annotation based pointcuts). If
|
||||
* there remains more than one unbound argument of a primitive type (which
|
||||
* can only be bound in {@code args}) then an
|
||||
* {@code AmbiguousBindingException} is raised. If there is exactly
|
||||
* one argument of a primitive type, then if exactly one {@code args}
|
||||
* can only be bound in <code>args</code>) then an
|
||||
* <code>AmbiguousBindingException</code> is raised. If there is exactly
|
||||
* one argument of a primitive type, then if exactly one <code>args</code>
|
||||
* bound variable was found, we assign the corresponding parameter name
|
||||
* the variable name. If there were no {@code args} bound variables
|
||||
* found an {@code IllegalStateException} is raised. If there are
|
||||
* multiple {@code args} bound variables, an
|
||||
* {@code AmbiguousBindingException} is raised. At this point, if
|
||||
* the variable name. If there were no <code>args</code> bound variables
|
||||
* found an <code>IllegalStateException</code> is raised. If there are
|
||||
* multiple <code>args</code> bound variables, an
|
||||
* <code>AmbiguousBindingException</code> is raised. At this point, if
|
||||
* there remains more than one unbound argument we raise an
|
||||
* {@code AmbiguousBindingException}. If there are no unbound arguments
|
||||
* <code>AmbiguousBindingException</code>. If there are no unbound arguments
|
||||
* remaining, we are done. If there is exactly one unbound argument
|
||||
* remaining, and only one candidate variable name unbound from
|
||||
* {@code this}, {@code target}, or {@code args}, it is
|
||||
* <code>this</code>, <code>target</code>, or <code>args</code>, it is
|
||||
* assigned as the corresponding parameter name. If there are multiple
|
||||
* possibilities, an {@code AmbiguousBindingException} is raised.</li>
|
||||
* possibilities, an <code>AmbiguousBindingException</code> is raised.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>The behavior on raising an {@code IllegalArgumentException} or
|
||||
* {@code AmbiguousBindingException} is configurable to allow this discoverer
|
||||
* <p>The behavior on raising an <code>IllegalArgumentException</code> or
|
||||
* <code>AmbiguousBindingException</code> is configurable to allow this discoverer
|
||||
* to be used as part of a chain-of-responsibility. By default the condition will
|
||||
* be logged and the {@code getParameterNames(..)} method will simply return
|
||||
* {@code null}. If the {@link #setRaiseExceptions(boolean) raiseExceptions}
|
||||
* property is set to {@code true}, the conditions will be thrown as
|
||||
* {@code IllegalArgumentException} and {@code AmbiguousBindingException},
|
||||
* be logged and the <code>getParameterNames(..)</code> method will simply return
|
||||
* <code>null</code>. If the {@link #setRaiseExceptions(boolean) raiseExceptions}
|
||||
* property is set to <code>true</code>, the conditions will be thrown as
|
||||
* <code>IllegalArgumentException</code> and <code>AmbiguousBindingException</code>,
|
||||
* respectively.
|
||||
*
|
||||
* <p>Was that perfectly clear? ;)
|
||||
*
|
||||
* <p>Short version: If an unambiguous binding can be deduced, then it is.
|
||||
* If the advice requirements cannot possibly be satisfied, then {@code null}
|
||||
* If the advice requirements cannot possibly be satisfied, then <code>null</code>
|
||||
* is returned. By setting the {@link #setRaiseExceptions(boolean) raiseExceptions}
|
||||
* property to {@code true}, descriptive exceptions will be thrown instead of
|
||||
* returning {@code null} in the case that the parameter names cannot be discovered.
|
||||
* property to <code>true</code>, descriptive exceptions will be thrown instead of
|
||||
* returning <code>null</code> in the case that the parameter names cannot be discovered.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
@@ -142,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("&&");
|
||||
@@ -155,18 +156,24 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
|
||||
/** The pointcut expression associated with the advice, as a simple String */
|
||||
private String pointcutExpression;
|
||||
|
||||
private boolean raiseExceptions;
|
||||
|
||||
/** If the advice is afterReturning, and binds the return value, this is the parameter name used */
|
||||
/**
|
||||
* If the advice is afterReturning, and binds the return value, this is the parameter name used.
|
||||
*/
|
||||
private String returningName;
|
||||
|
||||
/** If the advice is afterThrowing, and binds the thrown value, this is the parameter name used */
|
||||
/**
|
||||
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
|
||||
*/
|
||||
private String throwingName;
|
||||
|
||||
private Class<?>[] argumentTypes;
|
||||
/**
|
||||
* The pointcut expression associated with the advice, as a simple String.
|
||||
*/
|
||||
private String pointcutExpression;
|
||||
|
||||
private Class[] argumentTypes;
|
||||
|
||||
private String[] parameterNameBindings;
|
||||
|
||||
@@ -181,18 +188,17 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
this.pointcutExpression = pointcutExpression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicate whether {@link IllegalArgumentException} and {@link AmbiguousBindingException}
|
||||
* must be thrown as appropriate in the case of failing to deduce advice parameter names.
|
||||
* @param raiseExceptions {@code true} if exceptions are to be thrown
|
||||
* @param raiseExceptions <code>true</code> if exceptions are to be thrown
|
||||
*/
|
||||
public void setRaiseExceptions(boolean raiseExceptions) {
|
||||
this.raiseExceptions = raiseExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code afterReturning} advice binds the return value, the
|
||||
* If <code>afterReturning</code> advice binds the return value, the
|
||||
* returning variable name must be specified.
|
||||
* @param returningName the name of the returning variable
|
||||
*/
|
||||
@@ -201,7 +207,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code afterThrowing} advice binds the thrown value, the
|
||||
* If <code>afterThrowing</code> advice binds the thrown value, the
|
||||
* throwing variable name must be specified.
|
||||
* @param throwingName the name of the throwing variable
|
||||
*/
|
||||
@@ -209,7 +215,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
this.throwingName = throwingName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deduce the parameter names for an advice method.
|
||||
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
|
||||
@@ -217,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;
|
||||
@@ -301,12 +305,11 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
|
||||
/**
|
||||
* An advice method can never be a constructor in Spring.
|
||||
* @return {@code null}
|
||||
* @return <code>null</code>
|
||||
* @throws UnsupportedOperationException if
|
||||
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
|
||||
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to <code>true</code>
|
||||
*/
|
||||
@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");
|
||||
}
|
||||
@@ -415,7 +418,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
String[] tokens = StringUtils.tokenizeToStringArray(this.pointcutExpression, " ");
|
||||
for (int i = 0; i < tokens.length; i++) {
|
||||
String toMatch = tokens[i];
|
||||
int firstParenIndex = toMatch.indexOf('(');
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
@@ -471,7 +474,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* If the token starts meets Java identifier conventions, it's in.
|
||||
*/
|
||||
private String maybeExtractVariableName(String candidateToken) {
|
||||
if (!StringUtils.hasLength(candidateToken)) {
|
||||
if (candidateToken == null || candidateToken.equals("")) {
|
||||
return null;
|
||||
}
|
||||
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
|
||||
@@ -490,7 +493,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an args pointcut body (could be {@code args} or {@code at_args}),
|
||||
* Given an args pointcut body (could be <code>args</code> or <code>at_args</code>),
|
||||
* add any candidate variable names to the given list.
|
||||
*/
|
||||
private void maybeExtractVariableNamesFromArgs(String argsSpec, List<String> varNames) {
|
||||
@@ -575,7 +578,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
if (toMatch.startsWith("!")) {
|
||||
toMatch = toMatch.substring(1);
|
||||
}
|
||||
int firstParenIndex = toMatch.indexOf('(');
|
||||
int firstParenIndex = toMatch.indexOf("(");
|
||||
if (firstParenIndex != -1) {
|
||||
toMatch = toMatch.substring(0, firstParenIndex);
|
||||
}
|
||||
@@ -649,7 +652,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
if (tokens[currentIndex].endsWith(")")) {
|
||||
sb.append(tokens[currentIndex], 0, tokens[currentIndex].length() - 1);
|
||||
sb.append(tokens[currentIndex].substring(0, tokens[currentIndex].length() - 1));
|
||||
return new PointcutBody(numTokensConsumed, sb.toString().trim());
|
||||
}
|
||||
|
||||
@@ -697,7 +700,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
// 1 primitive arg, and one candidate...
|
||||
for (int i = 0; i < this.argumentTypes.length; i++) {
|
||||
if (isUnbound(i) && this.argumentTypes[i].isPrimitive()) {
|
||||
bindParameterName(i, varNames.get(0));
|
||||
bindParameterName(i, (String) varNames.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -723,10 +726,10 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
/*
|
||||
* Return {@code true} if the given argument type is a subclass
|
||||
* Return <code>true</code> 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]);
|
||||
}
|
||||
|
||||
@@ -752,9 +755,9 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
|
||||
/*
|
||||
* Find the argument index with the given type, and bind the given
|
||||
* {@code varName} in that position.
|
||||
* <code>varName</code> 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);
|
||||
@@ -787,7 +790,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* Thrown in response to an ambiguous binding being detected when
|
||||
* trying to resolve a method's parameter names.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static class AmbiguousBindingException extends RuntimeException {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -30,18 +29,14 @@ 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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+6
-36
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-16
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -32,7 +32,7 @@ import org.springframework.aop.BeforeAdvice;
|
||||
public abstract class AspectJAopUtils {
|
||||
|
||||
/**
|
||||
* Return {@code true} if the advisor is a form of before advice.
|
||||
* Return <code>true</code> if the advisor is a form of before advice.
|
||||
*/
|
||||
public static boolean isBeforeAdvice(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
@@ -43,7 +43,7 @@ public abstract class AspectJAopUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the advisor is a form of after advice.
|
||||
* Return <code>true</code> if the advisor is a form of after advice.
|
||||
*/
|
||||
public static boolean isAfterAdvice(Advisor anAdvisor) {
|
||||
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
|
||||
@@ -56,7 +56,7 @@ public abstract class AspectJAopUtils {
|
||||
/**
|
||||
* Return the AspectJPrecedenceInformation provided by this advisor or its advice.
|
||||
* If neither the advisor nor the advice have precedence information, this method
|
||||
* will return {@code null}.
|
||||
* will return <code>null</code>.
|
||||
*/
|
||||
public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
|
||||
if (anAdvisor instanceof AspectJPrecedenceInformation) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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);
|
||||
|
||||
+125
-178
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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;
|
||||
@@ -28,7 +27,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
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;
|
||||
@@ -41,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,7 +55,6 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -77,7 +76,6 @@ import org.springframework.util.StringUtils;
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||
|
||||
@@ -99,16 +97,14 @@ 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<Method, ShadowMatch>(32);
|
||||
@@ -126,7 +122,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(
|
||||
@@ -140,37 +136,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;
|
||||
@@ -186,22 +179,18 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
if (this.pointcutExpression == null) {
|
||||
this.pointcutClassLoader = determinePointcutClassLoader();
|
||||
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
|
||||
this.pointcutExpression = buildPointcutExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the ClassLoader to use for pointcut evaluation.
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private ClassLoader determinePointcutClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
}
|
||||
if (this.pointcutDeclarationScope != null) {
|
||||
return this.pointcutDeclarationScope.getClassLoader();
|
||||
}
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
private PointcutExpression buildPointcutExpression() {
|
||||
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory)
|
||||
.getBeanClassLoader() : Thread.currentThread()
|
||||
.getContextClassLoader());
|
||||
return buildPointcutExpression(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,9 +201,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);
|
||||
}
|
||||
|
||||
@@ -232,9 +223,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
/**
|
||||
* If a pointcut expression has been specified in XML, the user cannot
|
||||
* write {@code and} as "&&" (though && will work).
|
||||
* We also allow {@code and} between two pointcut sub-expressions.
|
||||
* <p>This method converts back to {@code &&} for the AspectJ pointcut parser.
|
||||
* write <code>and</code> as "&&" (though && will work).
|
||||
* We also allow <code>and</code> between two pointcut sub-expressions.
|
||||
* <p>This method converts back to <code>&&</code> for the AspectJ pointcut parser.
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
String result = StringUtils.replace(pcExpr, " and ", " && ");
|
||||
@@ -252,30 +243,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);
|
||||
// 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 (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
}
|
||||
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);
|
||||
@@ -290,32 +281,21 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
return false;
|
||||
}
|
||||
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));
|
||||
// the maybe case
|
||||
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);
|
||||
@@ -336,67 +316,65 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
// TODO: Should we really proceed here?
|
||||
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);
|
||||
}
|
||||
@@ -417,58 +395,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(targetMethod);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the original method instead...
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader 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...
|
||||
else {
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Possibly AspectJ 1.8.10 encountering an invalid signature
|
||||
logger.debug("PointcutExpression matching rejected target method", ex);
|
||||
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);
|
||||
}
|
||||
@@ -530,10 +494,10 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the Spring-specific {@code bean()} pointcut designator
|
||||
* Handler for the Spring-specific <code>bean()</code> pointcut designator
|
||||
* extension to AspectJ.
|
||||
* <p>This handler must be added to each pointcut object that needs to
|
||||
* handle the {@code bean()} PCD. Matching context is obtained
|
||||
* handle the <code>bean()</code> PCD. Matching context is obtained
|
||||
* automatically by examining a thread local variable and therefore a matching
|
||||
* context need not be set on the pointcut.
|
||||
*/
|
||||
@@ -541,12 +505,10 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
private static final String BEAN_DESIGNATOR_NAME = "bean";
|
||||
|
||||
@Override
|
||||
public String getDesignatorName() {
|
||||
return BEAN_DESIGNATOR_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContextBasedMatcher parse(String expression) {
|
||||
return new BeanNameContextMatcher(expression);
|
||||
}
|
||||
@@ -568,40 +530,31 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
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
|
||||
return FuzzyBoolean.MAYBE;
|
||||
return FuzzyBoolean.MAYBE;
|
||||
}
|
||||
if (BeanFactoryUtils.isGeneratedBeanName(advisedBeanName)) {
|
||||
return FuzzyBoolean.NO;
|
||||
@@ -647,11 +600,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
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) {
|
||||
@@ -659,36 +610,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-27
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,53 +18,44 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
|
||||
/**
|
||||
* Spring AOP Advisor that can be used for any AspectJ pointcut expression.
|
||||
*
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware {
|
||||
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor {
|
||||
|
||||
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
public void setExpression(String expression) {
|
||||
this.pointcut.setExpression(expression);
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
public void setExpression(String expression) {
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
|
||||
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 setParameterNames(String... names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class<?>... types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.pointcut.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-9
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+6
-9
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -22,6 +22,7 @@ import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice}
|
||||
@@ -50,27 +51,23 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
this.pointcut = advice.buildSafePointcut();
|
||||
}
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@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;
|
||||
@@ -90,12 +87,12 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
return false;
|
||||
}
|
||||
AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other;
|
||||
return this.advice.equals(otherAdvisor.advice);
|
||||
return (ObjectUtils.nullSafeEquals(this.advice, otherAdvisor.advice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AspectJPointcutAdvisor.class.hashCode() * 29 + this.advice.hashCode();
|
||||
return AspectJPointcutAdvisor.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -30,14 +30,14 @@ import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AspectJProxyUtils {
|
||||
|
||||
|
||||
/**
|
||||
* Add special advisors if necessary to work with a proxy chain that contains AspectJ advisors.
|
||||
* This will expose the current Spring AOP invocation (necessary for some AspectJ pointcut matching)
|
||||
* and make available the current AspectJ JoinPoint. The call will have no effect if there are no
|
||||
* AspectJ advisors in the advisor chain.
|
||||
* @param advisors Advisors available
|
||||
* @return {@code true} if any special {@link Advisor Advisors} were added, otherwise {@code false}.
|
||||
* @return <code>true</code> if any special {@link Advisor Advisors} were added, otherwise <code>false</code>.
|
||||
*/
|
||||
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
|
||||
// Don't add advisors to an empty list; may indicate that proxying is just not required
|
||||
@@ -64,8 +64,8 @@ public abstract class AspectJProxyUtils {
|
||||
*/
|
||||
private static boolean isAspectJAdvice(Advisor advisor) {
|
||||
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
|
||||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
|
||||
(advisor instanceof PointcutAdvisor &&
|
||||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
|
||||
(advisor instanceof PointcutAdvisor &&
|
||||
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
|
||||
}
|
||||
|
||||
|
||||
+35
-33
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,13 +27,13 @@ import org.aspectj.bridge.IMessageHandler;
|
||||
* Implementation of AspectJ's {@link IMessageHandler} interface that
|
||||
* routes AspectJ weaving messages through the same logging system as the
|
||||
* regular Spring messages.
|
||||
*
|
||||
*
|
||||
* <p>Pass the option...
|
||||
*
|
||||
* <p><code class="code">-XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler</code>
|
||||
*
|
||||
* <p>to the weaver; for example, specifying the following in a
|
||||
* "{@code META-INF/aop.xml} file:
|
||||
* "<code>META-INF/aop.xml</code> file:
|
||||
*
|
||||
* <p><code class="code"><weaver options="..."/></code>
|
||||
*
|
||||
@@ -44,62 +44,64 @@ import org.aspectj.bridge.IMessageHandler;
|
||||
public class AspectJWeaverMessageHandler implements IMessageHandler {
|
||||
|
||||
private static final String AJ_ID = "[AspectJ] ";
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog("AspectJ Weaver");
|
||||
|
||||
|
||||
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) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(makeMessageFor(message));
|
||||
|
||||
if (LOGGER.isDebugEnabled() || LOGGER.isTraceEnabled()) {
|
||||
if (messageKind == IMessage.DEBUG) {
|
||||
LOGGER.debug(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
if ((messageKind == IMessage.INFO) || (messageKind == IMessage.WEAVEINFO)) {
|
||||
LOGGER.info(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isWarnEnabled()) {
|
||||
if (messageKind == IMessage.WARNING) {
|
||||
LOGGER.warn(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.INFO || messageKind == IMessage.WEAVEINFO) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(makeMessageFor(message));
|
||||
|
||||
if (LOGGER.isErrorEnabled()) {
|
||||
if (messageKind == IMessage.ERROR) {
|
||||
LOGGER.error(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.WARNING) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ERROR) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (messageKind == IMessage.ABORT) {
|
||||
if (logger.isFatalEnabled()) {
|
||||
logger.fatal(makeMessageFor(message));
|
||||
|
||||
if (LOGGER.isFatalEnabled()) {
|
||||
if (messageKind == IMessage.ABORT) {
|
||||
LOGGER.fatal(makeMessageFor(message));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String makeMessageFor(IMessage aMessage) {
|
||||
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...
|
||||
}
|
||||
|
||||
+22
-26
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -20,7 +20,6 @@ import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAdvisor;
|
||||
import org.springframework.aop.IntroductionInterceptor;
|
||||
import org.springframework.aop.support.ClassFilters;
|
||||
import org.springframework.aop.support.DelegatePerTargetObjectIntroductionInterceptor;
|
||||
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
@@ -35,12 +34,12 @@ import org.springframework.aop.support.DelegatingIntroductionInterceptor;
|
||||
*/
|
||||
public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
|
||||
private final Advice advice;
|
||||
|
||||
private final Class<?> introducedInterface;
|
||||
private final Class introducedInterface;
|
||||
|
||||
private final ClassFilter typePatternClassFilter;
|
||||
|
||||
private final Advice advice;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new advisor for this DeclareParents field.
|
||||
@@ -48,9 +47,9 @@ 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) {
|
||||
this(interfaceType, typePattern,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
public DeclareParentsAdvisor(Class interfaceType, String typePattern, Class defaultImpl) {
|
||||
this(interfaceType, typePattern, defaultImpl,
|
||||
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,56 +58,53 @@ 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) {
|
||||
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(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 interceptor the delegation advice as {@link IntroductionInterceptor}
|
||||
* @param implementationClass implementation class
|
||||
* @param advice delegation advice
|
||||
*/
|
||||
private DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, IntroductionInterceptor interceptor) {
|
||||
this.advice = interceptor;
|
||||
private DeclareParentsAdvisor(Class interfaceType, String typePattern, Class implementationClass, Advice advice) {
|
||||
this.introducedInterface = interfaceType;
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
|
||||
// Excludes methods implemented.
|
||||
ClassFilter typePatternFilter = new TypePatternClassFilter(typePattern);
|
||||
ClassFilter exclusion = new ClassFilter() {
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
return !introducedInterface.isAssignableFrom(clazz);
|
||||
public boolean matches(Class clazz) {
|
||||
return !(introducedInterface.isAssignableFrom(clazz));
|
||||
}
|
||||
};
|
||||
|
||||
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
|
||||
this.advice = advice;
|
||||
}
|
||||
|
||||
|
||||
@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};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
||||
+34
-69
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,20 +27,21 @@ 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;
|
||||
|
||||
/**
|
||||
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
|
||||
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
|
||||
* Implementation of AspectJ ProceedingJoinPoint interface
|
||||
* wrapping an AOP Alliance MethodInvocation.
|
||||
*
|
||||
* <p><b>Note</b>: The {@code getThis()} method returns the current Spring AOP proxy.
|
||||
* The {@code getTarget()} method returns the current Spring AOP target (which may be
|
||||
* {@code null} if there is no target instance) as a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use {@code getThis()}.</b>
|
||||
* A common example is casting the object to an introduced interface in the implementation of
|
||||
* an introduction. There is no such distinction between target and proxy in AspectJ itself.
|
||||
* <p><b>Note</b>: the <code>getThis()</code> method returns the current Spring AOP proxy.
|
||||
* The <code>getTarget()</code> method returns the current Spring AOP target (which may be
|
||||
* <code>null</code> if there is no target), and is a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use
|
||||
* <code>getThis()</code>.</b> A common example is casting the object to an
|
||||
* introduced interface in the implementation of an introduction.
|
||||
*
|
||||
* <p>Of course there is no such distinction between target and proxy in AspectJ.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -49,12 +50,10 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {
|
||||
|
||||
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||
|
||||
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
private Object[] args;
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
|
||||
/** Lazily initialized signature object */
|
||||
private Signature signature;
|
||||
@@ -73,18 +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) {
|
||||
@@ -97,38 +92,35 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring AOP proxy. Cannot be {@code null}.
|
||||
* Returns the Spring AOP proxy. Cannot be <code>null</code>.
|
||||
*/
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return this.methodInvocation.getProxy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Spring AOP target. May be {@code null} if there is no target.
|
||||
* Returns the Spring AOP target. May be <code>null</code> if there is no target.
|
||||
*/
|
||||
@Override
|
||||
public Object getTarget() {
|
||||
return this.methodInvocation.getThis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArgs() {
|
||||
if (this.args == null) {
|
||||
this.args = this.methodInvocation.getArguments().clone();
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
this.defensiveCopyOfArgs = new Object[argsSource.length];
|
||||
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
|
||||
}
|
||||
return this.args;
|
||||
return this.defensiveCopyOfArgs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Signature getSignature() {
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
}
|
||||
return this.signature;
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceLocation getSourceLocation() {
|
||||
if (this.sourceLocation == null) {
|
||||
this.sourceLocation = new SourceLocationImpl();
|
||||
@@ -136,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() + ")";
|
||||
}
|
||||
@@ -175,74 +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() {
|
||||
String[] parameterNames = this.parameterNames;
|
||||
if (parameterNames == null) {
|
||||
parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
|
||||
this.parameterNames = parameterNames;
|
||||
if (this.parameterNames == null) {
|
||||
this.parameterNames = (new LocalVariableTableParameterNameDiscoverer()).getParameterNames(getMethod());
|
||||
}
|
||||
return parameterNames;
|
||||
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()));
|
||||
@@ -256,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);
|
||||
@@ -297,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,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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;
|
||||
@@ -42,15 +39,15 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* This class encapsulates some AspectJ internal knowledge that should be
|
||||
* pushed back into the AspectJ project in a future release.
|
||||
* pushed back into the AspectJ project in a future release.
|
||||
*
|
||||
* <p>It relies on implementation specific knowledge in AspectJ to break
|
||||
* encapsulation and do something AspectJ was not designed to do: query
|
||||
* the types of runtime tests that will be performed. The code here should
|
||||
* migrate to {@code ShadowMatch.getVariablesInvolvedInRuntimeTest()}
|
||||
* migrate to <code>ShadowMatch.getVariablesInvolvedInRuntimeTest()</code>
|
||||
* 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,48 +160,31 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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,23 +228,20 @@ 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) {
|
||||
aTest.accept(this);
|
||||
return this.testsSubtypeSensitiveVars;
|
||||
}
|
||||
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-15
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -29,42 +29,38 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the specified aspect class (never {@code null}).
|
||||
* Return the specified aspect class (never <code>null</code>).
|
||||
*/
|
||||
public final Class<?> getAspectClass() {
|
||||
public final Class getAspectClass() {
|
||||
return this.aspectClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public final Object getAspectInstance() {
|
||||
try {
|
||||
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);
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return this.aspectClass.getClassLoader();
|
||||
}
|
||||
@@ -77,7 +73,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see #getOrderForAspectClass
|
||||
*/
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return getOrderForAspectClass(this.aspectClass);
|
||||
}
|
||||
@@ -86,7 +81,7 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
* 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}.
|
||||
* <p>The default implementation simply returns <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
|
||||
+5
-11
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -31,9 +29,8 @@ 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();
|
||||
@@ -77,7 +71,7 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
|
||||
* 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}.
|
||||
* <p>The default implementation simply returns <code>Ordered.LOWEST_PRECEDENCE</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
|
||||
+21
-24
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,7 +27,6 @@ import org.springframework.util.StringUtils;
|
||||
* Spring AOP {@link ClassFilter} implementation using AspectJ type matching.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TypePatternClassFilter implements ClassFilter {
|
||||
@@ -48,11 +47,11 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fully configured {@link TypePatternClassFilter} using the
|
||||
* Create a fully configured {@link TypePatternClassFilter} using the
|
||||
* given type pattern.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied {@code typePattern} is {@code null}
|
||||
* or is recognized as invalid
|
||||
* @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public TypePatternClassFilter(String typePattern) {
|
||||
setTypePattern(typePattern);
|
||||
@@ -69,50 +68,48 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* <code class="code">
|
||||
* org.springframework.beans.ITestBean+
|
||||
* </code>
|
||||
* This will match the {@code ITestBean} interface and any class
|
||||
* This will match the <code>ITestBean</code> interface and any class
|
||||
* that implements it.
|
||||
* <p>These conventions are established by AspectJ, not Spring AOP.
|
||||
* @param typePattern the type pattern that AspectJ weaver should parse
|
||||
* @throws IllegalArgumentException if the supplied {@code typePattern} is {@code null}
|
||||
* or is recognized as invalid
|
||||
* @throws IllegalArgumentException if the supplied <code>typePattern</code> is <code>null</code>
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public void setTypePattern(String typePattern) {
|
||||
Assert.notNull(typePattern, "Type pattern must not be null");
|
||||
Assert.notNull(typePattern);
|
||||
this.typePattern = typePattern;
|
||||
this.aspectJTypePatternMatcher =
|
||||
PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution().
|
||||
parseTypePattern(replaceBooleanOperators(typePattern));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AspectJ type pattern to match.
|
||||
*/
|
||||
public String getTypePattern() {
|
||||
return this.typePattern;
|
||||
return typePattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should the pointcut apply to the given interface or target class?
|
||||
* @param clazz candidate target class
|
||||
* @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) {
|
||||
Assert.state(this.aspectJTypePatternMatcher != null, "No type pattern has been set");
|
||||
public boolean matches(Class clazz) {
|
||||
if (this.aspectJTypePatternMatcher == null) {
|
||||
throw new IllegalStateException("No 'typePattern' has been set via ctor/setter.");
|
||||
}
|
||||
return this.aspectJTypePatternMatcher.matches(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a type pattern has been specified in XML, the user cannot
|
||||
* write {@code and} as "&&" (though && will work).
|
||||
* We also allow {@code and} between two sub-expressions.
|
||||
* <p>This method converts back to {@code &&} for the AspectJ pointcut parser.
|
||||
* write <code>and</code> as "&&" (though && will work).
|
||||
* We also allow <code>and</code> between two sub-expressions.
|
||||
* <p>This method converts back to <code>&&</code> for the AspectJ pointcut parser.
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
String result = StringUtils.replace(pcExpr," and "," && ");
|
||||
result = StringUtils.replace(result, " or ", " || ");
|
||||
return StringUtils.replace(result, " not ", " ! ");
|
||||
pcExpr = StringUtils.replace(pcExpr," and "," && ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
|
||||
return pcExpr;
|
||||
}
|
||||
}
|
||||
|
||||
+130
-69
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -38,8 +38,10 @@ import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.PrioritizedParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -56,26 +58,59 @@ import org.springframework.util.StringUtils;
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
|
||||
|
||||
protected static final ParameterNameDiscoverer ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER =
|
||||
new AspectJAnnotationParameterNameDiscoverer();
|
||||
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
|
||||
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
@@ -86,7 +121,7 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
|
||||
/**
|
||||
* We need to detect this as "code-style" AspectJ aspects should not be
|
||||
* interpreted by Spring AOP.
|
||||
* interpreted by Spring AOP.
|
||||
*/
|
||||
private boolean compiledByAjc(Class<?> clazz) {
|
||||
// The AJTypeSystem goes to great lengths to provide a uniform appearance between code-style and
|
||||
@@ -100,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 &&
|
||||
@@ -120,42 +154,58 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {
|
||||
throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " +
|
||||
"This is not supported in Spring AOP.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...).
|
||||
* The pointcut and advice annotations both have an "argNames" member which contains a
|
||||
* comma-separated list of the argument names. We use this (if non-empty) to build the
|
||||
* formal parameters for the pointcut.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
protected AspectJExpressionPointcut createPointcutExpression(
|
||||
Method annotatedMethod, Class declarationScope, String[] pointcutParameterNames) {
|
||||
|
||||
Class<?> [] pointcutParameterTypes = new Class<?>[0];
|
||||
if (pointcutParameterNames != null) {
|
||||
pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod);
|
||||
}
|
||||
return null;
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes);
|
||||
ajexp.setLocation(annotatedMethod.toString());
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Enum for AspectJ annotation types.
|
||||
* @see AspectJAnnotation#getAnnotationType()
|
||||
* Create the pointcut parameters needed by aspectj based on the given argument names
|
||||
* and the argument types that are available from the adviceMethod. Needs to take into
|
||||
* account (ignore) any JoinPoint based arguments as these are not pointcut context but
|
||||
* rather part of the advice execution context (thisJoinPoint, thisJoinPointStaticPart)
|
||||
*/
|
||||
private Class<?>[] extractPointcutParameterTypes(String[] argNames, Method adviceMethod) {
|
||||
Class<?>[] ret = new Class<?>[argNames.length];
|
||||
Class<?>[] paramTypes = adviceMethod.getParameterTypes();
|
||||
if (argNames.length > paramTypes.length) {
|
||||
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;
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = paramTypes[i + typeOffset];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
AtAfterReturning,
|
||||
AtAfterThrowing,
|
||||
AtAround
|
||||
}
|
||||
|
||||
|
||||
@@ -165,18 +215,18 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
*/
|
||||
protected static class AspectJAnnotation<A extends Annotation> {
|
||||
|
||||
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
|
||||
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
|
||||
|
||||
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap =
|
||||
new HashMap<Class<?>, AspectJAnnotationType>(8);
|
||||
private static Map<Class, AspectJAnnotationType> annotationTypes =
|
||||
new HashMap<Class, AspectJAnnotationType>();
|
||||
|
||||
static {
|
||||
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
|
||||
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
|
||||
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
|
||||
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
|
||||
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
|
||||
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
|
||||
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
|
||||
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
|
||||
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
|
||||
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
|
||||
}
|
||||
|
||||
private final A annotation;
|
||||
@@ -190,31 +240,44 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
public AspectJAnnotation(A annotation) {
|
||||
this.annotation = annotation;
|
||||
this.annotationType = determineAnnotationType(annotation);
|
||||
// We know these methods exist with the same name on each object,
|
||||
// but need to invoke them reflectively as there isn't a common interface.
|
||||
try {
|
||||
this.pointcutExpression = resolveExpression(annotation);
|
||||
this.argumentNames = (String) AnnotationUtils.getValue(annotation, "argNames");
|
||||
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
|
||||
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private AspectJAnnotationType determineAnnotationType(A annotation) {
|
||||
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation);
|
||||
}
|
||||
|
||||
private String resolveExpression(A annotation) {
|
||||
for (String attributeName : EXPRESSION_ATTRIBUTES) {
|
||||
String candidate = (String) AnnotationUtils.getValue(annotation, attributeName);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
return candidate;
|
||||
for (Class type : annotationTypes.keySet()) {
|
||||
if (type.isInstance(annotation)) {
|
||||
return annotationTypes.get(type);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to resolve expression: " + annotation);
|
||||
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
|
||||
}
|
||||
|
||||
private String resolveExpression(A annotation) throws Exception {
|
||||
String expression = null;
|
||||
for (String methodName : EXPRESSION_PROPERTIES) {
|
||||
Method method;
|
||||
try {
|
||||
method = annotation.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
method = null;
|
||||
}
|
||||
if (method != null) {
|
||||
String candidate = (String) method.invoke(annotation);
|
||||
if (StringUtils.hasText(candidate)) {
|
||||
expression = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
public AspectJAnnotationType getAnnotationType() {
|
||||
@@ -246,30 +309,28 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
*/
|
||||
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
|
||||
@Override
|
||||
public String[] getParameterNames(Method method) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
return new String[0];
|
||||
}
|
||||
AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
|
||||
AspectJAnnotation annotation = findAspectJAnnotationOnMethod(method);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (nameTokens.countTokens() > 0) {
|
||||
String[] names = new String[nameTokens.countTokens()];
|
||||
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
|
||||
if (strTok.countTokens() > 0) {
|
||||
String[] names = new String[strTok.countTokens()];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = nameTokens.nextToken();
|
||||
names[i] = strTok.nextToken();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterNames(Constructor<?> ctor) {
|
||||
|
||||
public String[] getParameterNames(Constructor ctor) {
|
||||
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-11
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -45,12 +45,11 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
|
||||
|
||||
private List<Pattern> includePatterns;
|
||||
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory;
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
|
||||
|
||||
@@ -67,16 +66,13 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
super.initBeanFactory(beanFactory);
|
||||
if (this.aspectJAdvisorFactory == null) {
|
||||
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
|
||||
}
|
||||
this.aspectJAdvisorsBuilder =
|
||||
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
|
||||
}
|
||||
@@ -92,7 +88,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
|
||||
@@ -107,7 +103,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
/**
|
||||
* Check whether the given aspect bean is eligible for auto-proxying.
|
||||
* <p>If no <aop:include> elements were used then "includePatterns" will be
|
||||
* {@code null} and all beans are included. If "includePatterns" is non-null,
|
||||
* <code>null</code> and all beans are included. If "includePatterns" is non-null,
|
||||
* then one of the patterns must match.
|
||||
*/
|
||||
protected boolean isEligibleAspectBean(String beanName) {
|
||||
@@ -133,7 +129,6 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
|
||||
public BeanFactoryAspectJAdvisorsBuilderAdapter(
|
||||
ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
|
||||
|
||||
super(beanFactory, advisorFactory);
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -40,7 +40,7 @@ public interface AspectJAdvisorFactory {
|
||||
/**
|
||||
* Determine whether or not the given class is an aspect, as reported
|
||||
* by AspectJ's {@link org.aspectj.lang.reflect.AjTypeSystem}.
|
||||
* <p>Will simply return {@code false} if the supposed aspect is
|
||||
* <p>Will simply return <code>false</code> if the supposed aspect is
|
||||
* invalid (such as an extension of a concrete aspect class).
|
||||
* Will return true for some aspects that Spring AOP cannot process,
|
||||
* such as those with unsupported instantiation models.
|
||||
@@ -63,33 +63,33 @@ 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
|
||||
* @return <code>null</code> 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
|
||||
* @return <code>null</code> 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
|
||||
* @see org.springframework.aop.aspectj.AspectJAroundAdvice
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
+30
-37
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.aop.aspectj.AspectJProxyUtils;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyCreatorSupport;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -46,11 +46,10 @@ import org.springframework.util.ClassUtils;
|
||||
* @see #getProxy(ClassLoader)
|
||||
* @see org.springframework.aop.framework.ProxyFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/** Cache for singleton aspect instances */
|
||||
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<Class<?>, Object>();
|
||||
private static final Map<Class, Object> aspectCache = new HashMap<Class, Object>();
|
||||
|
||||
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
@@ -73,10 +72,10 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code AspectJProxyFactory}.
|
||||
* Create a new <code>AspectJProxyFactory</code>.
|
||||
* No target, only interfaces. Must add interceptors.
|
||||
*/
|
||||
public AspectJProxyFactory(Class<?>... interfaces) {
|
||||
public AspectJProxyFactory(Class[] interfaces) {
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
|
||||
@@ -89,7 +88,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 +103,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);
|
||||
@@ -115,20 +114,20 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
/**
|
||||
* Add all {@link Advisor Advisors} from the supplied {@link MetadataAwareAspectInstanceFactory}
|
||||
* to the current chain. Exposes any special purpose {@link Advisor Advisors} if needed.
|
||||
* @see AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary(List)
|
||||
* @see #makeAdvisorChainAspectJCapableIfNecessary()
|
||||
*/
|
||||
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
|
||||
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,9 +141,9 @@ 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;
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = null;
|
||||
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
// Create a shared aspect instance.
|
||||
Object instance = getSingletonAspectInstance(aspectClass);
|
||||
@@ -161,30 +160,24 @@ 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) {
|
||||
// Quick check without a lock...
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
synchronized (aspectCache) {
|
||||
// To be safe, check within full lock now...
|
||||
instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + aspectClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + aspectClass.getName(), ex);
|
||||
}
|
||||
}
|
||||
private Object getSingletonAspectInstance(Class aspectClass) {
|
||||
synchronized (aspectCache) {
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+33
-51
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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;
|
||||
@@ -35,35 +31,21 @@ import org.springframework.aop.support.ComposablePointcut;
|
||||
* Metadata for an AspectJ aspect class, with an additional Spring AOP pointcut
|
||||
* for the per clause.
|
||||
*
|
||||
* <p>Uses AspectJ 5 AJType reflection API, enabling us to work with different
|
||||
* AspectJ instantiation models such as "singleton", "pertarget" and "perthis".
|
||||
* <p>Uses AspectJ 5 AJType reflection API, so is only supported on Java 5.
|
||||
* Enables us to work with different AspectJ instantiation models such as
|
||||
* "singleton", "pertarget" and "perthis".
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @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
|
||||
@@ -72,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.
|
||||
@@ -82,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;
|
||||
@@ -94,40 +83,39 @@ 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:
|
||||
case SINGLETON :
|
||||
this.perClausePointcut = Pointcut.TRUE;
|
||||
return;
|
||||
case PERTARGET:
|
||||
case PERTHIS:
|
||||
case PERTARGET : case PERTHIS :
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setLocation(aspectClass.getName());
|
||||
ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
|
||||
ajexp.setExpression(findPerClause(aspectClass));
|
||||
ajexp.setPointcutDeclarationScope(aspectClass);
|
||||
this.perClausePointcut = ajexp;
|
||||
return;
|
||||
case PERTYPEWITHIN:
|
||||
case PERTYPEWITHIN :
|
||||
// Works with a type pattern
|
||||
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
|
||||
return;
|
||||
default:
|
||||
default :
|
||||
throw new AopConfigException(
|
||||
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract contents from String of form {@code pertarget(contents)}.
|
||||
* Extract contents from String of form <code>pertarget(contents)</code>.
|
||||
*/
|
||||
private String findPerClause(Class<?> aspectClass) {
|
||||
// TODO when AspectJ provides this, we can remove this hack. Hence we don't
|
||||
// bother to make it elegant. Or efficient. Or robust :-)
|
||||
String str = aspectClass.getAnnotation(Aspect.class).value();
|
||||
str = str.substring(str.indexOf('(') + 1);
|
||||
str = str.substring(str.indexOf("(") + 1);
|
||||
str = str.substring(0, str.length() - 1);
|
||||
return str;
|
||||
}
|
||||
@@ -136,19 +124,19 @@ 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the aspect name.
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public String getAspectName() {
|
||||
return this.aspectName;
|
||||
@@ -156,7 +144,7 @@ public class AspectMetadata implements Serializable {
|
||||
|
||||
/**
|
||||
* Return a Spring pointcut expression for a singleton aspect.
|
||||
* (e.g. {@code Pointcut.TRUE} if it's a singleton).
|
||||
* (e.g. <code>Pointcut.TRUE</code> if it's a singleton).
|
||||
*/
|
||||
public Pointcut getPerClausePointcut() {
|
||||
return this.perClausePointcut;
|
||||
@@ -185,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-38
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,13 +16,10 @@
|
||||
|
||||
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.Order;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -30,7 +27,7 @@ import org.springframework.util.ClassUtils;
|
||||
* backed by a Spring {@link org.springframework.beans.factory.BeanFactory}.
|
||||
*
|
||||
* <p>Note that this may instantiate multiple times if using a prototype,
|
||||
* which probably won't give the semantics you expect.
|
||||
* which probably won't give the semantics you expect.
|
||||
* Use a {@link LazySingletonAspectInstanceFactoryDecorator}
|
||||
* to wrap this to ensure only one new aspect comes back.
|
||||
*
|
||||
@@ -40,8 +37,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;
|
||||
|
||||
@@ -60,7 +56,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
|
||||
this(beanFactory, name, beanFactory.getType(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a BeanFactoryAspectInstanceFactory, providing a type that AspectJ should
|
||||
* introspect to create AJType metadata. Use if the BeanFactory may consider the type
|
||||
@@ -69,49 +65,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() {
|
||||
if (this.beanFactory != null) {
|
||||
if (this.beanFactory.isSingleton(name)) {
|
||||
// Rely on singleton semantics provided by the factory -> no local lock.
|
||||
return null;
|
||||
}
|
||||
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's target aspect, either
|
||||
* an instance-specific order expressed through implementing the
|
||||
@@ -122,14 +99,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 = type.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
+50
-51
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,10 +17,10 @@
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
@@ -43,12 +43,12 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private final AspectJAdvisorFactory advisorFactory;
|
||||
|
||||
private volatile List<String> aspectBeanNames;
|
||||
private List<String> aspectBeanNames;
|
||||
|
||||
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<String, List<Advisor>>();
|
||||
private final Map<String, List<Advisor>> advisorsCache = new HashMap<String, List<Advisor>>();
|
||||
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
|
||||
new ConcurrentHashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
new HashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,7 +56,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
* @param beanFactory the ListableBeanFactory to scan
|
||||
*/
|
||||
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
|
||||
this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
|
||||
this(beanFactory, new ReflectiveAspectJAdvisorFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,62 +80,61 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
* @see #isEligibleBean
|
||||
*/
|
||||
public List<Advisor> buildAspectJAdvisors() {
|
||||
List<String> aspectNames = this.aspectBeanNames;
|
||||
List<String> aspectNames = null;
|
||||
|
||||
if (aspectNames == null) {
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
if (!isEligibleBean(beanName)) {
|
||||
continue;
|
||||
}
|
||||
// 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);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
if (!isEligibleBean(beanName)) {
|
||||
continue;
|
||||
}
|
||||
// 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);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
}
|
||||
this.aspectBeanNames = aspectNames;
|
||||
return advisors;
|
||||
}
|
||||
this.aspectBeanNames = aspectNames;
|
||||
return advisors;
|
||||
}
|
||||
}
|
||||
|
||||
if (aspectNames.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (String aspectName : aspectNames) {
|
||||
|
||||
+78
-115
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2018 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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,119 +37,79 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The pointcut for Spring AOP to use.
|
||||
* Actual behaviour of the pointcut will change depending on the state of the advice.
|
||||
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
|
||||
* depending on the state of the advice.
|
||||
*/
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
@Override
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is only of interest for Spring AOP: AspectJ instantiation semantics
|
||||
* are much richer. In AspectJ terminology, all a return of {@code true}
|
||||
* are much richer. In AspectJ terminology, all a return of <code>true</code>
|
||||
* means here is that the aspect is not a SINGLETON.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the AspectJ AspectMetadata for this advisor.
|
||||
*/
|
||||
@@ -160,6 +117,30 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.aspectInstanceFactory.getAspectMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily instantiate advice if necessary.
|
||||
*/
|
||||
public synchronized Advice getAdvice() {
|
||||
if (this.instantiatedAdvice == null) {
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
}
|
||||
return this.instantiatedAdvice;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return this.lazy;
|
||||
}
|
||||
|
||||
public synchronized boolean isAdviceInstantiated() {
|
||||
return (this.instantiatedAdvice != null);
|
||||
}
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.atAspectJAdvisorFactory.getAdvice(
|
||||
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
return this.aspectInstanceFactory;
|
||||
}
|
||||
@@ -168,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();
|
||||
@@ -191,7 +168,6 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
return this.isBeforeAdvice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAfterAdvice() {
|
||||
if (this.isAfterAdvice == null) {
|
||||
determineAdviceType();
|
||||
@@ -205,55 +181,45 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
*/
|
||||
private void determineAdviceType() {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
|
||||
if (aspectJAnnotation == null) {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
}
|
||||
else {
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
case AtAround:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isBeforeAdvice = true;
|
||||
this.isAfterAdvice = false;
|
||||
break;
|
||||
case AtAfter:
|
||||
case AtAfterReturning:
|
||||
case AtAfterThrowing:
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = true;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtAround:
|
||||
case AtPointcut:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = false;
|
||||
break;
|
||||
case AtBefore:
|
||||
this.isAfterAdvice = false;
|
||||
this.isBeforeAdvice = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
"]; advice method [" + this.method + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
|
||||
* if it does not at first match statically.
|
||||
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
|
||||
* be optimized out if it does not at first match statically.
|
||||
*/
|
||||
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
|
||||
|
||||
@@ -263,9 +229,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
|
||||
|
||||
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
|
||||
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
this.preInstantiationPointcut = preInstantiationPointcut;
|
||||
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
|
||||
@@ -274,15 +239,13 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
// We're either instantiated and matching on declared pointcut,
|
||||
// or uninstantiated matching on either pointcut...
|
||||
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));
|
||||
}
|
||||
|
||||
+7
-25
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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,18 +42,11 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
public synchronized Object getAspectInstance() {
|
||||
if (this.materialized == null) {
|
||||
Object mutex = this.maaif.getAspectCreationMutex();
|
||||
if (mutex == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
else {
|
||||
synchronized (mutex) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,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();
|
||||
}
|
||||
|
||||
+2
-9
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -39,11 +39,4 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
|
||||
*/
|
||||
AspectMetadata getAspectMetadata();
|
||||
|
||||
/**
|
||||
* Return the best possible creation mutex for this factory.
|
||||
* @return the mutex object (may be {@code null} for no mutex to use)
|
||||
* @since 4.3
|
||||
*/
|
||||
Object getAspectCreationMutex();
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -26,7 +26,6 @@ import org.springframework.aop.framework.AopConfigException;
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NotAnAtAspectException extends AopConfigException {
|
||||
|
||||
private Class<?> nonAspectClass;
|
||||
|
||||
+5
-8
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -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
|
||||
|
||||
+44
-86
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
@@ -46,7 +45,6 @@ import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.DeclareParentsAdvisor;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConvertingComparator;
|
||||
@@ -67,8 +65,7 @@ import org.springframework.util.comparator.InstanceComparator;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory {
|
||||
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
@@ -78,15 +75,13 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
new InstanceComparator<Annotation>(
|
||||
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
|
||||
new Converter<Method, Annotation>() {
|
||||
@Override
|
||||
public Annotation convert(Method method) {
|
||||
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (ann != null ? ann.getAnnotation() : null);
|
||||
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return annotation == null ? null : annotation.getAnnotation();
|
||||
}
|
||||
}));
|
||||
comparator.addComparator(new ConvertingComparator<Method, String>(
|
||||
new Converter<Method, String>() {
|
||||
@Override
|
||||
public String convert(Method method) {
|
||||
return method.getName();
|
||||
}
|
||||
@@ -95,42 +90,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code ReflectiveAspectJAdvisorFactory}.
|
||||
*/
|
||||
public ReflectiveAspectJAdvisorFactory() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ReflectiveAspectJAdvisorFactory}, propagating the given
|
||||
* {@link BeanFactory} to the created {@link AspectJExpressionPointcut} instances,
|
||||
* for bean pointcut handling as well as consistent {@link ClassLoader} resolution.
|
||||
* @param beanFactory the BeanFactory to propagate (may be {@code null}}
|
||||
* @since 4.3.6
|
||||
* @see AspectJExpressionPointcut#setBeanFactory
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader()
|
||||
*/
|
||||
public ReflectiveAspectJAdvisorFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@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 ArrayList<Advisor>();
|
||||
final List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
@@ -156,9 +126,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
|
||||
final List<Method> methods = new ArrayList<Method>();
|
||||
final List<Method> methods = new LinkedList<Method>();
|
||||
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException {
|
||||
// Exclude pointcuts
|
||||
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
|
||||
@@ -175,7 +144,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
* for the given introduction field.
|
||||
* <p>Resulting Advisors will need to be evaluated for targets.
|
||||
* @param introductionField the field to introspect
|
||||
* @return the Advisor instance, or {@code null} if not an Advisor
|
||||
* @return <code>null</code> if not an Advisor
|
||||
*/
|
||||
private Advisor getDeclareParentsAdvisor(Field introductionField) {
|
||||
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
|
||||
@@ -184,8 +153,10 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DeclareParents.class == declareParents.defaultImpl()) {
|
||||
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
|
||||
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");
|
||||
}
|
||||
|
||||
return new DeclareParentsAdvisor(
|
||||
@@ -193,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) {
|
||||
@@ -215,20 +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());
|
||||
ajexp.setBeanFactory(this.beanFactory);
|
||||
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 =
|
||||
@@ -237,7 +203,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we get here, we know we have an AspectJ method.
|
||||
// If we get here, we know we have an AspectJ method.
|
||||
// Check that it's an AspectJ-annotated class
|
||||
if (!isAspect(candidateAspectClass)) {
|
||||
throw new AopConfigException("Advice must be declared inside an aspect type: " +
|
||||
@@ -252,57 +218,50 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
AbstractAspectJAdvice springAdvice;
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
return null;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
break;
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
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, ajexp, aif);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
|
||||
}
|
||||
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);
|
||||
}
|
||||
springAdvice.calculateArgumentBindings();
|
||||
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synthetic advisor that instantiates the aspect.
|
||||
* Triggered by per-clause pointcut on non-singleton aspect.
|
||||
@@ -313,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
-11
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,7 +18,7 @@ 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.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that
|
||||
@@ -39,25 +39,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</code>.
|
||||
* @param aspectClass the aspect class
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-14
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
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.Order;
|
||||
|
||||
/**
|
||||
* Implementation of {@link MetadataAwareAspectInstanceFactory} that is backed
|
||||
@@ -32,9 +30,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 +47,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</code>.
|
||||
* @see org.springframework.core.annotation.Order
|
||||
*/
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
Order order = aspectClass.getAnnotation(Order.class);
|
||||
if (order != null) {
|
||||
return order.value();
|
||||
}
|
||||
return Ordered.LOWEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,6 +1,10 @@
|
||||
|
||||
/**
|
||||
* Classes enabling AspectJ 5 @Annotated classes to be used in Spring AOP.
|
||||
*
|
||||
* 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;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user