Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Buildmaster 917e9a6ef3 Release version 5.0.0.RC2 2017-06-14 09:50:06 +00:00
8084 changed files with 134455 additions and 265466 deletions
-17
View File
@@ -1,17 +0,0 @@
<!--
!!! For Security Vulnerabilities, please go to https://pivotal.io/security !!!
-->
**Affects:** \<Spring Framework version>
---
<!--
Thanks for taking the time to create an issue. Please read the following:
- Questions should be asked on Stack Overflow.
- For bugs, specify affected versions and explain what you are trying to do.
- For enhancements, provide context and describe the problem.
Issue or Pull Request? Create only one, not both. GitHub treats them as the same.
If unsure, start with an issue, and if you submit a pull request later, the
issue will be closed as superseded.
-->
@@ -0,0 +1,9 @@
#com.springsource.sts.gradle.core.preferences.GradleImportPreferences
#Thu Aug 9 11:34:43 CEST 2012
enableAfterTasks=true
afterTasks=afterEclipseImport;
enableDependendencyManagement=false
enableBeforeTasks=true
projects=;spring-aop;spring-aspects;spring-beans;spring-context;spring-context-support;spring-core;spring-expression;spring-instrument;spring-instrument-tomcat;spring-jdbc;spring-jms;spring-orm;spring-oxm;spring-struts;spring-test;spring-tx;spring-web;spring-webmvc;spring-webmvc-portlet;
enableDSLD=false
beforeTasks=cleanEclipse;eclipse;\:spring-oxm\:compileTestJava;
@@ -0,0 +1,5 @@
#com.springsource.sts.gradle.core.preferences.GradleProjectPreferences
#Tue Feb 21 14:38:31 CET 2012
com.springsource.sts.gradle.classpath.enableSorting=false
com.springsource.sts.gradle.rootprojectloc=
com.springsource.sts.gradle.linkedresources=
@@ -0,0 +1,9 @@
#com.springsource.sts.gradle.core.actions.GradleRefreshPreferences
#Thu Aug 9 11:34:43 CEST 2012
enableAfterTasks=true
afterTasks=afterEclipseImport;
useHierarchicalNames=false
enableBeforeTasks=true
addResourceFilters=false
enableDSLD=false
beforeTasks=cleanEclipse;eclipse;\:spring-oxm\:compileTestJava;
+2 -2
View File
@@ -40,5 +40,5 @@ appropriate to the circumstances. Maintainers are obligated to maintain confiden
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/]
http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
+51
View File
@@ -0,0 +1,51 @@
= How to contribute to the reference
The Spring Framework reference now uses http://asciidoctor.org/[asciidoctor]. This
document describes how to contribute documentation updates.
== Building with Gradle
You can build the documentation using gradle using the `reference` task. For example, from
the project root execute the following command:
./gradlew reference
the output will be available at `spring-framework/build/reference/htmlsingle/index.html`
== Live editing
One of the nice features about using asciidoctor is the support for live editing.
You will find a Guardfile already present at `spring-framework/src/asciidoc/Guardfile`.
Make sure first to follow the setup instructions within the
http://asciidoctor.org/docs/editing-asciidoc-with-live-preview/[Editing AsciiDoc with Live Preview]
document. Once you have done that, there are additional gems to install to make it work
(assuming that you are using http://livereload.com/[LiveReload]):
gem install guard-rspec guard-livereload
When running `guard start` within the `src/asciidoc/` folder, any changes to the
`src/asciidoc/index.adoc` file will automatically be written at
`src/asciidoc/build/index.html`.
== Troubleshooting
* If you are using LiveReload, make sure to select _Allow access to file URLs_ in the
LiveEdit plugin options of your browser.
* The icon used to enable _LiveReload_ can be a bit confusing. The dot is empty when it is
disabled and full when the plugin is active. Make sure to enable it on the tab
displaying the `index.html` file.
* Ensure you are _not_ running guard start at all as two instances could not run at the
same time. To exit a current session in a clean way, just type e in the shell.
== Documentation notes
Some notes on documentation
* Documentation is wrapped at 90 chars, ensure that you manually wrap your edits
* Tabs are used for indentation, do not use spaces
* Follow the existing style when inserting `source` blocks
* http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[Asciidoctor Quick Reference]
* http://asciidoctor.org/docs/user-manual/[Asciidoctor Manual]
* http://asciidoctor.org/docs/asciidoc-writers-guide/[Asciidoctor Writers Guide]
+268 -90
View File
@@ -1,126 +1,304 @@
# Contributing to the Spring Framework
_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
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._
First off, thank you for taking the time to contribute! :+1: :tada:
_Please refer back to this document as a checklist before issuing any pull
request; this will save time for everyone!_
### Table of Contents
## 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.
* [Code of Conduct](#code-of-conduct)
* [How to Contribute](#how-to-contribute)
* [Discuss](#discuss)
* [Create a Ticket](#create-a-ticket)
* [Ticket Lifecycle](#ticket-lifecycle)
* [Submit a Pull Request](#submit-a-pull-request)
* [Build from Source](#build-from-source)
* [Source Code Style](#source-code-style)
* [Reference Docs](#reference-docs)
## Take Your First Steps
### Code of Conduct
### Understand the basics
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc).
By participating you are expected to uphold this code.
Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
excellent [help documentation][] first.
### How to Contribute
### Search Stack Overflow first; discuss if necessary
#### Discuss
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.
If you have a question, check StackOverflow using
[this list of tags](https://spring.io/questions), organized by Spring project.
Find an existing discussion or start a new one if necessary.
### Search JIRA; create an issue if necessary
If you suspect an issue, perform a search in the
[GitHub issue tracker](https://github.com/spring-projects/spring-framework/issues), using a few different keywords.
When you find related issues and discussions, prior or current, it helps you to learn and
it helps us to make a decision.
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.
#### Create a Ticket
### Sign the Contributor License Agreement (CLA)
Reporting an issue or making a feature request is a great way to contribute. Your feedback
and the conversations that result from it provide a continuous flow of ideas.
If you have not previously done so, please sign the [Contributor License Agreement][].
If you forget to do so, you'll be reminded when you submit a pull request.
Before you create a ticket, please take the time to [research first](#discuss).
## Create a Branch
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
### Branch from `master`
When ready create a ticket in the [GitHub issue tracker](https://github.com/spring-projects/spring-framework/issues).
Master currently represents work toward Spring Framework 5.0. Please submit
all pull requests there, even bug fixes and minor improvements. Backports to
`4.3.x` will be considered on a case-by-case basis.
#### Ticket Lifecycle
When an issue is first created, it is flagged `waiting-for-triage` waiting for a team
member to triage it. Within a day or two, the issue will then be reviewed and the team
may ask for further information if needed. Based on the findings, the issue is either
assigned a fix version or declined.
### Use short branch names
When a fix is ready, the issue is closed and may still be re-opened. Once a fix is
released, the issue can't be reopened. If necessary, you will need to create a new,
related ticket with a fresh description.
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.
#### Submit a Pull Request
## Use Spring Framework Code Style
You can contribute a source code change by submitting a pull request.
The complete [Spring Framework Code Style][] reference is available on the wiki, but
here's a quick summary:
1. If you have not previously done so, please sign the
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
automatically when you submit a pull request.
### Mind the whitespace
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
The purpose of the ticket is to understand and discuss the underlying issue or feature.
We use the GitHub issue tracker as the preferred place of record for conversations and
conclusions. In that sense discussions directly under a PR are more implementation detail
oriented and transient in nature.
Please carefully follow the whitespace and formatting conventions already
present in the framework.
1. Always check out the `master` branch and submit pull requests against it
(for target version see [settings.gradle](settings.gradle)).
Backports to prior versions will be considered on a case-by-case basis and reflected as
the fix version in the issue tracker.
1. Tabs, not spaces
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
1. Use short branch names, preferably based on the GitHub issue (e.g. `22276`), or
otherwise using succinct, lower-case, dash (-) delimited names, such as `fix-warnings`.
1. Choose the granularity of your commits consciously and squash commits that represent
multiple edits or corrections of the same logical change. See
[Rewriting History section of Pro Git](https://git-scm.com/book/en/Git-Tools-Rewriting-History)
for an overview of streamlining commit history.
### Add Apache license header to all new classes
1. Format commit messages using 55 characters for the subject line, 72 characters per line
for the description, followed by the issue fixed, e.g. `Closes gh-22276`. See the
[Commit Guidelines section of Pro Git](https://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines)
for best practices around commit messages and use `git log` to see some examples.
```java
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
1. List the GitHub issue number in the PR description.
package ...;
```
If accepted, your contribution may be heavily modified as needed prior to merging.
You will likely retain author attribution for your Git commits granted that the bulk of
your changes remain intact. You may also be asked to rework the submission.
### Update Apache license header in modified files as necessary
If asked to make corrections, simply push the changes against the same branch, and your
pull request will be updated. In other words, you do not need to create a new pull request
when asked to make changes.
Always check the date range in the license header. For example, if you've
modified a file in 2017 whose header still reads:
### Build from Source
```java
/*
* Copyright 2002-2011 the original author or authors.
```
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source)
wiki page for instructions on how to check out, build, and import the Spring Framework
source code into your IDE.
Then be sure to update it to 2017 accordingly:
### Source Code Style
```java
/*
* Copyright 2002-2017 the original author or authors.
```
The wiki pages
[Code Style](https://github.com/spring-projects/spring-framework/wiki/Code-Style) and
[IntelliJ IDEA Editor Settings](https://github.com/spring-projects/spring-framework/wiki/IntelliJ-IDEA-Editor-Settings)
defines the source file coding standards we use along with some IDEA editor settings we customize.
### Use @since tags for newly-added public API types and methods
### Reference Docs
For example:
The reference documentation is in the [src/docs/asciidoc](src/docs/asciidoc) directory and, in
[Asciidoctor](https://asciidoctor.org/) format. For trivial changes, you may be able to browse,
edit source files, and submit directly from GitHub.
```java
/**
* ...
*
* @author First Last
* @since 5.0
* @see ...
*/
```
When making changes locally, use `./gradlew asciidoctor` and then browse the result under
`build/asciidoc/html5/index.html`.
## Prepare Your Commit
Asciidoctor also supports live editing. For more details read
[Editing AsciiDoc with Live Preview](https://asciidoctor.org/docs/editing-asciidoc-with-live-preview/).
Note that if you choose the
[System Monitor](https://asciidoctor.org/docs/editing-asciidoc-with-live-preview/#using-a-system-monitor)
option, you can find a Guardfile under `src/docs/asciidoc`.
### 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:
```java
package org.springframework.beans.factory.support;
/**
* Unit tests for SPR-8954, in which a custom {@link InstantiationAwareBeanPostProcessor}
* forces the predicted type of a FactoryBean, effectively preventing retrieval of the
* bean from calls to #getBeansOfType(FactoryBean.class). The implementation of
* {@link AbstractBeanFactory#isFactoryBean(String, RootBeanDefinition)} now ensures
* that not only the predicted bean type is considered, but also the original bean
* definition's beanClass.
*
* @author Chris Beams
*/
public class Spr8954Tests {
@Test
public void cornerSpr8954() {
// ...
}
}
```
### 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 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:
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):
Author: First Last <user@mail.com>
This helps ensure traceability against the ICLA 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
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:
cd spring-framework
git config user.name "First Last"
git config user.email user@mail.com
### Format commit messages
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):
Short (50 chars or less) summary of changes
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded by a
single space, with blank lines in between, but conventions vary here
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. In the body of the commit message, explain how things worked before this
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:
- 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
## Run the Final Checklist
### Run all tests prior to submission
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
Subject line:
Follow the same conventions for pull request subject lines as mentioned above
for commit message subject lines.
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.
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
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
Add a comment to the associated JIRA issue(s) linking to your new pull request.
### 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,
and to keep complexity at a minimum. Your changes, if accepted, may be heavily
modified prior to merging. You will retain "Author:" attribution for your Git
commits granted that the bulk of your changes remain intact. You may be asked to
rework the submission for style (as explained above) and/or substance. Again, we
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.
[help documentation]: https://help.github.com/categories/collaborating-on-projects-using-issues-and-pull-requests/
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
[Contributor License Agreement]: https://cla.pivotal.io/sign/spring
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
[Rewriting History section of Pro Git]: http://git-scm.com/book/en/Git-Tools-Rewriting-History
[Commit Guidelines section of Pro Git]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines
[building from source]: https://github.com/spring-projects/spring-framework#building-from-source
+88 -16
View File
@@ -1,30 +1,102 @@
# <img src="src/docs/asciidoc/images/spring-framework.png" width="80" height="80"> Spring Framework
## Spring Framework
The Spring Framework provides a comprehensive programming and configuration
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.
This is the home of the Spring Framework: the foundation for all [Spring projects](https://spring.io/projects). Collectively the Spring Framework and the family of Spring projects is often referred to simply as "Spring".
Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the [Overview](https://docs.spring.io/spring/docs/current/spring-framework-reference/overview.html#spring-introduction) section as reference for a more complete introduction.
The framework also serves as the foundation for [Spring Integration][], [Spring Batch][]
and the rest of the Spring [family of projects][]. Browse the repositories under
the [Spring organization][] on GitHub for a full list.
## Code of Conduct
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
## Access to Binaries
For access to artifacts or a distribution zip, see the [Spring Framework Artifacts](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Artifacts) wiki page.
## 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][].
## Documentation
See the current [Javadoc][] and [reference docs][].
The Spring Framework maintains reference documentation ([published](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/) and [source](src/docs/asciidoc)), Github [wiki pages](https://github.com/spring-projects/spring-framework/wiki), and an
[API reference](https://docs.spring.io/spring-framework/docs/current/javadoc-api/). There are also [guides and tutorials](https://spring.io/guides) across Spring projects.
## Getting Support
Check out the [spring][spring tags] tags on [Stack Overflow][]. [Commercial support][]
is available too.
## Build from Source
## Issue Tracking
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.
See the [Build from Source](https://github.com/spring-projects/spring-framework/wiki/Build-from-Source) Wiki page and the [CONTRIBUTING.md](CONTRIBUTING.md) file.
## 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.
## Stay in Touch
### Prerequisites
Follow [@SpringCentral](https://twitter.com/springcentral), [@SpringFramework](https://twitter.com/springframework), and its [team members](https://twitter.com/springframework/lists/team/members) on Twitter. In-depth articles can be found at [The Spring Blog](https://spring.io/blog/), and releases are announced via our [news feed](https://spring.io/blog/category/news).
[Git][] and [JDK 8 update 20 or later][JDK8 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
`./gradlew install`
### Compile and test; build all jars, distribution zips, and docs
`./gradlew build`
... and discover more commands with `./gradlew tasks`. See also the [Gradle
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][].
## License
The Spring Framework is released under version 2.0 of the [Apache License][].
The Spring Framework is released under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0).
[Spring Integration]: https://github.com/spring-projects/spring-integration
[Spring Batch]: https://github.com/spring-projects/spring-batch
[family of projects]: http://spring.io/projects
[Spring organization]: https://github.com/spring-projects
[downloading Spring artifacts]: https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
[spring tags]: http://spring.io/questions
[Stack Overflow]: http://stackoverflow.com/faq
[Commercial support]: http://spring.io/services
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
[Gradle]: http://gradle.org
[`./gradlew`]: http://vimeo.com/34436402
[Git]: http://help.github.com/set-up-git-redirect
[JDK8 build]: http://www.oracle.com/technetwork/java/javase/downloads
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
[Pull requests]: https://help.github.com/categories/collaborating-on-projects-using-issues-and-pull-requests/
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
[@SpringFramework]: https://twitter.com/springframework
[@SpringCentral]: https://twitter.com/springcentral
[team members]: https://twitter.com/springframework/lists/team/members
[The Spring Blog]: http://spring.io/blog/
[news feed]: http://spring.io/blog/category/news
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
+1124 -143
View File
File diff suppressed because it is too large Load Diff
-10
View File
@@ -1,10 +0,0 @@
description = "Exposes gradle buildSrc for IDE support"
apply plugin: "groovy"
dependencies {
compile gradleApi()
compile localGroovy()
}
configurations.archives.artifacts.clear()
@@ -0,0 +1,158 @@
/*
* 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)
}
}
}
@@ -0,0 +1,177 @@
/*
* 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)
model.project = project
project.configurations.create("merging")
Configuration runtimeMerge = project.configurations.create("runtimeMerge")
// Ensure the IDE can reference merged projects
project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
// Hook to perform the actual merge logic
project.afterEvaluate{
if (it.merge.into != null) {
setup(it)
}
setupIdeDependencies(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 setupIdeDependencies(Project project) {
project.configurations.each { c ->
c.dependencies.findAll( { it instanceof org.gradle.api.artifacts.ProjectDependency } ).each { d ->
d.dependencyProject.merge.from.each { from ->
project.dependencies.add("runtimeMerge", from)
}
}
}
}
private void setupMaven(Project project) {
project.configurations.each { configuration ->
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
if (mapping.scope) {
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 project;
Project into;
List<Project> from = [];
public void setInto(Project into) {
this.into = into;
into.merge.from.add(project);
}
}
@@ -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,
@@ -0,0 +1 @@
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin
@@ -0,0 +1 @@
implementation-class=org.springframework.build.gradle.MergePlugin
+1 -1
View File
@@ -1 +1 @@
version=5.2.0.M2
version=5.0.0.RC2
+30 -104
View File
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -14,6 +14,29 @@
* limitations under the License.
*/
apply plugin: "org.asciidoctor.convert"
asciidoctor {
sources {
include '*.adoc'
}
logDocuments = true
backends = ["html5", "pdf"]
options doctype: 'book', eruby: 'erubis'
attributes 'icons': 'font',
'idprefix': '',
'idseparator': '-',
docinfo: '',
revnumber: project.version,
sectanchors: '',
sectnums: '',
'source-highlighter': 'coderay@', // TODO switch to 'rouge' once supported by the html5 backend
stylesdir: 'stylesheets/',
stylesheet: 'spring.css',
'spring-version': project.version
}
task api(type: Javadoc) {
group = "Documentation"
description = "Generates aggregated Javadoc API documentation."
@@ -27,7 +50,6 @@ task api(type: Javadoc) {
options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
options.author = true
options.header = rootProject.description
options.use = true
options.overview = "src/docs/api/overview.html"
options.stylesheetFile = file("src/docs/api/stylesheet.css")
options.splitIndex = true
@@ -50,97 +72,12 @@ task api(type: Javadoc) {
}
}
dokka {
dependsOn {
tasks.getByName("api")
}
doFirst {
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
}
moduleName = "spring-framework"
outputFormat = "html"
outputDirectory = "$buildDir/docs/kdoc"
sourceDirs = files(subprojects.collect { project ->
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
kotlinDirs -= project.sourceSets.main.java.srcDirs
})
externalDocumentationLink {
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
packageListUrl = new File(buildDir, "api/package-list").toURI().toURL()
}
externalDocumentationLink {
url = new URL("https://projectreactor.io/docs/core/release/api/")
}
externalDocumentationLink {
url = new URL("https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/")
}
externalDocumentationLink {
url = new URL("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
}
}
configurations {
docs
}
dependencies {
// for documentation resources
docs "io.spring.docresources:spring-doc-resources:0.1.0.RELEASE@zip"
}
task extractDocResources(type: Sync) {
dependsOn configurations.docs
from "src/docs/asciidoc/"
from {
configurations.docs.collect { zipTree(it) }
}
into "$buildDir/asciidoc/build"
}
asciidoctor {
sourceDir "$buildDir/asciidoc/build"
sources {
include '*.adoc'
}
resources {
from(sourceDir) {
include 'images/*', 'css/**', 'js/**'
}
}
logDocuments = true
backends = ["html5"]
// only ouput PDF documentation for non-SNAPSHOT builds
if(!project.getVersion().toString().contains("BUILD-SNAPSHOT")) {
backends += "pdf"
}
options doctype: 'book', eruby: 'erubis'
attributes 'icons': 'font',
'idprefix': '',
'idseparator': '-',
docinfo: 'shared',
revnumber: project.version,
sectanchors: '',
sectnums: '',
'source-highlighter=highlight.js',
'highlightjsdir=js/highlight',
'highlightjs-theme=atom-one-dark-reasonable',
stylesdir: "css/",
stylesheet: 'spring.css',
'spring-version': project.version
}
asciidoctor.dependsOn extractDocResources
task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
task docsZip(type: Zip, dependsOn: 'asciidoctor') {
group = "Distribution"
baseName = "spring-framework"
classifier = "docs"
description = "Builds -${classifier} archive containing api and reference " +
"for deployment at https://docs.spring.io/spring-framework/docs."
"for deployment at http://docs.spring.io/spring-framework/docs."
from("src/dist") {
include "changelog.txt"
@@ -150,17 +87,9 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
into "javadoc-api"
}
from ("$asciidoctor.outputDir/html5") {
from (asciidoctor) {
into "spring-framework-reference"
}
from ("$asciidoctor.outputDir/pdf") {
into "spring-framework-reference/pdf"
}
from (dokka) {
into "kdoc-api"
}
}
task schemaZip(type: Zip) {
@@ -168,7 +97,7 @@ task schemaZip(type: Zip) {
baseName = "spring-framework"
classifier = "schema"
description = "Builds -${classifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema."
"XSDs for deployment at http://springframework.org/schema."
duplicatesStrategy 'exclude'
moduleProjects.each { subproject ->
def Properties schemas = new Properties();
@@ -192,7 +121,6 @@ task schemaZip(type: Zip) {
}
task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
group = "Distribution"
baseName = "spring-framework"
classifier = "dist"
@@ -230,8 +158,6 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
}
}
distZip.mustRunAfter subprojects.test
// Create a distribution that contains all dependencies (required and optional).
// Not published by default; only for use when building from source.
task depsZip(type: Zip, dependsOn: distZip) { zipTask ->
@@ -262,4 +188,4 @@ task depsZip(type: Zip, dependsOn: distZip) { zipTask ->
}
}
}
}
}
+3 -11
View File
@@ -11,9 +11,9 @@ eclipse.jdt {
}
// Replace classpath entries with project dependencies (GRADLE-1116)
// https://issues.gradle.org/browse/GRADLE-1116
// http://issues.gradle.org/browse/GRADLE-1116
eclipse.classpath.file.whenMerged { classpath ->
def regexp = /.*?\/([^\/]+)\/build\/([^\/]+\/)+(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
def 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)
@@ -21,7 +21,7 @@ eclipse.classpath.file.whenMerged { classpath ->
def projectName = matcher[0][1]
def path = "/${projectName}"
if(!classpath.entries.find { e -> e instanceof ProjectDependency && e.path == path }) {
def dependency = new ProjectDependency(path)
def dependency = new ProjectDependency(path, project(":${projectName}").path)
dependency.exported = true
classpath.entries.add(dependency)
}
@@ -91,14 +91,6 @@ task cleanEclipseJdtUi(type: Delete) {
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
}
task eclipseBuildship(type: Copy) {
from rootProject.files(
"src/eclipse/org.eclipse.jdt.ui.prefs",
"src/eclipse/org.eclipse.jdt.core.prefs")
into project.file('.settings/')
outputs.upToDateWhen { false }
}
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
+4 -4
View File
@@ -11,11 +11,11 @@ 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
be seen at http://javadiff.sourceforge.net/
be seen at http://www.jdiff.org
For an example with the source distribution, run "ant" and
look at the HTML output in ./build/reports/example/changes.html
@@ -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
View File
@@ -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> &lt;<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> &lt;<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 "&lt;p>Here is some
text.", with no closing tag. XML requires that either a closing tag exists ("&lt;/p>"),
or that the single tag is closed, e.g. "&lt;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>
+4 -9
View File
@@ -18,11 +18,6 @@ def customizePom(pom, gradleProject) {
"$dep.scope:$dep.groupId:$dep.artifactId"
}
def managedVersions = dependencyManagement.managedVersions
generatedPom.dependencies.findAll{dep -> !dep.version }.each { dep ->
dep.version = managedVersions["${dep.groupId}:${dep.artifactId}"]
}
// add all items necessary for maven central publication
generatedPom.project {
name = gradleProject.description
@@ -30,12 +25,12 @@ def customizePom(pom, gradleProject) {
url = "https://github.com/spring-projects/spring-framework"
organization {
name = "Spring IO"
url = "https://projects.spring.io/spring-framework"
url = "http://projects.spring.io/spring-framework"
}
licenses {
license {
name "Apache License, Version 2.0"
url "https://www.apache.org/licenses/LICENSE-2.0"
url "http://www.apache.org/licenses/LICENSE-2.0"
distribution "repo"
}
}
@@ -52,8 +47,8 @@ def customizePom(pom, gradleProject) {
}
}
issueManagement {
system = "GitHub"
url = "https://github.com/spring-projects/spring-framework/issues"
system = "Jira"
url = "https://jira.springsource.org/browse/SPR"
}
}
}
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
configure(allprojects) { project ->
ext.snifferVersion = "1.15"
configurations {
sniffer
javaApiSignature
}
dependencies {
sniffer("org.codehaus.mojo:animal-sniffer-ant-tasks:${snifferVersion}")
javaApiSignature("org.codehaus.mojo.signature:java18:1.0@signature")
}
}
task copyJavaApiSignature(type: Copy) {
ext.to = file("$buildDir/javaApiSignature/")
description "Copy the resolved Animal Sniffer signature dependency artifact to a known location and name"
from configurations.javaApiSignature
into to
rename '.*signature', 'javaApi.signature'
}
task sniff {
group = "Verification"
description = "Checks the Java API signatures"
dependsOn compileJava
dependsOn copyJavaApiSignature
inputs.dir sourceSets.main.output.classesDir
inputs.dir copyJavaApiSignature.to
doLast {
ant.taskdef(
name: 'animalSniffer',
classname: 'org.codehaus.mojo.animal_sniffer.ant.CheckSignatureTask',
classpath: configurations.sniffer.asPath
)
// TODO: Animal Sniffer currently chokes on optional JDK 9 bytecode in AspectJ 1.9 beta 5
// ant.animalSniffer(
// signature: "$buildDir/javaApiSignature/javaApi.signature",
// classpath: sourceSets.main.compileClasspath.asPath) {
// path(path: sourceSets.main.output.classesDir)
// annotation(className: "org.springframework.lang.UsesSunHttpServer")
// }
}
}
Binary file not shown.
+2 -1
View File
@@ -1,5 +1,6 @@
#Mon Apr 10 21:20:52 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
Vendored
+4 -20
View File
@@ -1,21 +1,5 @@
#!/usr/bin/env sh
#
# Copyright 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.
#
##############################################################################
##
## Gradle start up script for UN*X
@@ -45,16 +29,16 @@ 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='"-Xmx64m" "-Xms64m"'
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
warn ( ) {
echo "$*"
}
die () {
die ( ) {
echo
echo "$*"
echo
@@ -172,7 +156,7 @@ if $cygwin ; then
fi
# Escape application args
save () {
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
Vendored
+1 -17
View File
@@ -1,19 +1,3 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -31,7 +15,7 @@ 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="-Xmx64m" "-Xms64m"
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
+117
View File
@@ -0,0 +1,117 @@
@echo off
set STS_TEST_VERSION='2.9.2.RELEASE'
set CURRENT_DIR=%~dp0
cd %CURRENT_DIR%
cls
echo.
echo -----------------------------------------------------------------------
echo Spring Framework Eclipse/STS project import guide
echo.
echo This script will guide you through the process of importing the
echo Spring Framework sources into Eclipse/STS. It is recommended that you
echo have a recent version of the SpringSource Tool Suite (this script has
echo been tested against STS %STS_TEST_VERSION%), but at the minimum you will
echo need Eclipse + AJDT.
echo.
echo If you need to download and install STS, please do that now by
echo visiting http://spring.io/tools/sts/all
echo.
echo Otherwise, press enter and we'll begin.
pause
REM this command:
REM - wipes out any existing Eclipse metadata
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
echo.
echo -----------------------------------------------------------------------
echo STEP 1: Generate subproject Eclipse metadata
echo.
echo The first step will be to generate Eclipse project metadata for each
echo of the spring-* subprojects. This happens via the built-in
echo "Gradle wrapper" script (./gradlew in this directory). If this is your
echo first time using the Gradle wrapper, this step may take a few minutes
echo while a Gradle distribution is downloaded for you.
echo.
echo The command run will be:
echo.
echo %COMMAND%
echo.
echo Press enter when ready.
pause
call %COMMAND%
if not "%ERRORLEVEL%" == "0" exit /B %ERRORLEVEL%
echo.
echo -----------------------------------------------------------------------
echo STEP 2: Import subprojects into Eclipse/STS
echo.
echo Within Eclipse/STS, do the following:
echo.
echo File ^> Import... ^> Existing Projects into Workspace
echo ^> When prompted for the 'root directory', provide %CURRENT_DIR%
echo ^> Press enter. You will see the modules show up under "Projects"
echo ^> All projects should be selected/checked. Click Finish.
echo ^> When the project import is complete, you should have no errors.
echo.
echo When the above is complete, return here and press the enter key.
pause
set COMMAND=gradlew --no-daemon :eclipse
echo.
echo -----------------------------------------------------------------------
echo STEP 3: generate root project Eclipse metadata
echo.
echo Unfortunately, Eclipse does not allow for importing project
echo hierarchies, so we had to skip root project metadata generation in the
echo during step 1. In this step we simply generate root project metadata
echo so you can import it in the next step.
echo.
echo The command run will be:
echo.
echo %COMMAND%
echo.
echo Press the enter key when ready.
pause
call %COMMAND%
if not "%ERRORLEVEL%" == "0" exit /B %ERRORLEVEL%
echo.
echo -----------------------------------------------------------------------
echo STEP 4: Import root project into Eclipse/STS
echo.
echo Follow the project import steps listed in step 2 above to import the
echo root project.
echo.
echo Press enter when complete, and move on to the final step.
pause
echo.
echo -----------------------------------------------------------------------
echo STEP 5: Enable Git support for all projects
echo.
echo - In the Eclipse/STS Package Explorer, select all spring* projects.
echo - Right-click to open the context menu and select Team ^> Share Project...
echo - In the Share Project dialog that appears, select Git and press Next
echo - Check "Use or create repository in parent folder of project"
echo - Click Finish
echo.
echo When complete, you'll have Git support enabled for all projects.
echo.
echo You're ready to code! Goodbye!
-49
View File
@@ -1,49 +0,0 @@
# Spring Framework - Eclipse/STS Project Import Guide
This document will guide you through the process of importing the Spring Framework
projects into Eclipse or the Spring Tool Suite (STS). It is recommended that you have a
recent version of Eclipse or STS. As a bare minimum you will need Eclipse with full Java
8 support, the AspectJ Development Tools (AJDT), and the Groovy Compiler.
The following instructions have been tested against
[Spring Tool Suite](https://spring.io/tools) (_STS_) 3.9.4 and 4.0.0.M11 with
[Eclipse Buildship](https://projects.eclipse.org/projects/tools.buildship) (Eclipse
Plug-ins for Gradle). The instructions should work with the latest Eclipse distribution
as long as you install
[Buildship](https://marketplace.eclipse.org/content/buildship-gradle-integration). Note
that STS 4 comes with Buildship preinstalled.
## Steps
_Within your locally cloned `spring-framework` working directory:_
1. Precompile `spring-oxm` with `./gradlew :spring-oxm:compileTestJava`
2. Import into Eclipse (File -> Import -> Gradle -> Existing Gradle Project -> Navigate
to directory -> Select Finish)
3. If prompted, exclude the `spring-aspects` module (or after the import by closing or
deleting the project)
4. In the `spring-oxm` project, add the `jaxb` folder in
`build/generated-sources` to the build path (right click on them and select
`Build Path -> Use as Source Folder`)
5. To apply project specific settings run `./gradlew eclipseBuildship`
7. Code away
## Known Issues
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
- See `*RepackJar` tasks in the build.
2. `spring-aspects` does not compile due to references to aspect types unknown to Eclipse.
- If you install [AJDT](https://www.eclipse.org/ajdt/downloads/) into Eclipse it should
work.
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
the IDE.
- Resolving this is a work in progress.
- If attempting to run all JUnit tests from within the IDE, you will likely need to set
the following VM options to avoid out of memory errors:
`-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m`
## Tips
In any case, please do not check in your own generated `.classpath` file, `.project`
file, or `.settings` folder. You'll notice these files are already intentionally in
`.gitignore`. The same policy holds for IDEA metadata.
+135
View File
@@ -0,0 +1,135 @@
cd `dirname $0`
clear
cat <<EOM
------------------------------------------------------------------------
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 has been tested against:
- STS: 3.6.3.RELEASE (Eclipse Luna SR1 4.4.1)
- AJDT: 2.2.4.e44x-20141118-0700 (Luna 4.4)
If you need to download and install Eclipse or STS, please do that now
by visiting one of the following sites:
- Eclipse downloads: http://download.eclipse.org/eclipse/downloads
- STS downloads: http://spring.io/tools/sts/all
- STS nightly builds: http://dist.springsource.com/snapshot/STS/nightly-distributions.html
If you need to install a recent CI build for AJDT (i.e., so that the
spring-aspects module properly compiles in Eclipse/STS), click on the
"Artifacts" tab of a successful CI build and copy the link to the
"update site" which you can then use to install or update AJDT within
Eclipse/STS.
- AJDT CI builds: https://build.spring.io/browse/AJDT-AE44
Once Eclipse/STS is installed, press enter, and we'll begin.
EOM
read
# this command:
# - wipes out any existing Eclipse metadata
# - generates OXM test classes to avoid errors on import into Eclipse
# - 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"
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 command run will be:
$COMMAND
Press enter when ready.
EOM
read
$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.
When the above is complete, return here and press the enter key.
EOM
read
COMMAND="./gradlew --no-daemon :eclipse"
cat <<EOM
------------------------------------------------------------------------
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.
The command run will be:
$COMMAND
Press the enter key when ready.
EOM
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.
Press enter when complete, and move on to the final step.
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.
When complete, you'll have Git support enabled for all projects.
You're ready to code! Goodbye!
EOM
+3 -3
View File
@@ -14,7 +14,7 @@ _Within your locally cloned spring-framework working directory:_
1. `spring-core` and `spring-oxm` should be pre-compiled due to repackaged dependencies.
See `*RepackJar` tasks in the build and https://youtrack.jetbrains.com/issue/IDEA-160605).
2. `spring-aspects` does not compile due to references to aspect types unknown to
IntelliJ IDEA. See https://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the
IntelliJ IDEA. See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the
'spring-aspects' can be excluded from the project to avoid compilation errors.
3. While JUnit tests pass from the command line with Gradle, some may fail when run from
IntelliJ IDEA. Resolving this is a work in progress. If attempting to run all JUnit tests from within
@@ -31,6 +31,6 @@ You'll notice these files are already intentionally in .gitignore. The same poli
## FAQ
Q. What about IntelliJ IDEA's own [Gradle support](https://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?
Q. What about IntelliJ 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. Keep an eye on http://youtrack.jetbrains.com/issue/IDEA-53476
+3 -6
View File
@@ -1,11 +1,13 @@
rootProject.name = "spring"
include "spring-aop"
include "spring-aspects"
include "spring-beans"
include "spring-beans-groovy"
include "spring-context"
include "spring-context-support"
include "spring-context-indexer"
include "spring-core"
include "spring-core-coroutines"
include "spring-expression"
include "spring-instrument"
include "spring-jcl"
@@ -25,8 +27,3 @@ include "spring-framework-bom"
// Exposes gradle buildSrc for IDE support
include "buildSrc"
rootProject.children.find{ it.name == "buildSrc" }.name = "spring-build-src"
rootProject.name = "spring"
rootProject.children.each {project ->
project.buildFileName = "${project.name}.gradle"
}
-9
View File
@@ -1,9 +0,0 @@
description = "Spring AOP"
dependencies {
compile(project(":spring-beans"))
compile(project(":spring-core"))
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
optional("org.apache.commons:commons-pool2:2.6.0")
optional("com.jamonapi:jamon:2.81")
}
@@ -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-2018 the original author or authors.
* 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
* 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,13 @@
package org.aopalliance.aop;
import org.springframework.lang.Nullable;
/**
* 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
@@ -41,7 +43,7 @@ public class AspectException extends RuntimeException {
* @param message the exception message
* @param cause the root cause, if any
*/
public AspectException(String message, Throwable cause) {
public AspectException(String message, @Nullable Throwable cause) {
super(message, cause);
}
@@ -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-2018 the original author or authors.
* 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
* 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,7 @@ package org.aopalliance.intercept;
import java.lang.reflect.Constructor;
/**
* Description of an invocation to a constructor, given to an
* 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
@@ -30,12 +30,12 @@ import java.lang.reflect.Constructor;
*/
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();
/**
* 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,11 +1,11 @@
/*
* Copyright 2002-2019 the original author or authors.
* 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
* 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,7 +24,7 @@ import org.aopalliance.aop.Advice;
* <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...
* access, exceptions...
*
* <p>This interface is not used directly. Use the sub-interfaces
* to intercept specific events. For instance, the following class
@@ -32,8 +32,8 @@ import org.aopalliance.aop.Advice;
* debugger:
*
* <pre class=code>
* class DebuggingInterceptor implements MethodInterceptor,
* ConstructorInterceptor {
* class DebuggingInterceptor implements MethodInterceptor,
* ConstructorInterceptor, FieldInterceptor {
*
* Object invoke(MethodInvocation i) throws Throwable {
* debug(i.getMethod(), i.getThis(), i.getArgs());
@@ -44,6 +44,16 @@ import org.aopalliance.aop.Advice;
* 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) {
* ...
@@ -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-2018 the original author or authors.
* 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
* 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,6 +16,8 @@
package org.aopalliance.intercept;
import org.springframework.lang.Nullable;
/**
* Intercepts calls on an interface on its way to the target. These
* are nested "on top" of the target.
@@ -41,7 +43,7 @@ package org.aopalliance.intercept;
*/
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {
/**
* Implement this method to perform extra treatments before and
* after the invocation. Polite implementations would certainly
@@ -52,6 +54,7 @@ public interface MethodInterceptor extends Interceptor {
* @throws Throwable if the interceptors or the target object
* throws an exception
*/
@Nullable
Object invoke(MethodInvocation invocation) throws Throwable;
}
@@ -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,
@@ -32,7 +32,7 @@ public interface MethodInvocation extends Invocation {
/**
* Get the method being called.
* <p>This method is a friendly implementation of the
* <p>This method is a frienly implementation of the
* {@link Joinpoint#getStaticPart()} method (same result).
* @return the method being called
*/
@@ -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,
@@ -31,18 +31,9 @@ import org.aopalliance.aop.Advice;
* implemented using interception.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public interface Advisor {
/**
* Common placeholder for an empty {@code Advice} to be returned from
* {@link #getAdvice()} if no proper advice has been configured (yet).
* @since 5.0
*/
Advice EMPTY_ADVICE = new Advice() {};
/**
* Return the advice part of this aspect. An advice may be an
* interceptor, a before advice, a throws advice, etc.
@@ -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,
@@ -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,
@@ -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,
@@ -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-2018 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,6 +18,8 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* A specialized type of {@link MethodMatcher} that takes into account introductions
* when matching methods. If there are no introductions on the target class,
@@ -33,11 +35,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
* @param targetClass the target class (may be {@code null}, 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
* @return whether or not this method matches statically
*/
boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);
boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions);
}
@@ -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-2018 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,
@@ -24,9 +24,10 @@ import org.springframework.lang.Nullable;
* Advice invoked before a method is invoked. Such advices cannot
* prevent the method call proceeding, unless they throw a Throwable.
*
* @author Rod Johnson
* @see AfterReturningAdvice
* @see ThrowsAdvice
*
* @author Rod Johnson
*/
public interface MethodBeforeAdvice extends BeforeAdvice {
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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
*
* 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,6 +18,8 @@ package org.springframework.aop;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Part of a {@link Pointcut}: Checks whether the target method is eligible for advice.
*
@@ -48,16 +50,16 @@ 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} 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.
* @param method the candidate method
* @param targetClass the target class
* @param targetClass the target class (may be {@code null}, in which case
* the candidate class must be taken to be the method's declaring class)
* @return whether or not this method matches statically
*/
boolean matches(Method method, Class<?> targetClass);
boolean matches(Method method, @Nullable Class<?> targetClass);
/**
* Is this MethodMatcher dynamic, that is, must a final call be made on the
@@ -80,12 +82,13 @@ public interface MethodMatcher {
* 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
* @param targetClass the target class (may be {@code null}, 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, @Nullable Class<?> targetClass, Object... args);
/**
@@ -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,
@@ -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,
@@ -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-2018 the original author or authors.
/*<
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -42,7 +42,6 @@ public interface TargetSource extends TargetClassAware {
* @return the type of targets returned by this {@link TargetSource}
*/
@Override
@Nullable
Class<?> getTargetClass();
/**
@@ -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-2018 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,
@@ -24,7 +24,7 @@ import java.io.Serializable;
* @author Rod Johnson
*/
@SuppressWarnings("serial")
final class TrueClassFilter implements ClassFilter, Serializable {
class TrueClassFilter implements ClassFilter, Serializable {
public static final TrueClassFilter INSTANCE = new TrueClassFilter();
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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
*
* 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,13 +19,15 @@ package org.springframework.aop;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Canonical MethodMatcher instance that matches all methods.
*
* @author Rod Johnson
*/
@SuppressWarnings("serial")
final class TrueMethodMatcher implements MethodMatcher, Serializable {
class TrueMethodMatcher implements MethodMatcher, Serializable {
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
@@ -43,12 +45,12 @@ final class TrueMethodMatcher implements MethodMatcher, Serializable {
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
// Should never be invoked as isRuntime returns false.
throw new UnsupportedOperationException();
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 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,
@@ -24,7 +24,7 @@ import java.io.Serializable;
* @author Rod Johnson
*/
@SuppressWarnings("serial")
final class TruePointcut implements Pointcut, Serializable {
class TruePointcut implements Pointcut, Serializable {
public static final TruePointcut INSTANCE = new TruePointcut();
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -63,7 +63,7 @@ import org.springframework.util.StringUtils;
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
/**
* Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
*/
protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();
@@ -104,11 +104,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
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 = "";
private String aspectName;
/**
* The order of declaration of this advice within the aspect.
@@ -117,18 +117,15 @@ 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.
* and sets them explicitly
*/
@Nullable
private String[] argumentNames;
private String[] argumentNames = null;
/** Non-null if after throwing advice binds the thrown value. */
@Nullable
private String throwingName;
/** Non-null if after throwing advice binds the thrown value */
private String throwingName = null;
/** Non-null if after returning advice binds the return value. */
@Nullable
private String returningName;
/** Non-null if after returning advice binds the return value */
private String returningName = null;
private Class<?> discoveredReturningType = Object.class;
@@ -136,22 +133,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
/**
* Index for thisJoinPoint argument (currently only
* supported at index 0 if present at all).
* supported at index 0 if present at all)
*/
private int joinPointArgumentIndex = -1;
/**
* Index for thisJoinPointStaticPart argument (currently only
* supported at index 0 if present at all).
* supported at index 0 if present at all)
*/
private int joinPointStaticPartArgumentIndex = -1;
@Nullable
private Map<String, Integer> argumentBindings;
private boolean argumentsIntrospected = false;
@Nullable
private Type discoveredReturningGenericType;
// Note: Unlike return type, no such generic information is needed for the throwing type,
// since Java doesn't allow exception types to be parameterized.
@@ -224,9 +219,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* Set the name of the aspect (bean) in which the advice was declared.
*/
public void setAspectName(String name) {
this.aspectName = name;
}
@@ -237,7 +229,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
/**
* 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;
@@ -377,7 +369,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* 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) {
return;
@@ -385,8 +377,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
int numUnboundArgs = this.parameterTypes.length;
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
maybeBindJoinPointStaticPart(parameterTypes[0])) {
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
numUnboundArgs--;
}
else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
numUnboundArgs--;
}
@@ -470,7 +464,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
private void bindExplicitArguments(int numArgumentsLeftToBind) {
Assert.state(this.argumentNames != null, "No argument names available");
this.argumentBindings = new HashMap<>();
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterCount();
@@ -511,7 +504,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
// configure the pointcut expression accordingly.
configurePointcutParameters(this.argumentNames, argumentIndexOffset);
configurePointcutParameters(argumentIndexOffset);
}
/**
@@ -519,7 +512,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
* pointcut parameters - but returning and throwing vars are handled differently
* and must be removed from the list if present.
*/
private void configurePointcutParameters(String[] argumentNames, int argumentIndexOffset) {
private void configurePointcutParameters(int argumentIndexOffset) {
int numParametersToRemove = argumentIndexOffset;
if (this.returningName != null) {
numParametersToRemove++;
@@ -527,20 +520,20 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
if (this.throwingName != null) {
numParametersToRemove++;
}
String[] pointcutParameterNames = new String[argumentNames.length - numParametersToRemove];
String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
int index = 0;
for (int i = 0; i < argumentNames.length; i++) {
for (int i = 0; i < this.argumentNames.length; i++) {
if (i < argumentIndexOffset) {
continue;
}
if (argumentNames[i].equals(this.returningName) ||
argumentNames[i].equals(this.throwingName)) {
if (this.argumentNames[i].equals(this.returningName) ||
this.argumentNames[i].equals(this.throwingName)) {
continue;
}
pointcutParameterNames[index] = argumentNames[i];
pointcutParameterNames[index] = this.argumentNames[i];
pointcutParameterTypes[index] = methodParameterTypes[i];
index++;
}
@@ -551,7 +544,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
/**
* Take the arguments at the method execution join point and output a set of arguments
* to the advice method.
* to the advice method
* @param jp the current JoinPoint
* @param jpMatch the join point match that matched this execution join point
* @param returnValue the return value from the method execution (may be null)
@@ -715,7 +708,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return !this.adviceMethod.equals(method);
}
@@ -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-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -114,7 +114,6 @@ import org.springframework.util.StringUtils;
* returning {@code null} in the case that the parameter names cannot be discovered.
*
* @author Adrian Colyer
* @author Juergen Hoeller
* @since 2.0
*/
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
@@ -156,29 +155,32 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
/** The pointcut expression associated with the advice, as a simple String. */
@Nullable
private String pointcutExpression;
private boolean raiseExceptions;
/** If the advice is afterReturning, and binds the return value, this is the parameter name used. */
@Nullable
/**
* 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. */
@Nullable
/**
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
*/
private String throwingName;
private Class<?>[] argumentTypes = new Class<?>[0];
/**
* The pointcut expression associated with the advice, as a simple String.
*/
private String pointcutExpression;
private String[] parameterNameBindings = new String[0];
private Class<?>[] argumentTypes;
private String[] parameterNameBindings;
private int numberOfRemainingUnboundArguments;
/**
* Create a new discoverer that attempts to discover parameter names.
* Create a new discoverer that attempts to discover parameter names
* from the given pointcut expression.
*/
public AspectJAdviceParameterNameDiscoverer(@Nullable String pointcutExpression) {
@@ -200,7 +202,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* returning variable name must be specified.
* @param returningName the name of the returning variable
*/
public void setReturningName(@Nullable String returningName) {
public void setReturningName(String returningName) {
this.returningName = returningName;
}
@@ -209,7 +211,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* throwing variable name must be specified.
* @param throwingName the name of the throwing variable
*/
public void setThrowingName(@Nullable String throwingName) {
public void setThrowingName(String throwingName) {
this.throwingName = throwingName;
}
@@ -222,7 +224,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* @return the parameter names
*/
@Override
@Nullable
public String[] getParameterNames(Method method) {
this.argumentTypes = method.getParameterTypes();
this.numberOfRemainingUnboundArguments = this.argumentTypes.length;
@@ -272,7 +273,15 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
}
}
catch (AmbiguousBindingException | IllegalArgumentException ex) {
catch (AmbiguousBindingException ambigEx) {
if (this.raiseExceptions) {
throw ambigEx;
}
else {
return null;
}
}
catch (IllegalArgumentException ex) {
if (this.raiseExceptions) {
throw ex;
}
@@ -303,7 +312,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
* {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
*/
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
if (this.raiseExceptions) {
throw new UnsupportedOperationException("An advice method can never be a constructor");
@@ -413,7 +421,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);
}
@@ -574,7 +582,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);
}
@@ -669,7 +677,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
}
/**
* Match up args against unbound arguments of primitive types.
* Match up args against unbound arguments of primitive types
*/
private void maybeBindPrimitiveArgsFromPointcutExpression() {
int numUnboundPrimitives = countNumberOfUnboundPrimitiveArguments();
@@ -773,7 +781,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
private int numTokensConsumed;
@Nullable
private String text;
public PointcutBody(int tokens, @Nullable String text) {
@@ -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,
@@ -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,
@@ -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-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
@@ -103,20 +102,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class);
@Nullable
private Class<?> pointcutDeclarationScope;
private String[] pointcutParameterNames = new String[0];
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
@Nullable
private BeanFactory beanFactory;
@Nullable
private transient ClassLoader pointcutClassLoader;
@Nullable
private transient PointcutExpression pointcutExpression;
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
@@ -174,13 +169,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
@Override
public ClassFilter getClassFilter() {
obtainPointcutExpression();
checkReadyToMatch();
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
obtainPointcutExpression();
checkReadyToMatch();
return this;
}
@@ -189,7 +184,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Check whether this pointcut is ready to match,
* lazily building the underlying AspectJ pointcut expression.
*/
private PointcutExpression obtainPointcutExpression() {
private void checkReadyToMatch() {
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
@@ -197,7 +192,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
this.pointcutClassLoader = determinePointcutClassLoader();
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}
/**
@@ -264,15 +258,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* Return the underlying AspectJ pointcut expression.
*/
public PointcutExpression getPointcutExpression() {
return obtainPointcutExpression();
checkReadyToMatch();
return this.pointcutExpression;
}
@Override
public boolean matches(Class<?> targetClass) {
PointcutExpression pointcutExpression = obtainPointcutExpression();
checkReadyToMatch();
try {
try {
return pointcutExpression.couldMatchJoinPointsInType(targetClass);
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
}
catch (ReflectionWorldException ex) {
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
@@ -290,9 +285,10 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
@Override
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean beanHasIntroductions) {
checkReadyToMatch();
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
// Special handling for this, target, @this, @target, @annotation
// in Spring - we can optimize since we know we have exactly this class,
@@ -305,7 +301,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
else {
// the maybe case
if (hasIntroductions) {
if (beanHasIntroductions) {
return true;
}
// A match test returned maybe - if there are any subtype sensitive variables
@@ -313,24 +309,27 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
// we say this is not a match as in Spring there will never be a different
// runtime subtype.
RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
return (!walker.testsSubtypeSensitiveVars() ||
(targetClass != null && walker.testTargetInstanceOfResidue(targetClass)));
}
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
public boolean matches(Method method, @Nullable Class<?> targetClass) {
return matches(method, targetClass, false);
}
@Override
public boolean isRuntime() {
return obtainPointcutExpression().mayNeedDynamicTest();
checkReadyToMatch();
return this.pointcutExpression.mayNeedDynamicTest();
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
checkReadyToMatch();
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
// consistent with return of MethodInvocationProceedingJoinPoint
@@ -365,7 +364,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
* <p>See SPR-2979 for the original bug.
*/
if (pmi != null && thisObject != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
@@ -425,28 +424,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
invocation.setUserAttribute(resolveExpression(), jpm);
}
private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetMethod.getDeclaringClass().isInterface()) {
// Try to build the most specific interface possible for inherited methods to be
// considered for sub-interface matches as well, in particular for proxy classes.
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
if (ifcs.size() > 1) {
try {
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
}
catch (IllegalArgumentException ex) {
// Implemented interfaces probably expose conflicting method signatures...
// Proceed with original target method.
}
}
}
return getShadowMatch(targetMethod, method);
}
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
// Avoid lock contention for known Methods through concurrent access...
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
@@ -454,12 +431,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
synchronized (this.shadowMatchCache) {
// Not found - now check again with full lock...
PointcutExpression fallbackExpression = null;
Method methodToMatch = targetMethod;
shadowMatch = this.shadowMatchCache.get(targetMethod);
if (shadowMatch == null) {
Method methodToMatch = targetMethod;
try {
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex) {
// Failed to introspect target method, probably because it has been loaded
@@ -474,16 +451,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
fallbackExpression = null;
}
}
if (targetMethod != originalMethod && (shadowMatch == null ||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
// Fall back to the plain original method in case of no resolvable match or a
// negative match on a proxy class (which doesn't carry any annotations on its
// redeclared methods).
if (shadowMatch == null && targetMethod != originalMethod) {
methodToMatch = originalMethod;
try {
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
}
catch (ReflectionWorldException ex) {
catch (ReflectionWorldException ex3) {
// Could neither introspect the target class nor the proxy class ->
// let's try the original method's declaring class before we give up...
try {
@@ -492,7 +465,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
}
}
catch (ReflectionWorldException ex2) {
catch (ReflectionWorldException ex4) {
fallbackExpression = null;
}
}
@@ -546,16 +519,18 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("AspectJExpressionPointcut: ");
sb.append("(");
for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
sb.append(this.pointcutParameterTypes[i].getName());
sb.append(" ");
sb.append(this.pointcutParameterNames[i]);
if ((i+1) < this.pointcutParameterTypes.length) {
sb.append(", ");
if (this.pointcutParameterNames != null && this.pointcutParameterTypes != null) {
sb.append("(");
for (int i = 0; i < this.pointcutParameterTypes.length; i++) {
sb.append(this.pointcutParameterTypes[i].getName());
sb.append(" ");
sb.append(this.pointcutParameterNames[i]);
if ((i+1) < this.pointcutParameterTypes.length) {
sb.append(", ");
}
}
sb.append(")");
}
sb.append(")");
sb.append(" ");
if (getExpression() != null) {
sb.append(getExpression());
@@ -566,19 +541,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
return sb.toString();
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<>(32);
}
/**
* Handler for the Spring-specific {@code bean()} pointcut designator
@@ -675,6 +637,20 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
}
//---------------------------------------------------------------------
// Serialization support
//---------------------------------------------------------------------
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
// Rely on default serialization, just initialize state after deserialization.
ois.defaultReadObject();
// Initialize transient fields.
// pointcutExpression will be initialized lazily by checkReadyToMatch()
this.shadowMatchCache = new ConcurrentHashMap<>(32);
}
private static class DefensiveShadowMatch implements ShadowMatch {
private final ShadowMatch primary;
@@ -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,7 +34,7 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
public void setExpression(@Nullable String expression) {
public void setExpression(String expression) {
this.pointcut.setExpression(expression);
}
@@ -43,7 +43,7 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
return this.pointcut.getExpression();
}
public void setLocation(@Nullable String location) {
public void setLocation(String location) {
this.pointcut.setLocation(location);
}
@@ -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-2018 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,
@@ -21,8 +21,8 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice}
@@ -38,12 +38,11 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
private final Pointcut pointcut;
@Nullable
private Integer order;
/**
* Create a new AspectJPointcutAdvisor for the given advice.
* Create a new AspectJPointcutAdvisor for the given advice
* @param advice the AbstractAspectJAdvice to wrap
*/
public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) {
@@ -52,20 +51,10 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
this.pointcut = advice.buildSafePointcut();
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
}
@Override
public boolean isPerInstance() {
@@ -82,13 +71,14 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
return this.pointcut;
}
/**
* Return the name of the aspect (bean) in which the advice was declared.
* @since 4.3.15
* @see AbstractAspectJAdvice#getAspectName()
*/
public String getAspectName() {
return this.advice.getAspectName();
@Override
public int getOrder() {
if (this.order != null) {
return this.order;
}
else {
return this.advice.getOrder();
}
}
@@ -101,12 +91,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,11 +1,11 @@
/*
* Copyright 2002-2018 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,
@@ -36,12 +36,12 @@ public interface AspectJPrecedenceInformation extends Ordered {
// its advice for aspects with non-singleton instantiation models.
/**
* Return the name of the aspect (bean) in which the advice was declared.
* The name of the aspect (bean) in which the advice was declared.
*/
String getAspectName();
/**
* Return the declaration order of the advice member within the aspect.
* The declaration order of the advice member within the aspect.
*/
int getDeclarationOrder();
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2019 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,
@@ -27,31 +27,27 @@ import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
*
* @author Rod Johnson
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @since 2.0
*/
public abstract class AspectJProxyUtils {
/**
* Add special advisors if necessary to work with a proxy chain that contains AspectJ advisors:
* concretely, {@link ExposeInvocationInterceptor} at the beginning of the list.
* <p>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 the advisors available
* @return {@code true} if an {@link ExposeInvocationInterceptor} was added to the list,
* otherwise {@code false}
* 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}.
*/
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
// Be careful not to get the Advice without a guard, as
// this might eagerly instantiate a non-singleton AspectJ aspect
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
@@ -70,7 +66,7 @@ public abstract class AspectJProxyUtils {
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
(advisor instanceof PointcutAdvisor &&
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}
}
@@ -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-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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 ClassFilter typePatternClassFilter;
private final Advice advice;
/**
* Create a new advisor for this DeclareParents field.
@@ -49,8 +48,8 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param defaultImpl the default implementation class
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Class<?> defaultImpl) {
this(interfaceType, typePattern,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
this(interfaceType, typePattern, defaultImpl,
new DelegatePerTargetObjectIntroductionInterceptor(defaultImpl, interfaceType));
}
/**
@@ -60,24 +59,27 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
* @param delegateRef the delegate implementation object
*/
public DeclareParentsAdvisor(Class<?> interfaceType, String typePattern, Object delegateRef) {
this(interfaceType, typePattern, new DelegatingIntroductionInterceptor(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 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 = (clazz -> !this.introducedInterface.isAssignableFrom(clazz));
ClassFilter exclusion = clazz -> !(introducedInterface.isAssignableFrom(clazz));
this.typePatternClassFilter = ClassFilters.intersection(typePatternFilter, exclusion);
this.advice = advice;
}
@@ -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-2018 the original author or authors.
* 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
*
* 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,15 +33,17 @@ import org.springframework.lang.Nullable;
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.
* <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.
* {@code null} 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()}.</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
@@ -55,15 +57,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
private final ProxyMethodInvocation methodInvocation;
@Nullable
private Object[] args;
private Object[] defensiveCopyOfArgs;
/** Lazily initialized signature object. */
@Nullable
/** Lazily initialized signature object */
private Signature signature;
/** Lazily initialized source location object. */
@Nullable
/** Lazily initialized source location object */
private SourceLocation sourceLocation;
@@ -77,7 +76,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
this.methodInvocation = methodInvocation;
}
@Override
public void set$AroundClosure(AroundClosure aroundClosure) {
throw new UnsupportedOperationException();
@@ -119,10 +117,12 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
@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
@@ -130,7 +130,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
if (this.signature == null) {
this.signature = new MethodSignatureImpl();
}
return this.signature;
return signature;
}
@Override
@@ -178,7 +178,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
*/
private class MethodSignatureImpl implements MethodSignature {
@Nullable
private volatile String[] parameterNames;
@Override
@@ -217,7 +216,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
}
@Override
@Nullable
public String[] getParameterNames() {
if (this.parameterNames == null) {
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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,
@@ -37,7 +37,6 @@ import org.aspectj.weaver.reflect.ReflectionVar;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ShadowMatch;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -51,7 +50,7 @@ import org.springframework.util.ReflectionUtils;
* migrate to {@code ShadowMatch.getVariablesInvolvedInRuntimeTest()}
* or some similar operation.
*
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593">Bug 151593</a>
* <p>See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=151593"/>Bug 151593</a>
*
* @author Adrian Colyer
* @author Ramnivas Laddad
@@ -79,7 +78,6 @@ class RuntimeTestWalker {
}
@Nullable
private final Test runtimeTest;
@@ -175,7 +173,7 @@ class RuntimeTestWalker {
}
private abstract static class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private static abstract class InstanceOfResidueTestVisitor extends TestVisitorAdapter {
private final Class<?> matchClass;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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
* 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 java.lang.reflect.InvocationTargetException;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -45,7 +44,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
this.aspectClass = aspectClass;
}
/**
* Return the specified aspect class (never {@code null}).
*/
@@ -53,6 +51,7 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
return this.aspectClass;
}
@Override
public final Object getAspectInstance() {
try {
@@ -77,7 +76,6 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.aspectClass.getClassLoader();
}
@@ -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,
@@ -19,7 +19,6 @@ package org.springframework.aop.aspectj;
import java.io.Serializable;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -54,7 +53,6 @@ public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Se
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.aspectInstance.getClass().getClassLoader();
}
@@ -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,
@@ -20,7 +20,6 @@ import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.TypePatternMatcher;
import org.springframework.aop.ClassFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -33,9 +32,8 @@ import org.springframework.util.StringUtils;
*/
public class TypePatternClassFilter implements ClassFilter {
private String typePattern = "";
private String typePattern;
@Nullable
private TypePatternMatcher aspectJTypePatternMatcher;
@@ -53,6 +51,8 @@ public class TypePatternClassFilter implements ClassFilter {
* 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
*/
public TypePatternClassFilter(String typePattern) {
setTypePattern(typePattern);
@@ -73,6 +73,8 @@ public class TypePatternClassFilter implements ClassFilter {
* 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
*/
public void setTypePattern(String typePattern) {
Assert.notNull(typePattern, "Type pattern must not be null");
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -42,6 +42,7 @@ import org.springframework.aop.framework.AopConfigException;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Abstract base class for factories that can create Spring AOP Advisors
@@ -59,11 +60,8 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
/** Logger available to subclasses. */
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();
@@ -125,13 +123,15 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...).
* (there <i>should</i> only be one anyway...)
*/
@SuppressWarnings("unchecked")
@Nullable
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
@@ -151,34 +151,34 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
/**
* Enum for AspectJ annotation types.
* @see AspectJAnnotation#getAnnotationType()
*/
protected enum AspectJAnnotationType {
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
AtPointcut,
AtBefore,
AtAfter,
AtAfterReturning,
AtAfterThrowing,
AtAround
}
/**
* Class modelling an AspectJ annotation, exposing its type enumeration and
* pointcut String.
* @param <A> the annotation type
*/
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<>(8);
private static Map<Class<?>, AspectJAnnotationType> annotationTypes = new HashMap<>();
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;
@@ -192,35 +192,45 @@ 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);
Object argNames = AnnotationUtils.getValue(annotation, "argNames");
this.argumentNames = (argNames instanceof String ? (String) 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;
for (Class<?> type : annotationTypes.keySet()) {
if (type.isInstance(annotation)) {
return annotationTypes.get(type);
}
}
throw new IllegalStateException("Unknown annotation type: " + annotation);
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
}
private String resolveExpression(A annotation) {
for (String attributeName : EXPRESSION_ATTRIBUTES) {
Object val = AnnotationUtils.getValue(annotation, attributeName);
if (val instanceof String) {
String str = (String) val;
if (!str.isEmpty()) {
return str;
@Nullable
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;
}
}
}
throw new IllegalStateException("Failed to resolve expression: " + annotation);
return expression;
}
public AspectJAnnotationType getAnnotationType() {
@@ -253,7 +263,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
@Override
@Nullable
public String[] getParameterNames(Method method) {
if (method.getParameterCount() == 0) {
return new String[0];
@@ -262,11 +271,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
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;
}
@@ -276,7 +285,6 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
@Override
@Nullable
public String[] getParameterNames(Constructor<?> ctor) {
throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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
* 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,7 +24,6 @@ import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -49,13 +48,10 @@ import org.springframework.util.Assert;
@SuppressWarnings("serial")
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
@Nullable
private List<Pattern> includePatterns;
@Nullable
private AspectJAdvisorFactory aspectJAdvisorFactory;
@Nullable
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
@@ -91,9 +87,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
@@ -107,8 +101,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
// proxied by that interface and fail at runtime as the advice method is not
// defined on the interface. We could potentially relax the restriction about
// not advising aspects in the future.
return (super.isInfrastructureClass(beanClass) ||
(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
}
/**
@@ -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-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -49,7 +49,7 @@ import org.springframework.util.ClassUtils;
@SuppressWarnings("serial")
public class AspectJProxyFactory extends ProxyCreatorSupport {
/** Cache for singleton aspect instances. */
/** Cache for singleton aspect instances */
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<>();
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
@@ -170,10 +170,11 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
synchronized (aspectCache) {
// To be safe, check within full lock now...
instance = aspectCache.get(aspectClass);
if (instance == null) {
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
aspectCache.put(aspectClass, instance);
if (instance != null) {
return instance;
}
instance = new SimpleAspectInstanceFactory(aspectClass).getAspectInstance();
aspectCache.put(aspectClass, instance);
}
}
return 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,
@@ -127,7 +127,7 @@ public class AspectMetadata implements Serializable {
*/
private String findPerClause(Class<?> aspectClass) {
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;
}
@@ -148,7 +148,7 @@ public class AspectMetadata implements Serializable {
}
/**
* Return the aspect name.
* Return the aspect class.
*/
public String getAspectName() {
return this.aspectName;
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -55,7 +55,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* Create a BeanFactoryAspectInstanceFactory. AspectJ will be called to
* introspect to create AJType metadata using the type returned for the
* given bean name from the BeanFactory.
* @param beanFactory the BeanFactory to obtain instance(s) from
* @param beanFactory BeanFactory to obtain instance(s) from
* @param name name of the bean
*/
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name) {
@@ -66,7 +66,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
* Create a BeanFactoryAspectInstanceFactory, providing a type that AspectJ should
* introspect to create AJType metadata. Use if the BeanFactory may consider the type
* to be a subclass (as when using CGLIB), and the information should relate to a superclass.
* @param beanFactory the BeanFactory to obtain instance(s) from
* @param beanFactory BeanFactory to obtain instance(s) from
* @param name the name of the bean
* @param type the type that should be introspected by AspectJ
* ({@code null} indicates resolution through {@link BeanFactory#getType} via the bean name)
@@ -91,7 +91,6 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
@@ -104,21 +103,20 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
}
@Override
@Nullable
public Object getAspectCreationMutex() {
if (this.beanFactory.isSingleton(this.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();
}
else {
return this;
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;
}
/**
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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
* 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,8 @@
package org.springframework.aop.aspectj.annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -27,7 +27,6 @@ import org.aspectj.lang.reflect.PerClauseKind;
import org.springframework.aop.Advisor;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -44,7 +43,6 @@ public class BeanFactoryAspectJAdvisorsBuilder {
private final AspectJAdvisorFactory advisorFactory;
@Nullable
private volatile List<String> aspectBeanNames;
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
@@ -87,8 +85,8 @@ public class BeanFactoryAspectJAdvisorsBuilder {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
List<Advisor> advisors = new LinkedList<>();
aspectNames = new LinkedList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
@@ -138,7 +136,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
List<Advisor> advisors = new LinkedList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -42,10 +42,10 @@ import org.springframework.lang.Nullable;
* @since 2.0
*/
@SuppressWarnings("serial")
final class InstantiationModelAwarePointcutAdvisorImpl
class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
private static final Advice EMPTY_ADVICE = new Advice() {};
private static Advice EMPTY_ADVICE = new Advice() {};
private final AspectJExpressionPointcut declaredPointcut;
@@ -70,13 +70,10 @@ final class InstantiationModelAwarePointcutAdvisorImpl
private final boolean lazy;
@Nullable
private Advice instantiatedAdvice;
@Nullable
private Boolean isBeforeAdvice;
@Nullable
private Boolean isAfterAdvice;
@@ -116,41 +113,14 @@ final class InstantiationModelAwarePointcutAdvisorImpl
/**
* The pointcut for Spring AOP to use.
* Actual behaviour of the pointcut will change depending on the state of the advice.
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
* depending on the state of the advice.
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
/**
* This is only of interest for Spring AOP: AspectJ instantiation semantics
* are much richer. In AspectJ terminology, all a return of {@code true}
@@ -168,6 +138,34 @@ final class InstantiationModelAwarePointcutAdvisorImpl
return this.aspectInstanceFactory.getAspectMetadata();
}
/**
* Lazily instantiate advice if necessary.
*/
@Override
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
@Override
public boolean isLazy() {
return this.lazy;
}
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
return this.aspectInstanceFactory;
}
@@ -220,26 +218,33 @@ final class InstantiationModelAwarePointcutAdvisorImpl
}
else {
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
case AtAround:
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
break;
case AtBefore:
this.isBeforeAdvice = true;
this.isAfterAdvice = false;
break;
case AtAfter:
case AtAfterReturning:
case AtAfterThrowing:
this.isBeforeAdvice = false;
this.isAfterAdvice = true;
this.isBeforeAdvice = false;
break;
case AtAround:
case AtPointcut:
this.isAfterAdvice = false;
this.isBeforeAdvice = false;
break;
case AtBefore:
this.isAfterAdvice = false;
this.isBeforeAdvice = true;
}
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
@@ -250,31 +255,22 @@ final class InstantiationModelAwarePointcutAdvisorImpl
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
/**
* Pointcut implementation that changes its behaviour when the advice is instantiated.
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
* if it does not at first match statically.
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
* be optimized out if it does not at first match statically.
*/
private static final class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
private final AspectJExpressionPointcut declaredPointcut;
private final Pointcut preInstantiationPointcut;
@Nullable
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) {
@@ -283,15 +279,14 @@ final class InstantiationModelAwarePointcutAdvisorImpl
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// We're either instantiated and matching on declared pointcut,
// or uninstantiated matching on either pointcut...
public boolean matches(Method method, @Nullable 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, @Nullable Class<?> targetClass, Object... args) {
// This can match only on declared pointcut.
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
}
@@ -1,11 +1,11 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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
* 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,6 @@ package org.springframework.aop.aspectj.annotation;
import java.io.Serializable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -33,7 +32,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
private final MetadataAwareAspectInstanceFactory maaif;
@Nullable
private volatile Object materialized;
@@ -49,24 +47,20 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
@Override
public Object getAspectInstance() {
Object aspectInstance = this.materialized;
if (aspectInstance == null) {
if (this.materialized == null) {
Object mutex = this.maaif.getAspectCreationMutex();
if (mutex == null) {
aspectInstance = this.maaif.getAspectInstance();
this.materialized = aspectInstance;
this.materialized = this.maaif.getAspectInstance();
}
else {
synchronized (mutex) {
aspectInstance = this.materialized;
if (aspectInstance == null) {
aspectInstance = this.maaif.getAspectInstance();
this.materialized = aspectInstance;
if (this.materialized == null) {
this.materialized = this.maaif.getAspectInstance();
}
}
}
}
return aspectInstance;
return this.materialized;
}
public boolean isMaterialized() {
@@ -74,7 +68,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
}
@Override
@Nullable
public ClassLoader getAspectClassLoader() {
return this.maaif.getAspectClassLoader();
}
@@ -85,7 +78,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
}
@Override
@Nullable
public Object getAspectCreationMutex() {
return this.maaif.getAspectCreationMutex();
}
@@ -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-2018 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,
@@ -29,7 +29,7 @@ import org.springframework.aop.framework.AopConfigException;
@SuppressWarnings("serial")
public class NotAnAtAspectException extends AopConfigException {
private final Class<?> nonAspectClass;
private Class<?> nonAspectClass;
/**
@@ -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-2019 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,8 +20,9 @@ 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;
@@ -85,7 +86,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
}
@Nullable
private final BeanFactory beanFactory;
@@ -121,7 +121,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
List<Advisor> advisors = new LinkedList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
@@ -147,14 +147,14 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
final List<Method> methods = new LinkedList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
methods.sort(METHOD_COMPARATOR);
});
Collections.sort(methods, METHOD_COMPARATOR);
return methods;
}
@@ -163,7 +163,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} if not an Advisor
*/
@Nullable
private Advisor getDeclareParentsAdvisor(Field introductionField) {
@@ -183,7 +183,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
@Override
@Nullable
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
@@ -210,15 +209,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
ajexp.setBeanFactory(this.beanFactory);
return ajexp;
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
@@ -246,15 +242,6 @@ 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);
@@ -279,6 +266,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
@@ -292,7 +288,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
@@ -306,8 +301,13 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
(method, args, target) -> aif.getAspectInstance());
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, @Nullable Object target) {
// Simply instantiate the aspect
aif.getAspectInstance();
}
});
}
}

Some files were not shown because too many files have changed in this diff Show More