mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88d3ce96c1 |
+64
-78
@@ -1,36 +1,33 @@
|
||||
_Have something you'd like to contribute to the framework? We welcome pull
|
||||
requests but ask that you carefully read this document first to understand how
|
||||
requests, but ask that you carefully read this document first to understand how
|
||||
best to submit them; what kind of changes are likely to be accepted; and what
|
||||
to expect from the Spring team when evaluating your submission._
|
||||
|
||||
_Please refer back to this document as a checklist before issuing any pull
|
||||
request; this will save time for everyone!_
|
||||
|
||||
## Take Your First Steps
|
||||
## Understand the basics
|
||||
|
||||
### Understand the basics
|
||||
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
excellent [help documentation][] first.
|
||||
|
||||
|
||||
### Search JIRA first; create an issue if necessary
|
||||
## Search JIRA first; create an issue if necessary
|
||||
|
||||
Is there already an issue that addresses your concern? Do a bit of searching
|
||||
in our [JIRA issue tracker][] to see if you can find something similar. If you
|
||||
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.
|
||||
Is there already an issue that addresses your concern? Do a bit of searching
|
||||
in our [JIRA issue tracker][] to see if you can find something similar. If not,
|
||||
please create a new issue before submitting a pull request unless the change is
|
||||
truly trivial, e.g. typo fixes, removing compiler warnings, etc.
|
||||
|
||||
### Discuss non-trivial contribution ideas with committers
|
||||
## Discuss non-trivial contribution ideas with committers
|
||||
|
||||
If you're considering anything more than correcting a typo or fixing a minor
|
||||
bug, please discuss it on the [spring-framework-contrib][] mailing list before
|
||||
submitting a pull request. We're happy to provide guidance, but please spend an
|
||||
hour or two researching the subject on your own, including searching the mailing
|
||||
hour or two researching the subject on your own including searching the mailing
|
||||
list for prior discussions.
|
||||
|
||||
### Sign the Contributor License Agreement
|
||||
## Sign the Contributor License Agreement
|
||||
|
||||
If you have not previously done so, please fill out and submit the
|
||||
[SpringSource CLA form][]. You'll receive a token when this process is complete.
|
||||
@@ -45,34 +42,29 @@ your pull request:
|
||||
I have signed and agree to the terms of the SpringSource Individual
|
||||
Contributor License Agreement.
|
||||
|
||||
You do not need to include your token/id. Please add the above statement to all
|
||||
You do not need to include your token/id. Please add the statement above to all
|
||||
future pull requests as well, simply so that the Spring Framework team knows
|
||||
immediately that this process is complete.
|
||||
|
||||
## Create a Branch
|
||||
|
||||
### Branch from `master`
|
||||
## Create your branch from `master`
|
||||
|
||||
Master currently represents work toward Spring Framework 4.0. Please submit
|
||||
all pull requests there, even bug fixes and minor improvements. Backports to
|
||||
`3.2.x` will be considered on a case-by-case basis.
|
||||
|
||||
|
||||
### Use short branch names
|
||||
## Use short branch names
|
||||
|
||||
Branches used when submitting pull requests should preferably be named
|
||||
according to JIRA issues, e.g. 'SPR-1234'. Otherwise, use succinct, lower-case,
|
||||
dash (-) delimited names, such as 'fix-warnings', 'fix-typo', etc. In
|
||||
[fork-and-edit][] cases, the GitHub default 'patch-1' is fine as well. This is
|
||||
important, because branch names show up in the merge commits that result from
|
||||
accepting pull requests and should be as expressive and concise as possible.
|
||||
accepting pull requests, and should be as expressive and concise as possible.
|
||||
|
||||
## Use Spring Framework Code Style
|
||||
|
||||
The complete [Spring Framework Code Style][] reference is available on the wiki, but
|
||||
here's a quick summary:
|
||||
|
||||
### Mind the whitespace
|
||||
## Mind the whitespace
|
||||
|
||||
Please carefully follow the whitespace and formatting conventions already
|
||||
present in the framework.
|
||||
@@ -84,16 +76,16 @@ present in the framework.
|
||||
1. Aim to wrap code at 90 characters, but favor readability over wrapping
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
naming conventions, etc.
|
||||
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
|
||||
if necessary
|
||||
if necessary
|
||||
|
||||
|
||||
### Add Apache license header to all new classes
|
||||
## Add Apache license header to all new classes
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -111,24 +103,24 @@ present in the framework.
|
||||
package ...;
|
||||
```
|
||||
|
||||
### Update Apache license header in modified files as necessary
|
||||
## Update Apache license header to modified files as necessary
|
||||
|
||||
Always check the date range in the license header. For example, if you've
|
||||
modified a file in 2014 whose header still reads:
|
||||
modified a file in 2013 whose header still reads
|
||||
|
||||
```java
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2014 accordingly:
|
||||
then be sure to update it to 2013 appropriately
|
||||
|
||||
```java
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
## Use @since tags for newly-added public API types and methods
|
||||
|
||||
For example:
|
||||
e.g.
|
||||
|
||||
```java
|
||||
/**
|
||||
@@ -140,13 +132,11 @@ For example:
|
||||
*/
|
||||
```
|
||||
|
||||
## Prepare Your Commit
|
||||
## Submit JUnit test cases for all behavior changes
|
||||
|
||||
### Submit JUnit test cases for all behavior changes
|
||||
|
||||
Search the codebase to find related tests and add additional `@Test` methods
|
||||
as appropriate. It is also acceptable to submit test cases on a per JIRA issue
|
||||
basis, for example:
|
||||
Search the codebase to find related unit tests and add additional @Test methods
|
||||
within. It is also acceptable to submit test cases on a per JIRA issue basis,
|
||||
e.g.
|
||||
|
||||
```java
|
||||
package org.springframework.beans.factory.support;
|
||||
@@ -171,15 +161,15 @@ public class Spr8954Tests {
|
||||
```
|
||||
|
||||
|
||||
### Squash commits
|
||||
## Squash commits
|
||||
|
||||
Use `git rebase --interactive --autosquash`, `git add --patch`, and other tools
|
||||
to "squash" multiple commits into a single atomic commit. In addition to the man
|
||||
pages for git, there are many resources online to help you understand how these
|
||||
tools work. The [Rewriting History section of Pro Git][] provides a good overview.
|
||||
Use `git rebase --interactive`, `git add --patch` and other tools to "squash"
|
||||
multiple commits into atomic changes. In addition to the man pages for git,
|
||||
there are many resources online to help you understand how these tools work.
|
||||
Here is one: http://book.git-scm.com/4_interactive_rebasing.html.
|
||||
|
||||
|
||||
### Use real name in git commits
|
||||
## Use real name in git commits
|
||||
|
||||
Please configure git to use your real first and last name for any commits you
|
||||
intend to submit as pull requests. For example, this is not acceptable:
|
||||
@@ -191,26 +181,26 @@ submitted against the SpringSource contributor license agreement:
|
||||
|
||||
Author: First Last <user@mail.com>
|
||||
|
||||
This helps ensure traceability against the CLA and also goes a long way to
|
||||
This helps ensure traceability against the CLA, and also goes a long way to
|
||||
ensuring useful output from tools like `git shortlog` and others.
|
||||
|
||||
You can configure this via the account admin area in GitHub (useful for
|
||||
fork-and-edit cases); _globally_ on your machine with
|
||||
You can configure this globally via the account admin area GitHub (useful for
|
||||
fork-and-edit cases); globally with
|
||||
|
||||
git config --global user.name "First Last"
|
||||
git config --global user.email user@mail.com
|
||||
|
||||
or _locally_ for the `spring-framework` repository only by omitting the
|
||||
'--global' flag:
|
||||
or locally for the spring-framework repository only by omitting the '--global'
|
||||
flag:
|
||||
|
||||
cd spring-framework
|
||||
git config user.name "First Last"
|
||||
git config user.email user@mail.com
|
||||
|
||||
|
||||
### Format commit messages
|
||||
## Format commit messages
|
||||
|
||||
Please read and follow the [Commit Guidelines section of Pro Git][].
|
||||
Please read and follow the [commit guidelines section of Pro Git][].
|
||||
|
||||
Most importantly, please format your commit messages in the following way
|
||||
(adapted from the commit template in the link above):
|
||||
@@ -235,33 +225,31 @@ Most importantly, please format your commit messages in the following way
|
||||
|
||||
|
||||
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. Begin the subject line sentence with a capitalized verb, e.g. "Add, Prune,
|
||||
Fix, Introduce, Avoid, etc."
|
||||
1. Do not end the subject line with a period
|
||||
1. Restrict the subject line to 50 characters or less if possible
|
||||
1. Keep the subject line to 50 characters or less if possible
|
||||
1. Wrap lines in the body at 72 characters or less
|
||||
1. Mention associated JIRA issue(s) at the end of the commit comment, prefixed
|
||||
with "Issue: " as above
|
||||
with "Issue: " as above
|
||||
1. In the body of the commit message, explain how things worked before this
|
||||
commit, what has changed, and how things work now
|
||||
commit, what has changed, and how things work now
|
||||
|
||||
For examples of this style, issue a `git log --author=cbeams` in the
|
||||
`spring-framework` git repository. For convenience, here are several such commits:
|
||||
spring-framework git repository. For convenience, here are several such commits:
|
||||
|
||||
- https://github.com/spring-projects/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
|
||||
- https://github.com/spring-projects/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
|
||||
- https://github.com/spring-projects/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
|
||||
- https://github.com/spring-projects/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
|
||||
https://github.com/SpringSource/spring-framework/commit/08e2669b84ec0faa2f7904441fe39ac70b65b078
|
||||
https://github.com/SpringSource/spring-framework/commit/1d9d3e6ff79ce9f0eca03b02cd1df705925575da
|
||||
https://github.com/SpringSource/spring-framework/commit/8e0b1c3a5f957af3049cfa0438317177e16d6de6
|
||||
https://github.com/SpringSource/spring-framework/commit/b787a68f2050df179f7036b209aa741230a02477
|
||||
|
||||
## Run the Final Checklist
|
||||
## Run all tests prior to submission
|
||||
|
||||
### Run all tests prior to submission
|
||||
|
||||
See the [building from source][] section of the `README` for instructions. Make
|
||||
See the [building from source][] section of the README for instructions. Make
|
||||
sure that all tests pass prior to submitting your pull request.
|
||||
|
||||
|
||||
### Submit your pull request
|
||||
## Submit your pull request
|
||||
|
||||
Subject line:
|
||||
|
||||
@@ -273,7 +261,7 @@ 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
|
||||
1. Add any additional information and ask questions; start a conversation, or
|
||||
continue one from JIRA
|
||||
1. Mention the JIRA issue ID
|
||||
1. Also mention that you have submitted the CLA as described above
|
||||
@@ -284,12 +272,12 @@ the commit message. This is fine, but please also include the items above in the
|
||||
body of the request.
|
||||
|
||||
|
||||
### Mention your pull request on the associated JIRA issue
|
||||
## Mention your pull request on the associated JIRA issue
|
||||
|
||||
Add a comment to the associated JIRA issue(s) linking to your new pull request.
|
||||
|
||||
|
||||
### Expect discussion and rework
|
||||
## Expect discussion and rework
|
||||
|
||||
The Spring team takes a very conservative approach to accepting contributions to
|
||||
the framework. This is to keep code quality and stability as high as possible,
|
||||
@@ -301,15 +289,13 @@ strongly recommend discussing any serious submissions with the Spring Framework
|
||||
team _prior_ to engaging in serious development work.
|
||||
|
||||
Note that you can always force push (`git push -f`) reworked / rebased commits
|
||||
against the branch used to submit your pull request. In other words, you do not
|
||||
need to issue a new pull request when asked to make changes.
|
||||
against the branch used to submit your pull request. i.e. you do not need to
|
||||
issue a new pull request when asked to make changes.
|
||||
|
||||
[help documentation]: http://help.github.com/send-pull-requests
|
||||
[JIRA issue tracker]: https://jira.spring.io/browse/SPR
|
||||
[JIRA issue tracker]: https://jira.springsource.org/browse/SPR
|
||||
[spring-framework-contrib]: https://groups.google.com/forum/#!forum/spring-framework-contrib
|
||||
[SpringSource CLA form]: https://support.springsource.com/spring_committer_signup
|
||||
[fork-and-edit]: https://github.com/blog/844-forking-with-the-edit-button
|
||||
[Spring Framework Code Style]: https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Code-Style
|
||||
[Rewriting History section of Pro Git]: http://git-scm.com/book/en/Git-Tools-Rewriting-History
|
||||
[Commit Guidelines section of Pro Git]: http://git-scm.com/book/en/Distributed-Git-Contributing-to-a-Project#Commit-Guidelines
|
||||
[building from source]: https://github.com/spring-projects/spring-framework#building-from-source
|
||||
[commit guidelines section of Pro Git]: http://progit.org/book/ch5-2.html#commit_guidelines
|
||||
[building from source]: https://github.com/SpringSource/spring-framework#building-from-source
|
||||
|
||||
@@ -7,10 +7,10 @@ can focus on application-level business logic, without unnecessary ties to
|
||||
specific deployment environments.
|
||||
|
||||
The framework also serves as the foundation for [Spring Integration][], [Spring
|
||||
Batch][] and the rest of the Spring [family of projects][]. Browse the repositories
|
||||
under the [Spring organization][] on GitHub for a full list.
|
||||
Batch][] and the rest of the Spring [family of projects][]. Browse the
|
||||
repositories under the [SpringSource organization][] on GitHub for a full list.
|
||||
|
||||
## Downloading Artifacts
|
||||
## Downloading artifacts
|
||||
See [downloading Spring artifacts][] for Maven repository information. Unable to
|
||||
use Maven or other transitive dependency management tools? See [building a
|
||||
distribution with dependencies][].
|
||||
@@ -18,7 +18,7 @@ distribution with dependencies][].
|
||||
## Documentation
|
||||
See the current [Javadoc][] and [reference docs][].
|
||||
|
||||
## Getting Support
|
||||
## Getting support
|
||||
Check out the [Spring forums][] and the [spring][spring tag] and
|
||||
[spring-mvc][spring-mvc tag] tags on [Stack Overflow][]. [Commercial support][]
|
||||
is available too.
|
||||
@@ -30,29 +30,30 @@ bug? Please consider submitting a reproduction project via the
|
||||
[spring-framework-issues][] GitHub repository. The [readme][] there provides
|
||||
simple step-by-step instructions.
|
||||
|
||||
## Building from Source
|
||||
## Building from source
|
||||
The Spring Framework uses a [Gradle][]-based build system. In the instructions
|
||||
below, [`./gradlew`][] is invoked from the root of the source tree and serves as
|
||||
a cross-platform, self-contained bootstrap mechanism for the build.
|
||||
|
||||
### Prerequisites
|
||||
### prerequisites
|
||||
|
||||
[Git][] and [OpenJDK 8 early access build 100 or later][JDK8 build]
|
||||
|
||||
Be sure that your `JAVA_HOME` environment variable points to the `jdk1.8.0` folder
|
||||
extracted from the JDK download.
|
||||
|
||||
### Check out sources
|
||||
`git clone git@github.com:spring-projects/spring-framework.git`
|
||||
### check out sources
|
||||
`git clone git://github.com/SpringSource/spring-framework.git`
|
||||
|
||||
### Import sources into your IDE
|
||||
### 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.
|
||||
> **Note:** Per the prerequisites above, ensure that you have JDK 8 configured
|
||||
properly in your IDE.
|
||||
|
||||
### Install all spring-\* jars into your local Maven cache
|
||||
### install all spring-\* jars into your local Maven cache
|
||||
`./gradlew install`
|
||||
|
||||
### Compile and test; build all jars, distribution zips, and docs
|
||||
### compile and test, build all jars, distribution zips and docs
|
||||
`./gradlew build`
|
||||
|
||||
... and discover more commands with `./gradlew tasks`. See also the [Gradle
|
||||
@@ -61,41 +62,40 @@ build and release FAQ][].
|
||||
## Contributing
|
||||
[Pull requests][] are welcome; see the [contributor guidelines][] for details.
|
||||
|
||||
## Staying in Touch
|
||||
Follow [@SpringCentral][] as well as [@SpringFramework][] and its [team members][]
|
||||
on Twitter. In-depth articles can be found at [The Spring Blog][], and releases
|
||||
are announced via our [news feed][].
|
||||
## Staying in touch
|
||||
Follow [@springframework][] and its [team members][] on Twitter. In-depth
|
||||
articles can be found at the SpringSource [team blog][], and releases are
|
||||
announced via our [news feed][].
|
||||
|
||||
## License
|
||||
The Spring Framework is released under version 2.0 of the [Apache License][].
|
||||
|
||||
[Spring Integration]: https://github.com/spring-projects/spring-integration
|
||||
[Spring Batch]: https://github.com/spring-projects/spring-batch
|
||||
[family of projects]: http://spring.io/projects
|
||||
[Spring organization]: https://github.com/spring-projects
|
||||
[downloading Spring artifacts]: https://github.com/spring-projects/spring-framework/wiki/Downloading-Spring-artifacts
|
||||
[building a distribution with dependencies]: https://github.com/spring-projects/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://docs.spring.io/spring-framework/docs/current/javadoc-api/
|
||||
[reference docs]: http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/
|
||||
[Spring forums]: http://forum.spring.io/
|
||||
[Spring Integration]: https://github.com/SpringSource/spring-integration
|
||||
[Spring Batch]: https://github.com/SpringSource/spring-batch
|
||||
[family of projects]: http://springsource.org/projects
|
||||
[SpringSource organization]: https://github.com/SpringSource
|
||||
[downloading Spring artifacts]: https://github.com/SpringSource/spring-framework/wiki/Downloading-Spring-artifacts
|
||||
[building a distribution with dependencies]: https://github.com/SpringSource/spring-framework/wiki/Building-a-distribution-with-dependencies
|
||||
[Javadoc]: http://static.springsource.org/spring-framework/docs/current/javadoc-api
|
||||
[reference docs]: http://static.springsource.org/spring-framework/docs/current/spring-framework-reference
|
||||
[Spring forums]: http://forum.springsource.org
|
||||
[spring tag]: http://stackoverflow.com/questions/tagged/spring
|
||||
[spring-mvc tag]: http://stackoverflow.com/questions/tagged/spring-mvc
|
||||
[Stack Overflow]: http://stackoverflow.com/faq
|
||||
[Commercial support]: http://spring.io/services
|
||||
[Spring Framework JIRA]: https://jira.spring.io/browse/SPR
|
||||
[the lifecycle of an issue]: https://github.com/spring-projects/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[readme]: https://github.com/spring-projects/spring-framework-issues#readme
|
||||
[Commercial support]: http://springsource.com/support/springsupport
|
||||
[Spring Framework JIRA]: http://jira.springsource.org/browse/SPR
|
||||
[the lifecycle of an issue]: https://github.com/cbeams/spring-framework/wiki/The-Lifecycle-of-an-Issue
|
||||
[spring-framework-issues]: https://github.com/SpringSource/spring-framework-issues#readme
|
||||
[readme]: https://github.com/SpringSource/spring-framework-issues#readme
|
||||
[Gradle]: http://gradle.org
|
||||
[`./gradlew`]: http://vimeo.com/34436402
|
||||
[Git]: http://help.github.com/set-up-git-redirect
|
||||
[JDK8 build]: http://jdk8.java.net/download.html
|
||||
[Gradle build and release FAQ]: https://github.com/spring-projects/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Gradle build and release FAQ]: https://github.com/SpringSource/spring-framework/wiki/Gradle-build-and-release-FAQ
|
||||
[Pull requests]: http://help.github.com/send-pull-requests
|
||||
[contributor guidelines]: https://github.com/spring-projects/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@SpringFramework]: https://twitter.com/springframework
|
||||
[@SpringCentral]: https://twitter.com/springcentral
|
||||
[team members]: https://twitter.com/springframework/team/members
|
||||
[The Spring Blog]: http://spring.io/blog/
|
||||
[news feed]: http://spring.io/blog/category/news
|
||||
[contributor guidelines]: https://github.com/SpringSource/spring-framework/blob/master/CONTRIBUTING.md
|
||||
[@springframework]: http://twitter.com/springframework
|
||||
[team members]: http://twitter.com/springframework/team/members
|
||||
[team blog]: http://blog.springsource.org
|
||||
[news feed]: http://www.springsource.org/news-events
|
||||
[Apache License]: http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
+143
-195
@@ -3,43 +3,31 @@ buildscript {
|
||||
maven { url "http://repo.springsource.org/plugins-release" }
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.5")
|
||||
classpath("org.asciidoctor:asciidoctor-gradle-plugin:0.7.0")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.8")
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
moduleProjects = subprojects.findAll {
|
||||
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
|
||||
}
|
||||
}
|
||||
|
||||
configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.2"
|
||||
ext.eclipseLinkVersion = "2.4.2"
|
||||
ext.groovyVersion = "1.8.9"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.2.14.Final"
|
||||
ext.hibVal4Version = "4.3.2.Final"
|
||||
ext.hsqldbVersion = "2.3.2"
|
||||
ext.jackson1Version = "1.9.13"
|
||||
ext.jackson2Version = "2.3.4"
|
||||
ext.jasperReportsVersion = "5.5.1"
|
||||
ext.jettyVersion = "9.1.5.v20140505"
|
||||
ext.jodaVersion = "2.3"
|
||||
ext.junitVersion = "4.11"
|
||||
ext.openJpaVersion = "2.2.2"
|
||||
ext.slf4jVersion = "1.7.7"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.4"
|
||||
ext.tomcatVersion = "8.0.9"
|
||||
ext.xstreamVersion = "1.4.7"
|
||||
ext.aspectjVersion = "1.7.4"
|
||||
ext.groovyVersion = "1.8.9"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.2.8.Final"
|
||||
ext.hibValVersion = "4.3.1.Final"
|
||||
ext.hsqldbVersion = "2.3.1"
|
||||
ext.jackson1Version = "1.9.13"
|
||||
ext.jackson2Version = "2.3.1"
|
||||
ext.jettyVersion = "9.1.1.v20140108"
|
||||
ext.jodaVersion = "2.3"
|
||||
ext.junitVersion = "4.11"
|
||||
ext.slf4jVersion = "1.7.5"
|
||||
ext.xstreamVersion = "1.4.6"
|
||||
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "java"
|
||||
@@ -77,30 +65,25 @@ configure(allprojects) { project ->
|
||||
systemProperty("java.awt.headless", "true")
|
||||
systemProperty("testGroups", project.properties.get("testGroups"))
|
||||
scanForTestClasses = false
|
||||
include(["**/*Tests.class", "**/*Test.class"])
|
||||
// Since we set scanForTestClasses to false, we need to filter out inner
|
||||
// classes with the "$" pattern; otherwise, using -Dtest.single=MyTests to
|
||||
// run MyTests by itself will fail if MyTests contains any inner classes.
|
||||
exclude(["**/Abstract*.class", '**/*$*'])
|
||||
include '**/*Tests.*'
|
||||
exclude '**/*Abstract*.*'
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "http://repo.spring.io/libs-release" }
|
||||
maven { url "http://repo.spring.io/milestone" } // for AspectJ 1.8.0.M1
|
||||
maven { url "https://oss.sonatype.org/content/repositories/releases" } // javax.cache
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile("junit:junit:${junitVersion}") {
|
||||
exclude group:'org.hamcrest', module:'hamcrest-core'
|
||||
}
|
||||
testCompile("org.mockito:mockito-core:1.9.5") {
|
||||
exclude group:'org.hamcrest', module:'hamcrest-core'
|
||||
}
|
||||
testCompile("junit:junit:${junitVersion}")
|
||||
testCompile("org.hamcrest:hamcrest-all:1.3")
|
||||
testCompile("org.mockito:mockito-core:1.9.5")
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
"http://docs.oracle.com/javase/7/docs/api/",
|
||||
"http://docs.oracle.com/javaee/7/api/",
|
||||
"http://docs.oracle.com/javaee/6/api/",
|
||||
"http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/", // CommonJ
|
||||
"http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/",
|
||||
"http://glassfish.java.net/nonav/docs/v3/api/",
|
||||
@@ -110,12 +93,11 @@ configure(allprojects) { project ->
|
||||
"http://commons.apache.org/proper/commons-codec/apidocs/",
|
||||
"http://commons.apache.org/proper/commons-dbcp/apidocs/",
|
||||
"http://portals.apache.org/pluto/portlet-2.0-apidocs/",
|
||||
"http://tiles.apache.org/tiles-request/apidocs/",
|
||||
"http://tiles.apache.org/framework/apidocs/",
|
||||
"http://aopalliance.sourceforge.net/doc/",
|
||||
"http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/",
|
||||
"http://ehcache.org/apidocs/",
|
||||
"http://quartz-scheduler.org/api/2.2.0/",
|
||||
"http://quartz-scheduler.org/api/2.1.7/",
|
||||
"http://jackson.codehaus.org/1.9.4/javadoc/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.3.0/",
|
||||
"http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/",
|
||||
@@ -156,10 +138,10 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
// don't include or exclude anything explicitly by default. See SPR-12085.
|
||||
task sourcesJar(type: Jar, dependsOn:classes) {
|
||||
classifier = "sources"
|
||||
from sourceSets.main.allJava.srcDirs
|
||||
include "**/*.java", "**/*.aj"
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar) {
|
||||
@@ -188,8 +170,8 @@ project("spring-build-src") {
|
||||
project("spring-core") {
|
||||
description = "Spring Core"
|
||||
|
||||
// As of Spring 4.0.3, spring-core includes asm 5.0 and repackages cglib 3.1, inlining
|
||||
// both into the spring-core jar. cglib 3.1 itself depends on asm 4+, and is therefore
|
||||
// As of Spring 4.0, spring-core includes asm 4.2 and repackages cglib 3.1, inlining
|
||||
// both into the spring-core jar. cglib 3.1 itself depends on asm 4, and is therefore
|
||||
// further transformed by the JarJar task to depend on org.springframework.asm; this
|
||||
// avoids including two different copies of asm unnecessarily.
|
||||
def cglibVersion = "3.1"
|
||||
@@ -249,11 +231,11 @@ project("spring-core") {
|
||||
jarjar("com.googlecode.jarjar:jarjar:1.3")
|
||||
|
||||
compile(files(cglibRepackJar))
|
||||
compile("commons-logging:commons-logging:1.1.3")
|
||||
compile("commons-logging:commons-logging:1.1.1")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("net.sf.jopt-simple:jopt-simple:4.6")
|
||||
optional("log4j:log4j:1.2.17")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.3")
|
||||
testCompile("org.codehaus.woodstox:wstx-asl:3.2.7") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
@@ -285,14 +267,14 @@ project("spring-beans") {
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
optional("javax.el:javax.el-api:2.2.4")
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-beans-groovy") {
|
||||
description "Groovy Bean Definitions"
|
||||
project('spring-beans-groovy') {
|
||||
description 'Groovy Bean Definitions'
|
||||
merge.into = project(":spring-beans")
|
||||
apply plugin: "groovy"
|
||||
|
||||
@@ -306,7 +288,7 @@ project("spring-beans-groovy") {
|
||||
sourceSets {
|
||||
main {
|
||||
groovy {
|
||||
srcDir "src/main/java"
|
||||
srcDir 'src/main/java'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,12 +360,12 @@ project("spring-context") {
|
||||
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("org.hibernate:hibernate-validator:${hibVal4Version}")
|
||||
optional("org.hibernate:hibernate-validator:${hibValVersion}")
|
||||
optional("joda-time:joda-time:${jodaVersion}")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.jruby:jruby:1.7.12")
|
||||
optional("org.jruby:jruby:1.7.10")
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
@@ -404,9 +386,8 @@ project("spring-messaging") {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-context"))
|
||||
optional("org.projectreactor:reactor-core:1.1.3.RELEASE")
|
||||
optional("org.projectreactor:reactor-net:1.1.3.RELEASE")
|
||||
optional("org.projectreactor:reactor-tcp:1.0.1.RELEASE")
|
||||
optional("org.projectreactor:reactor-core:1.0.0.RELEASE")
|
||||
optional("org.projectreactor:reactor-tcp:1.0.0.RELEASE")
|
||||
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet-api"
|
||||
}
|
||||
@@ -425,9 +406,8 @@ project("spring-messaging") {
|
||||
testCompile("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet-api"
|
||||
}
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:8.0.0-RC10")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:8.0.0-RC10")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
@@ -456,6 +436,11 @@ project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
// The following is a work-around until the Gradle build uses
|
||||
// Ant 1.9.x by default. This is necessary to avoid the genCastor
|
||||
// "Class not found: javac1.8" issue with Ant versions prior to 1.9.x
|
||||
ant.properties["build.compiler"] = "javac1.7"
|
||||
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
@@ -466,24 +451,14 @@ project("spring-oxm") {
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional("org.codehaus.castor:castor-xml:1.3.3") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
exclude group: "org.springframework", module: "spring-context"
|
||||
}
|
||||
optional("org.apache.xmlbeans:xmlbeans:2.6.0") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
optional("com.thoughtworks.xstream:xstream:${xstreamVersion}") {
|
||||
exclude group: 'xpp3', module: 'xpp3_min'
|
||||
exclude group: 'xmlpull', module: 'xmlpull'
|
||||
}
|
||||
optional("com.thoughtworks.xstream:xstream:${xstreamVersion}")
|
||||
optional("org.jibx:jibx-run:1.2.5")
|
||||
optional("org.apache.xmlbeans:xmlbeans:2.6.0")
|
||||
optional("org.codehaus.castor:castor-xml:1.3.2")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xpp3:xpp3:1.1.3.4.O")
|
||||
testCompile("org.codehaus.jettison:jettison:1.0.1") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
testCompile("org.codehaus.jettison:jettison:1.0.1")
|
||||
testCompile("xmlunit:xmlunit:1.3")
|
||||
testCompile("xmlpull:xmlpull:1.1.3.4a")
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
@@ -499,10 +474,10 @@ project("spring-jms") {
|
||||
compile(project(":spring-aop"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-tx"))
|
||||
provided("javax.jms:jms-api:1.1-rev-1")
|
||||
provided("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1")
|
||||
optional(project(":spring-oxm"))
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("javax.transaction:javax.transaction-api:1.2")
|
||||
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
|
||||
optional("javax.resource:connector-api:1.5")
|
||||
optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
@@ -517,12 +492,12 @@ project("spring-jdbc") {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-tx"))
|
||||
optional(project(":spring-context")) // for JndiDataSourceLookup
|
||||
optional("javax.transaction:javax.transaction-api:1.2")
|
||||
optional("com.mchange:c3p0:0.9.2.1")
|
||||
optional("org.apache.geronimo.specs:geronimo-jta_1.1_spec:1.1")
|
||||
optional("c3p0:c3p0:0.9.1.2")
|
||||
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
optional("com.h2database:h2:1.3.176")
|
||||
optional("org.apache.derby:derby:10.10.2.0")
|
||||
optional("org.apache.derby:derbyclient:10.10.2.0")
|
||||
optional("com.h2database:h2:1.0.71")
|
||||
optional("org.apache.derby:derby:10.10.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.10.1.1")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,10 +510,10 @@ project("spring-context-support") {
|
||||
compile(project(":spring-context"))
|
||||
optional(project(":spring-jdbc")) // for Quartz support
|
||||
optional(project(":spring-tx")) // for Quartz support
|
||||
optional("javax.mail:javax.mail-api:1.4.7")
|
||||
optional("javax.cache:cache-api:1.0.0")
|
||||
optional("com.google.guava:guava:17.0")
|
||||
optional("net.sf.ehcache:ehcache-core:2.6.7")
|
||||
optional("javax.mail:mail:1.4.7")
|
||||
optional("javax.cache:cache-api:1.0.0-RC1")
|
||||
optional("com.google.guava:guava:16.0")
|
||||
optional("net.sf.ehcache:ehcache-core:2.6.5")
|
||||
optional("org.quartz-scheduler:quartz:1.8.6") {
|
||||
exclude group: "org.slf4j", module: "slf4j-log4j12"
|
||||
}
|
||||
@@ -546,15 +521,12 @@ project("spring-context-support") {
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("org.freemarker:freemarker:2.3.20")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
}
|
||||
testCompile("org.apache.poi:poi:3.10-FINAL")
|
||||
optional("net.sf.jasperreports:jasperreports:5.5.0")
|
||||
testCompile("org.apache.poi:poi:3.9")
|
||||
testCompile("commons-beanutils:commons-beanutils:1.8.0") // for Velocity/JasperReports
|
||||
testCompile("commons-digester:commons-digester:1.8.1") // for Velocity/JasperReports
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
testRuntime("com.sun.mail:javax.mail:1.4.7")
|
||||
}
|
||||
|
||||
// pick up **/*.types files in src/main
|
||||
@@ -571,18 +543,19 @@ project("spring-web") {
|
||||
compile(project(":spring-core"))
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional(project(":spring-oxm")) // for MarshallingHttpMessageConverter
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp:jsp-api:2.1")
|
||||
optional("javax.portlet:portlet-api:2.0")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("javax.el:javax.el-api:2.2.4")
|
||||
optional("javax.faces:javax.faces-api:2.2")
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("com.caucho:hessian:4.0.7")
|
||||
optional("commons-fileupload:commons-fileupload:1.3.1")
|
||||
optional("org.apache.httpcomponents:httpclient:4.3.5")
|
||||
optional("org.apache.httpcomponents:httpasyncclient:4.0.2")
|
||||
optional("commons-fileupload:commons-fileupload:1.3")
|
||||
optional("org.apache.httpcomponents:httpclient:4.3.1")
|
||||
optional("org.apache.httpcomponents:httpasyncclient:4.0")
|
||||
optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
optional("rome:rome:1.0")
|
||||
optional("taglibs:standard:1.1.2")
|
||||
optional("org.eclipse.jetty:jetty-servlet:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet-api"
|
||||
}
|
||||
@@ -591,11 +564,8 @@ project("spring-web") {
|
||||
}
|
||||
optional("log4j:log4j:1.2.17")
|
||||
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.3")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
|
||||
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
|
||||
}
|
||||
}
|
||||
|
||||
// pick up ContextLoader.properties in src/main
|
||||
@@ -613,7 +583,7 @@ project("spring-websocket") {
|
||||
optional(project(":spring-webmvc"))
|
||||
optional("javax.servlet:javax.servlet-api:3.1.0")
|
||||
optional("javax.websocket:javax.websocket-api:1.0")
|
||||
optional("org.apache.tomcat:tomcat-websocket:${tomcatVersion}") {
|
||||
optional("org.apache.tomcat:tomcat-websocket:8.0.0-RC10") {
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
|
||||
}
|
||||
@@ -626,20 +596,17 @@ project("spring-websocket") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
|
||||
optional("io.undertow:undertow-core:1.0.1.Final")
|
||||
optional("io.undertow:undertow-servlet:1.0.1.Final") {
|
||||
optional("io.undertow:undertow-core:1.0.0.Beta31")
|
||||
optional("io.undertow:undertow-servlet:1.0.0.Beta31") {
|
||||
exclude group: "org.jboss.spec.javax.servlet", module: "jboss-servlet-api_3.1_spec"
|
||||
exclude group: "org.jboss.spec.javax.annotation", module: "jboss-annotations-api_1.2_spec"
|
||||
}
|
||||
optional("io.undertow:undertow-websockets-jsr:1.0.1.Final") {
|
||||
optional("io.undertow:undertow-websockets-jsr:1.0.0.Beta31") {
|
||||
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.0_spec"
|
||||
}
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}")
|
||||
testCompile("org.projectreactor:reactor-core:1.1.3.RELEASE")
|
||||
testCompile("org.projectreactor:reactor-net:1.1.3.RELEASE")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:8.0.0-RC10")
|
||||
testCompile("org.projectreactor:reactor-core:1.0.0.RELEASE")
|
||||
testCompile("org.projectreactor:reactor-tcp:1.0.0.RELEASE")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
}
|
||||
@@ -657,27 +624,13 @@ project("spring-orm") {
|
||||
optional(project(":spring-context"))
|
||||
optional(project(":spring-web"))
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.5")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:${eclipseLinkVersion}")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:${eclipseLinkVersion}") {
|
||||
exclude group: 'org.eclipse.persistence', module: 'javax.persistence'
|
||||
}
|
||||
optional("org.hibernate:hibernate-core:${hibernate3Version}") {
|
||||
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
|
||||
exclude group: 'javax.transaction', module: 'jta'
|
||||
}
|
||||
optional("org.hibernate:hibernate-entitymanager:${hibernate3Version}") {
|
||||
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
|
||||
}
|
||||
optional("org.apache.openjpa:openjpa:${openJpaVersion}") {
|
||||
exclude group: 'junit', module: 'junit'
|
||||
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jpa_2.0_spec'
|
||||
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jta_1.1_spec'
|
||||
exclude group: 'org.apache.geronimo.specs', module: 'geronimo-jms_1.1_spec'
|
||||
}
|
||||
optional("javax.jdo:jdo-api:3.0.1") {
|
||||
exclude group: 'javax.transaction', module: 'transaction-api'
|
||||
}
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.core:2.4.0")
|
||||
optional("org.eclipse.persistence:org.eclipse.persistence.jpa:2.4.0")
|
||||
optional("org.hibernate:hibernate-core:${hibernate3Version}")
|
||||
optional("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
|
||||
optional("org.apache.openjpa:openjpa:2.2.1")
|
||||
optional("javax.jdo:jdo-api:3.0")
|
||||
optional("javax.servlet:javax.servlet-api:3.0.1")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
@@ -696,7 +649,6 @@ project("spring-orm-hibernate4") {
|
||||
optional("org.hibernate:hibernate-core:${hibernate4Version}")
|
||||
optional("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
|
||||
optional("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,41 +665,40 @@ project("spring-webmvc") {
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional(project(":spring-context-support")) // for Velocity support
|
||||
optional(project(":spring-oxm")) // for MarshallingView
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
|
||||
optional("javax.servlet.jsp:jsp-api:2.1")
|
||||
optional("javax.servlet:jstl:1.2")
|
||||
optional("net.sourceforge.jexcelapi:jxl:2.6.12")
|
||||
optional("org.apache.poi:poi:3.10-FINAL")
|
||||
optional("org.apache.poi:poi:3.9")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("velocity-tools:velocity-tools-view:1.4")
|
||||
optional("org.freemarker:freemarker:2.3.20")
|
||||
optional("com.lowagie:itext:2.1.7")
|
||||
optional("net.sf.jasperreports:jasperreports:$jasperReportsVersion") {
|
||||
optional("net.sf.jasperreports:jasperreports:5.5.0") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
}
|
||||
optional("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
optional("rome:rome:1.0")
|
||||
optional("org.apache.tiles:tiles-api:${tiles2Version}")
|
||||
optional("org.apache.tiles:tiles-core:${tiles2Version}") {
|
||||
optional("org.apache.tiles:tiles-api:2.2.2")
|
||||
optional("org.apache.tiles:tiles-core:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-servlet:${tiles2Version}") {
|
||||
optional("org.apache.tiles:tiles-servlet:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-jsp:${tiles2Version}") {
|
||||
optional("org.apache.tiles:tiles-jsp:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-el:${tiles2Version}") {
|
||||
optional("org.apache.tiles:tiles-el:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-extras:${tiles2Version}") {
|
||||
optional("org.apache.tiles:tiles-extras:2.2.2") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
exclude group: "org.apache.velocity", module: "velocity-tools"
|
||||
exclude group: "org.springframework", module: "spring-web"
|
||||
}
|
||||
testCompile(project(":spring-aop"))
|
||||
testCompile("rhino:js:1.7R1")
|
||||
testCompile("xmlunit:xmlunit:1.5")
|
||||
testCompile("xmlunit:xmlunit:1.3")
|
||||
testCompile("dom4j:dom4j:1.6.1") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
}
|
||||
@@ -763,9 +714,9 @@ project("spring-webmvc") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
testCompile("javax.validation:validation-api:1.0.0.GA")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
|
||||
testCompile("org.apache.httpcomponents:httpclient:4.3.5")
|
||||
testCompile("commons-fileupload:commons-fileupload:1.3.1")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
|
||||
testCompile("org.apache.httpcomponents:httpclient:4.3.1")
|
||||
testCompile("commons-fileupload:commons-fileupload:1.3")
|
||||
testCompile("commons-io:commons-io:1.3")
|
||||
testCompile("joda-time:joda-time:${jodaVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
@@ -783,23 +734,24 @@ project("spring-webmvc-tiles3") {
|
||||
provided(project(":spring-context"))
|
||||
provided(project(":spring-web"))
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("org.apache.tiles:tiles-api:${tiles3Version}")
|
||||
optional("org.apache.tiles:tiles-core:${tiles3Version}") {
|
||||
optional("javax.servlet.jsp:jsp-api:2.1")
|
||||
optional("javax.servlet:jstl:1.2")
|
||||
optional("javax.el:javax.el-api:2.2.4")
|
||||
optional("org.apache.tiles:tiles-request-api:1.0.1")
|
||||
optional("org.apache.tiles:tiles-api:3.0.1")
|
||||
optional("org.apache.tiles:tiles-core:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-servlet:${tiles3Version}") {
|
||||
optional("org.apache.tiles:tiles-servlet:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-jsp:${tiles3Version}") {
|
||||
optional("org.apache.tiles:tiles-jsp:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-el:${tiles3Version}") {
|
||||
optional("org.apache.tiles:tiles-el:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
optional("org.apache.tiles:tiles-extras:${tiles3Version}") {
|
||||
optional("org.apache.tiles:tiles-extras:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
exclude group: "org.springframework", module: "spring-web"
|
||||
}
|
||||
@@ -818,7 +770,7 @@ project("spring-webmvc-portlet") {
|
||||
compile(project(":spring-webmvc"))
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
provided("javax.portlet:portlet-api:2.0")
|
||||
optional("commons-fileupload:commons-fileupload:1.3.1")
|
||||
optional("commons-fileupload:commons-fileupload:1.3")
|
||||
}
|
||||
|
||||
// pick up DispatcherPortlet.properties in src/main
|
||||
@@ -839,40 +791,35 @@ project("spring-test") {
|
||||
optional(project(":spring-webmvc"))
|
||||
optional(project(":spring-webmvc-portlet"))
|
||||
optional("junit:junit:${junitVersion}")
|
||||
optional("org.testng:testng:6.8.8")
|
||||
optional("org.testng:testng:6.8.7")
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("javax.servlet.jsp:javax.servlet.jsp-api:2.2.1")
|
||||
optional("javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1")
|
||||
optional("org.apache.taglibs:taglibs-standard-jstlel:1.2.1") {
|
||||
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
|
||||
}
|
||||
optional("javax.servlet.jsp:jsp-api:2.1")
|
||||
optional("javax.servlet:jstl:1.2")
|
||||
optional("javax.portlet:portlet-api:2.0")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.hamcrest:hamcrest-core:1.3")
|
||||
optional("com.jayway.jsonpath:json-path:0.9.0")
|
||||
optional("xmlunit:xmlunit:1.5")
|
||||
optional("xmlunit:xmlunit:1.3")
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile(project(":spring-webmvc-tiles3"))
|
||||
testCompile("javax.mail:javax.mail-api:1.4.7")
|
||||
testCompile("javax.mail:mail:1.4.7")
|
||||
testCompile("javax.ejb:ejb-api:3.0")
|
||||
testCompile("org.hibernate:hibernate-core:${hibernate3Version}") {
|
||||
exclude group: 'org.hibernate.javax.persistence', module: 'hibernate-jpa-2.0-api'
|
||||
}
|
||||
testCompile("org.hibernate:hibernate-core:${hibernate3Version}")
|
||||
testCompile("org.hibernate:hibernate-entitymanager:${hibernate3Version}")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibVal4Version}")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibValVersion}")
|
||||
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
|
||||
testCompile("org.codehaus.jackson:jackson-mapper-asl:${jackson1Version}")
|
||||
testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
testCompile("rome:rome:1.0")
|
||||
testCompile("org.apache.tiles:tiles-api:${tiles3Version}")
|
||||
testCompile("org.apache.tiles:tiles-core:${tiles3Version}") {
|
||||
testCompile("org.apache.tiles:tiles-request-api:1.0.1")
|
||||
testCompile("org.apache.tiles:tiles-api:3.0.1")
|
||||
testCompile("org.apache.tiles:tiles-core:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
testCompile("org.apache.tiles:tiles-servlet:${tiles3Version}") {
|
||||
testCompile("org.apache.tiles:tiles-servlet:3.0.1") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
@@ -881,25 +828,26 @@ project("spring-test") {
|
||||
|
||||
task testNG(type: Test) {
|
||||
useTestNG()
|
||||
scanForTestClasses = false
|
||||
include(["**/testng/**/*Tests.class", "**/testng/**/*Test.class"])
|
||||
// Show STD_OUT & STD_ERR of the test JVM(s) on the console:
|
||||
// testLogging.showStandardStreams = true
|
||||
// forkEvery 1
|
||||
scanForTestClasses = false
|
||||
include "**/testng/**/*.*"
|
||||
exclude "**/FailingBeforeAndAfterMethodsTests.class"
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude "**/*TestCase.class"
|
||||
// Generate TestNG reports alongside JUnit reports.
|
||||
getReports().getHtml().setEnabled(true)
|
||||
// show standard out and standard error of the test JVM(s) on the console
|
||||
// testLogging.showStandardStreams = true
|
||||
}
|
||||
|
||||
test {
|
||||
dependsOn testNG
|
||||
useJUnit()
|
||||
exclude "**/testng/**/*.*"
|
||||
include "**/testng/FailingBeforeAndAfterMethodsTests"
|
||||
// "TestCase" classes are run by other test classes, not the build.
|
||||
exclude(["**/*TestCase.class", "**/*TestSuite.class"])
|
||||
}
|
||||
|
||||
task aggregateTestReports(type: TestReport) {
|
||||
destinationDir = test.reports.html.destination
|
||||
reportOn test, testNG
|
||||
}
|
||||
|
||||
check.dependsOn aggregateTestReports
|
||||
}
|
||||
|
||||
project("spring-aspects") {
|
||||
@@ -908,9 +856,9 @@ project("spring-aspects") {
|
||||
|
||||
dependencies {
|
||||
aspects(project(":spring-orm"))
|
||||
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
|
||||
rt("org.aspectj:aspectjrt:${aspectjVersion}")
|
||||
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
ajc("org.aspectj:aspectjtools:1.8.0.M1") // needed for ajc on JDK 8 only
|
||||
rt("org.aspectj:aspectjrt:1.8.0.M1") // needed for ajc on JDK 8 only
|
||||
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // exposing regular AspectJ version to users
|
||||
provided("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
optional(project(":spring-beans")) // for @Configurable support
|
||||
@@ -920,7 +868,7 @@ project("spring-aspects") {
|
||||
optional(project(":spring-tx")) // for JPA, @Transactional support
|
||||
testCompile(project(":spring-core")) // for CodeStyleAspect
|
||||
testCompile(project(":spring-test"))
|
||||
testCompile("javax.mail:javax.mail-api:1.4.7")
|
||||
testCompile("javax.mail:mail:1.4.7")
|
||||
}
|
||||
|
||||
eclipse.project {
|
||||
@@ -1057,7 +1005,7 @@ configure(rootProject) {
|
||||
|
||||
doFirst {
|
||||
classpath = files(
|
||||
// ensure Servlet 3.x and Hibernate 4.x have precedence on the javadoc
|
||||
// ensure servlet 3.x and Hibernate 4.x have precedence on the Javadoc
|
||||
// classpath over their respective 2.5 and 3.x variants
|
||||
project(":spring-webmvc").sourceSets.main.compileClasspath.files.find { it =~ "servlet-api" },
|
||||
rootProject.sourceSets.test.compileClasspath.files.find { it =~ "hibernate-core" },
|
||||
@@ -1094,8 +1042,8 @@ configure(rootProject) {
|
||||
classifier = "schema"
|
||||
description = "Builds -${classifier} archive containing all " +
|
||||
"XSDs for deployment at http://springframework.org/schema."
|
||||
duplicatesStrategy 'exclude'
|
||||
moduleProjects.each { subproject ->
|
||||
|
||||
subprojects.each { subproject ->
|
||||
def Properties schemas = new Properties();
|
||||
|
||||
subproject.sourceSets.main.resources.find {
|
||||
@@ -1141,7 +1089,7 @@ configure(rootProject) {
|
||||
into "${baseDir}/schema"
|
||||
}
|
||||
|
||||
moduleProjects.each { subproject ->
|
||||
subprojects.each { subproject ->
|
||||
into ("${baseDir}/libs") {
|
||||
from subproject.jar
|
||||
if (subproject.tasks.findByPath("sourcesJar")) {
|
||||
@@ -1194,7 +1142,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = "1.12"
|
||||
gradleVersion = "1.9"
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
|
||||
@@ -21,13 +21,16 @@ import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.artifacts.maven.Conf2ScopeMapping
|
||||
import org.gradle.api.plugins.MavenPlugin
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.plugins.ide.eclipse.EclipsePlugin
|
||||
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
|
||||
import org.gradle.plugins.ide.idea.IdeaPlugin
|
||||
import org.gradle.api.invocation.*
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that allows projects to merged together. Primarily developed to
|
||||
* allow Spring to support multiple incompatible versions of third-party
|
||||
* allow Spring to support multiple multiple incompatible versions of third-party
|
||||
* dependencies (for example Hibernate v3 and v4).
|
||||
* <p>
|
||||
* The 'merge' extension should be used to define how projects are merged, for example:
|
||||
@@ -73,13 +76,13 @@ class MergePlugin implements Plugin<Project> {
|
||||
|
||||
// Hook to perform the actual merge logic
|
||||
project.afterEvaluate{
|
||||
if (it.merge.into != null) {
|
||||
if(it.merge.into != null) {
|
||||
setup(it)
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to build runtimeMerge dependencies
|
||||
if (!attachedProjectsEvaluated) {
|
||||
if(!attachedProjectsEvaluated) {
|
||||
project.gradle.projectsEvaluated{
|
||||
postProcessProjects(it)
|
||||
}
|
||||
@@ -99,7 +102,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
// invoking a task will invoke the task with the same name on 'into' project
|
||||
["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish"].each {
|
||||
def task = project.tasks.findByPath(it)
|
||||
if (task) {
|
||||
if(task) {
|
||||
task.enabled = false
|
||||
task.dependsOn(project.merge.into.tasks.findByPath(it))
|
||||
}
|
||||
@@ -117,7 +120,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
private void setupMaven(Project project) {
|
||||
project.configurations.each { configuration ->
|
||||
Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
|
||||
if (mapping.scope) {
|
||||
if(mapping.scope) {
|
||||
Configuration intoConfiguration = project.merge.into.configurations.create(
|
||||
project.name + "-" + configuration.name)
|
||||
configuration.excludeRules.each {
|
||||
@@ -128,7 +131,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
configuration.dependencies.each {
|
||||
def intoCompile = project.merge.into.configurations.getByName("compile")
|
||||
// Protect against changing a compile scope dependency (SPR-10218)
|
||||
if (!intoCompile.dependencies.contains(it)) {
|
||||
if(!intoCompile.dependencies.contains(it)) {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
|
||||
|
||||
/**
|
||||
* Gradle plugin that automatically updates testCompile dependencies to include
|
||||
* the test source sets of project dependencies.
|
||||
@@ -40,10 +41,11 @@ class TestSourceSetDependenciesPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies, Project project) {
|
||||
for (def configurationName in ["compile", "optional", "provided", "testCompile"]) {
|
||||
private void collectProjectDependencies(Set<ProjectDependency> projectDependencies,
|
||||
Project project) {
|
||||
for(def configurationName in ["compile", "optional", "provided", "testCompile"]) {
|
||||
Configuration configuration = project.getConfigurations().findByName(configurationName)
|
||||
if (configuration) {
|
||||
if(configuration) {
|
||||
configuration.dependencies.findAll { it instanceof ProjectDependency }.each {
|
||||
projectDependencies.add(it)
|
||||
collectProjectDependencies(projectDependencies, it.dependencyProject)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.0.7.RELEASE
|
||||
version=4.0.1.RELEASE
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Wed Apr 30 13:06:57 CEST 2014
|
||||
#Wed Nov 20 13:14:38 PST 2013
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-1.12-bin.zip
|
||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-bin.zip
|
||||
|
||||
+2
-3
@@ -12,11 +12,10 @@ _Within your locally cloned spring-framework working directory:_
|
||||
|
||||
## Known issues
|
||||
|
||||
1. Those steps don't work currently for Intellij IDEA 13+
|
||||
2. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
|
||||
1. `spring-aspects` does not compile out of the box due to references to aspect types unknown to IDEA.
|
||||
See http://youtrack.jetbrains.com/issue/IDEA-64446 for details. In the meantime, the 'spring-aspects'
|
||||
module has been excluded from the overall project to avoid compilation errors.
|
||||
3. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
2. While all JUnit tests pass from the command line with Gradle, many will fail when run from IDEA.
|
||||
Resolving this is a work in progress. If attempting to run all JUnit tests from within IDEA, you will
|
||||
likely need to set the following VM options to avoid out of memory errors:
|
||||
-XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -240,7 +240,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
setArgumentNamesFromStringArray(tokens);
|
||||
}
|
||||
|
||||
public void setArgumentNamesFromStringArray(String... args) {
|
||||
public void setArgumentNamesFromStringArray(String[] args) {
|
||||
this.argumentNames = new String[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
this.argumentNames[i] = StringUtils.trimWhitespace(args[i]);
|
||||
|
||||
+54
-59
@@ -29,6 +29,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.weaver.BCException;
|
||||
import org.aspectj.weaver.patterns.NamePattern;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
import org.aspectj.weaver.tools.ContextBasedMatcher;
|
||||
@@ -107,8 +108,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private transient ClassLoader pointcutClassLoader;
|
||||
|
||||
private transient PointcutExpression pointcutExpression;
|
||||
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<Method, ShadowMatch>(32);
|
||||
@@ -186,13 +185,20 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
if (this.pointcutExpression == null) {
|
||||
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
|
||||
this.pointcutExpression = buildPointcutExpression();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
private PointcutExpression buildPointcutExpression() {
|
||||
ClassLoader cl = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
return buildPointcutExpression(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
@@ -246,22 +252,23 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
public boolean matches(Class<?> targetClass) {
|
||||
checkReadyToMatch();
|
||||
try {
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (ReflectionWorldException rwe) {
|
||||
logger.debug("PointcutExpression matching rejected target class", rwe);
|
||||
try {
|
||||
return this.pointcutExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
|
||||
// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
|
||||
PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
|
||||
if (fallbackExpression != null) {
|
||||
return fallbackExpression.couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
return getFallbackPointcutExpression(targetClass).couldMatchJoinPointsInType(targetClass);
|
||||
}
|
||||
catch (BCException bce) {
|
||||
logger.debug("Fallback PointcutExpression matching rejected target class", bce);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (BCException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -358,19 +365,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
|
||||
/**
|
||||
* Get a new pointcut expression based on a target class's loader rather than the default.
|
||||
* Get a new pointcut expression based on a target class's loader, rather
|
||||
* than the default.
|
||||
*/
|
||||
private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
|
||||
try {
|
||||
ClassLoader classLoader = targetClass.getClassLoader();
|
||||
if (classLoader != null && classLoader != this.pointcutClassLoader) {
|
||||
return buildPointcutExpression(classLoader);
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("Failed to create fallback PointcutExpression", ex);
|
||||
}
|
||||
return null;
|
||||
ClassLoader classLoader = targetClass.getClassLoader();
|
||||
return (classLoader != null ? buildPointcutExpression(classLoader) : this.pointcutExpression);
|
||||
}
|
||||
|
||||
private RuntimeTestWalker getRuntimeTestWalker(ShadowMatch shadowMatch) {
|
||||
@@ -396,51 +396,46 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
if (shadowMatch == null) {
|
||||
synchronized (this.shadowMatchCache) {
|
||||
// Not found - now check again with full lock...
|
||||
PointcutExpression fallbackExpression = null;
|
||||
Method methodToMatch = targetMethod;
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
PointcutExpression fallbackPointcutExpression = null;
|
||||
shadowMatch = this.shadowMatchCache.get(methodToMatch);
|
||||
if (shadowMatch == null) {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(targetMethod);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
catch (ReflectionWorld.ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
// in a special ClassLoader. Let's try the original method instead...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex2) {
|
||||
if (targetMethod == originalMethod) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
else {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(originalMethod);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex3) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's simply consider this method as non-matching.
|
||||
methodToMatch = originalMethod;
|
||||
fallbackPointcutExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
try {
|
||||
shadowMatch = fallbackPointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorld.ReflectionWorldException ex4) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
}
|
||||
else if (shadowMatch.maybeMatches() && fallbackExpression != null) {
|
||||
if (shadowMatch.maybeMatches() && fallbackPointcutExpression != null) {
|
||||
shadowMatch = new DefensiveShadowMatch(shadowMatch,
|
||||
fallbackExpression.matchesMethodExecution(methodToMatch));
|
||||
fallbackPointcutExpression.matchesMethodExecution(methodToMatch));
|
||||
}
|
||||
this.shadowMatchCache.put(targetMethod, shadowMatch);
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,24 +40,24 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.pointcut.setLocation(location);
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class<?>[] types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
public void setParameterNames(String... names) {
|
||||
public void setParameterNames(String[] names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return this.pointcut.getExpression();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -91,11 +91,9 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
|
||||
// Ignore AOP infrastructure such as scoped proxies.
|
||||
return bean;
|
||||
}
|
||||
|
||||
if (bean instanceof Advised) {
|
||||
Advised advised = (Advised) bean;
|
||||
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
|
||||
// Add our local Advisor to the existing proxy's Advisor chain...
|
||||
if (isEligible(bean, beanName)) {
|
||||
if (bean instanceof Advised) {
|
||||
Advised advised = (Advised) bean;
|
||||
if (this.beforeExistingAdvisors) {
|
||||
advised.addAdvisor(0, this.advisor);
|
||||
}
|
||||
@@ -104,47 +102,32 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
else {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
return proxyFactory.getProxy(this.beanClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
if (isEligible(bean, beanName)) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(bean);
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
return proxyFactory.getProxy(this.beanClassLoader);
|
||||
else {
|
||||
// No async proxy needed.
|
||||
return bean;
|
||||
}
|
||||
|
||||
// No async proxy needed.
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given bean is eligible for advising with this
|
||||
* post-processor's {@link Advisor}.
|
||||
* <p>Delegates to {@link #isEligible(Class)} for target class checking.
|
||||
* <p>Implements caching of {@code canApply} results per bean target class.
|
||||
* Can be overridden e.g. to specifically exclude certain beans by name.
|
||||
* <p>Note: Only called for regular bean instances but not for existing
|
||||
* proxy instances which implement {@link Advised} and allow for adding
|
||||
* the local {@link Advisor} to the existing proxy's {@link Advisor} chain.
|
||||
* For the latter, {@link #isEligible(Class)} is being called directly,
|
||||
* with the actual target class behind the existing proxy (as determined
|
||||
* by {@link AopUtils#getTargetClass(Object)}).
|
||||
* @param bean the bean instance
|
||||
* @param beanName the name of the bean
|
||||
* @see #isEligible(Class)
|
||||
*/
|
||||
protected boolean isEligible(Object bean, String beanName) {
|
||||
return isEligible(bean.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given class is eligible for advising with this
|
||||
* post-processor's {@link Advisor}.
|
||||
* <p>Implements caching of {@code canApply} results per bean target class.
|
||||
* @param targetClass the class to check against
|
||||
* @see AopUtils#getTargetClass(Object)
|
||||
* @see AopUtils#canApply(Advisor, Class)
|
||||
*/
|
||||
protected boolean isEligible(Class<?> targetClass) {
|
||||
protected boolean isEligible(Object bean, String beanName) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||
Boolean eligible = this.eligibleBeans.get(targetClass);
|
||||
if (eligible != null) {
|
||||
return eligible;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,10 +32,10 @@ public interface AdvisorChainFactory {
|
||||
* for the given advisor chain configuration.
|
||||
* @param config the AOP configuration in the form of an Advised object
|
||||
* @param method the proxied method
|
||||
* @param targetClass the target class (may be {@code null} to indicate a proxy without
|
||||
* target object, in which case the method's declaring class is the next best option)
|
||||
* @param targetClass the target class
|
||||
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
|
||||
*/
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class<?> targetClass);
|
||||
List<Object> getInterceptorsAndDynamicInterceptionAdvice(
|
||||
Advised config, Method method, Class<?> targetClass);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,6 @@ import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cglib.core.CodeGenerationException;
|
||||
import org.springframework.cglib.core.SpringNamingPolicy;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
import org.springframework.cglib.proxy.Dispatcher;
|
||||
@@ -46,7 +45,7 @@ import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
import org.springframework.cglib.transform.impl.UndeclaredThrowableStrategy;
|
||||
import org.springframework.cglib.transform.impl.MemorySafeUndeclaredThrowableStrategy;
|
||||
import org.springframework.core.SmartClassLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -184,19 +183,19 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
enhancer.setSuperclass(proxySuperClass);
|
||||
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
|
||||
Callback[] callbacks = getCallbacks(rootClass);
|
||||
Class<?>[] types = new Class<?>[callbacks.length];
|
||||
|
||||
for (int x = 0; x < types.length; x++) {
|
||||
types[x] = callbacks[x].getClass();
|
||||
}
|
||||
// fixedInterceptorMap only populated at this point, after getCallbacks call above
|
||||
|
||||
enhancer.setCallbackTypes(types);
|
||||
enhancer.setCallbackFilter(new ProxyCallbackFilter(
|
||||
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
|
||||
enhancer.setCallbackTypes(types);
|
||||
|
||||
// Generate the proxy class and create a proxy instance.
|
||||
return createProxyClassAndInstance(enhancer, callbacks);
|
||||
@@ -261,7 +260,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (!Object.class.equals(method.getDeclaringClass()) && !Modifier.isStatic(method.getModifiers()) &&
|
||||
Modifier.isFinal(method.getModifiers())) {
|
||||
logger.warn("Unable to proxy method [" + method + "] because it is final: " +
|
||||
"All calls to this method via a proxy will NOT be routed to the target instance.");
|
||||
"All calls to this method via a proxy will be routed directly to the proxy.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -604,7 +603,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
|
||||
|
||||
private final AdvisedSupport advised;
|
||||
private AdvisedSupport advised;
|
||||
|
||||
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
|
||||
this.advised = advised;
|
||||
@@ -622,8 +621,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
oldProxy = AopContext.setCurrentProxy(proxy);
|
||||
setProxyContext = true;
|
||||
}
|
||||
// May be null. Get as late as possible to minimize the time we
|
||||
// "own" the target, in case it comes from a pool...
|
||||
// May be null Get as late as possible to minimize the time we
|
||||
// "own" the target, in case it comes from a pool.
|
||||
target = getTarget();
|
||||
if (target != null) {
|
||||
targetClass = target.getClass();
|
||||
@@ -689,13 +688,13 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
private final MethodProxy methodProxy;
|
||||
|
||||
private final boolean publicMethod;
|
||||
private boolean protectedMethod;
|
||||
|
||||
public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
|
||||
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
|
||||
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
|
||||
this.methodProxy = methodProxy;
|
||||
this.publicMethod = Modifier.isPublic(method.getModifiers());
|
||||
this.protectedMethod = Modifier.isProtected(method.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -704,11 +703,11 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeJoinpoint() throws Throwable {
|
||||
if (this.publicMethod) {
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
if (this.protectedMethod) {
|
||||
return super.invokeJoinpoint();
|
||||
}
|
||||
else {
|
||||
return super.invokeJoinpoint();
|
||||
return this.methodProxy.invoke(this.target, this.arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -829,8 +828,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// of the target type. If so we know it never needs to have return type
|
||||
// massage and can use a dispatcher.
|
||||
// If the proxy is being exposed, then must use the interceptor the
|
||||
// correct one is already configured. If the target is not static, then
|
||||
// cannot use a dispatcher because the target cannot be released.
|
||||
// correct one is already configured. If the target is not static cannot
|
||||
// use a Dispatcher because the target can not then be released.
|
||||
if (exposeProxy || !isStatic) {
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
|
||||
+8
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,21 +50,19 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
|
||||
Advised config, Method method, Class<?> targetClass) {
|
||||
|
||||
// This is somewhat tricky... We have to process introductions first,
|
||||
// This is somewhat tricky... we have to process introductions first,
|
||||
// but we need to preserve order in the ultimate list.
|
||||
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
|
||||
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
|
||||
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
|
||||
boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
|
||||
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
|
||||
|
||||
for (Advisor advisor : config.getAdvisors()) {
|
||||
if (advisor instanceof PointcutAdvisor) {
|
||||
// Add it conditionally.
|
||||
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
|
||||
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
|
||||
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
|
||||
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
|
||||
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
|
||||
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
|
||||
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
|
||||
if (mm.isRuntime()) {
|
||||
// Creating a new object instance in the getInterceptors() method
|
||||
// isn't a problem as we normally cache created chains.
|
||||
@@ -80,7 +78,7 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
}
|
||||
else if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
|
||||
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
|
||||
Interceptor[] interceptors = registry.getInterceptors(advisor);
|
||||
interceptorList.addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
@@ -90,19 +88,18 @@ public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializ
|
||||
interceptorList.addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
}
|
||||
|
||||
return interceptorList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the Advisors contain matching introductions.
|
||||
*/
|
||||
private static boolean hasMatchingIntroductions(Advised config, Class<?> actualClass) {
|
||||
private static boolean hasMatchingIntroductions(Advised config, Class<?> targetClass) {
|
||||
for (int i = 0; i < config.getAdvisors().length; i++) {
|
||||
Advisor advisor = config.getAdvisors()[i];
|
||||
if (advisor instanceof IntroductionAdvisor) {
|
||||
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
|
||||
if (ia.getClassFilter().matches(actualClass)) {
|
||||
if (ia.getClassFilter().matches(targetClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -75,7 +75,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
*/
|
||||
|
||||
/** We use a static Log to avoid serialization issues */
|
||||
private static final Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
|
||||
private static Log logger = LogFactory.getLog(JdkDynamicAopProxy.class);
|
||||
|
||||
/** Config used to configure this proxy */
|
||||
private final AdvisedSupport advised;
|
||||
@@ -215,10 +215,8 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// is type-compatible. Note that we can't help if the target sets
|
||||
// a reference to itself in another returned object.
|
||||
retVal = proxy;
|
||||
}
|
||||
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
|
||||
throw new AopInvocationException(
|
||||
"Null return value from advice does not match primitive return type for: " + method);
|
||||
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
|
||||
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.framework;
|
||||
import org.aopalliance.intercept.Interceptor;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -46,8 +47,9 @@ public class ProxyFactory extends ProxyCreatorSupport {
|
||||
* @param target the target object to be proxied
|
||||
*/
|
||||
public ProxyFactory(Object target) {
|
||||
setTarget(target);
|
||||
Assert.notNull(target, "Target object must not be null");
|
||||
setInterfaces(ClassUtils.getAllInterfaces(target));
|
||||
setTarget(target);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -154,7 +154,7 @@ public class ProxyFactoryBean extends ProxyCreatorSupport
|
||||
* @see org.aopalliance.aop.Advice
|
||||
* @see org.springframework.aop.target.SingletonTargetSource
|
||||
*/
|
||||
public void setInterceptorNames(String... interceptorNames) {
|
||||
public void setInterceptorNames(String[] interceptorNames) {
|
||||
this.interceptorNames = interceptorNames;
|
||||
}
|
||||
|
||||
|
||||
+15
-57
@@ -40,18 +40,14 @@ import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
@@ -205,7 +201,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
* Ordering is significant: The TargetSource returned from the first matching
|
||||
* TargetSourceCreator (that is, the first that returns non-null) will be used.
|
||||
*/
|
||||
public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
|
||||
public void setCustomTargetSourceCreators(TargetSourceCreator[] targetSourceCreators) {
|
||||
this.customTargetSourceCreators = targetSourceCreators;
|
||||
}
|
||||
|
||||
@@ -216,7 +212,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
* This is perfectly valid, if "specific" interceptors such as matching
|
||||
* Advisors are all we want.
|
||||
*/
|
||||
public void setInterceptorNames(String... interceptorNames) {
|
||||
public void setInterceptorNames(String[] interceptorNames) {
|
||||
this.interceptorNames = interceptorNames;
|
||||
}
|
||||
|
||||
@@ -469,12 +465,12 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
|
||||
proxyFactory.copyFrom(this);
|
||||
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
if (shouldProxyTargetClass(beanClass, beanName)) {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
else {
|
||||
evaluateProxyInterfaces(beanClass, proxyFactory);
|
||||
if (!shouldProxyTargetClass(beanClass, beanName)) {
|
||||
// Must allow for introductions; can't just set interfaces to
|
||||
// the target's interfaces only.
|
||||
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
|
||||
for (Class<?> targetInterface : targetInterfaces) {
|
||||
proxyFactory.addInterface(targetInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,8 +491,10 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given bean should be proxied with its target class rather than its interfaces.
|
||||
* <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
|
||||
* Determine whether the given bean should be proxied with its target
|
||||
* class rather than its interfaces. Checks the
|
||||
* {@link #setProxyTargetClass "proxyTargetClass" setting} as well as the
|
||||
* {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
|
||||
* of the corresponding bean definition.
|
||||
* @param beanClass the class of the bean
|
||||
* @param beanName the name of the bean
|
||||
@@ -504,49 +502,9 @@ public abstract class AbstractAutoProxyCreator extends ProxyConfig
|
||||
* @see AutoProxyUtils#shouldProxyTargetClass
|
||||
*/
|
||||
protected boolean shouldProxyTargetClass(Class<?> beanClass, String beanName) {
|
||||
return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
|
||||
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the interfaces on the given bean class and apply them to the ProxyFactory,
|
||||
* if appropriate.
|
||||
* <p>Calls {@link #isConfigurationCallbackInterface} to filter for reasonable
|
||||
* proxy interfaces, falling back to a target-class proxy otherwise.
|
||||
* @param beanClass the class of the bean
|
||||
* @param proxyFactory the ProxyFactory for the bean
|
||||
*/
|
||||
private void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
|
||||
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
|
||||
boolean hasReasonableProxyInterface = false;
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
if (!isConfigurationCallbackInterface(ifc) && ifc.getMethods().length > 0) {
|
||||
hasReasonableProxyInterface = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasReasonableProxyInterface) {
|
||||
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
|
||||
for (Class<?> ifc : targetInterfaces) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given interface is just a container callback and
|
||||
* therefore not to be considered as a reasonable proxy interface.
|
||||
* <p>If no reasonable proxy interface is found for a given bean, it will get
|
||||
* proxied with its full target class, assuming that as the user's intention.
|
||||
* @param ifc the interface to check
|
||||
* @return whether the given interface is just a container callback
|
||||
*/
|
||||
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
|
||||
return (ifc.equals(InitializingBean.class) || ifc.equals(DisposableBean.class) ||
|
||||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
|
||||
return (isProxyTargetClass() ||
|
||||
(this.beanFactory instanceof ConfigurableListableBeanFactory &&
|
||||
AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,7 +60,7 @@ public class BeanNameAutoProxyCreator extends AbstractAutoProxyCreator {
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.BeanFactory#FACTORY_BEAN_PREFIX
|
||||
*/
|
||||
public void setBeanNames(String... beanNames) {
|
||||
public void setBeanNames(String[] beanNames) {
|
||||
Assert.notEmpty(beanNames, "'beanNames' must not be empty");
|
||||
this.beanNames = new ArrayList<String>(beanNames.length);
|
||||
for (String mappedName : beanNames) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -25,7 +25,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
* TargetSourceCreator that enforces a LazyInitTargetSource for each bean
|
||||
* that is defined as "lazy-init". This will lead to a proxy created for
|
||||
* each of those beans, allowing to fetch a reference to such a bean
|
||||
* without actually initializing the target bean instance.
|
||||
* without actually initialized the target bean instance.
|
||||
*
|
||||
* <p>To be registered as custom TargetSourceCreator for an auto-proxy creator,
|
||||
* in combination with custom interceptors for specific beans or for the
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
@@ -80,7 +81,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -62,11 +62,11 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
|
||||
/**
|
||||
* Create a new {@code AsyncExecutionInterceptor}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to
|
||||
* @param executor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to.
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
public AsyncExecutionInterceptor(Executor executor) {
|
||||
super(executor);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,8 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
* Subclasses may override to provide support for extracting qualifier information,
|
||||
* e.g. via an annotation on the given method.
|
||||
* @return always {@code null}
|
||||
* @since 3.1.2
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
* @since 3.1.2
|
||||
*/
|
||||
@Override
|
||||
protected String getExecutorQualifier(Method method) {
|
||||
|
||||
+2
-2
@@ -258,7 +258,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
return returnValue;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (stopWatch.isRunning()) {
|
||||
if(stopWatch.isRunning()) {
|
||||
stopWatch.stop();
|
||||
}
|
||||
exitThroughException = true;
|
||||
@@ -268,7 +268,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
}
|
||||
finally {
|
||||
if (!exitThroughException) {
|
||||
if (stopWatch.isRunning()) {
|
||||
if(stopWatch.isRunning()) {
|
||||
stopWatch.stop();
|
||||
}
|
||||
writeToLog(logger,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -125,7 +125,10 @@ public class ScopedProxyFactoryBean extends ProxyConfig implements FactoryBean<O
|
||||
if (this.proxy != null) {
|
||||
return this.proxy.getClass();
|
||||
}
|
||||
return this.scopedTargetSource.getTargetClass();
|
||||
if (this.scopedTargetSource != null) {
|
||||
return this.scopedTargetSource.getTargetClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -47,7 +47,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
|
||||
* @see #setMappedNames
|
||||
*/
|
||||
public void setMappedName(String mappedName) {
|
||||
setMappedNames(mappedName);
|
||||
setMappedNames(new String[] {mappedName});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut impleme
|
||||
* Matching will be the union of all these; if any match,
|
||||
* the pointcut matches.
|
||||
*/
|
||||
public void setMappedNames(String... mappedNames) {
|
||||
public void setMappedNames(String[] mappedNames) {
|
||||
this.mappedNames = new LinkedList<String>();
|
||||
if (mappedNames != null) {
|
||||
this.mappedNames.addAll(Arrays.asList(mappedNames));
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -68,7 +68,7 @@ public class NameMatchMethodPointcutAdvisor extends AbstractGenericPointcutAdvis
|
||||
* the pointcut matches.
|
||||
* @see NameMatchMethodPointcut#setMappedNames
|
||||
*/
|
||||
public void setMappedNames(String... mappedNames) {
|
||||
public void setMappedNames(String[] mappedNames) {
|
||||
this.pointcut.setMappedNames(mappedNames);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -98,7 +98,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
|
||||
* @see #setPatterns
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
setPatterns(pattern);
|
||||
setPatterns(new String[] {pattern});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +108,7 @@ public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor
|
||||
* patterns matches, the pointcut matches.
|
||||
* @see AbstractRegexpMethodPointcut#setPatterns
|
||||
*/
|
||||
public void setPatterns(String... patterns) {
|
||||
public void setPatterns(String[] patterns) {
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,8 @@ import org.springframework.util.ObjectUtils;
|
||||
* @see ThreadLocalTargetSource
|
||||
* @see CommonsPoolTargetSource
|
||||
*/
|
||||
public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSource, BeanFactoryAware, Serializable {
|
||||
public abstract class AbstractBeanFactoryBasedTargetSource
|
||||
implements TargetSource, BeanFactoryAware, Serializable {
|
||||
|
||||
/** use serialVersionUID from Spring 1.2.7 for interoperability */
|
||||
private static final long serialVersionUID = -4721607536018568393L;
|
||||
@@ -106,7 +108,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (this.targetBeanName == null) {
|
||||
throw new IllegalStateException("Property 'targetBeanName' is required");
|
||||
throw new IllegalStateException("Property'targetBeanName' is required");
|
||||
}
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
@@ -183,7 +185,8 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(getClass().getSimpleName());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(ClassUtils.getShortName(getClass()));
|
||||
sb.append(" for target bean '").append(this.targetBeanName).append("'");
|
||||
if (this.targetClass != null) {
|
||||
sb.append(" of type [").append(this.targetClass.getName()).append("]");
|
||||
|
||||
+10
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,15 @@
|
||||
*/
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -37,9 +46,7 @@ import org.aspectj.lang.annotation.DeclareParents;
|
||||
import org.aspectj.lang.annotation.DeclarePrecedence;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
@@ -59,9 +66,6 @@ import test.aop.Lockable;
|
||||
import test.aop.PerTargetAspect;
|
||||
import test.aop.TwoAdviceAspect;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Abstract tests for AspectJAdvisorFactory.
|
||||
* See subclasses for tests of concrete factories.
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.aop.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -23,8 +27,6 @@ import org.junit.Test;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.SerializationTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Dmitriy Kopylenko
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n
|
||||
|
||||
log4j.rootCategory=WARN, console
|
||||
log4j.logger.org.springframework.beans=WARN
|
||||
log4j.logger.org.springframework.binding=DEBUG
|
||||
|
||||
#log4j.logger.org.springframework.aop=TRACE
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.binding">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="warn" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
+27
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,18 +27,26 @@ import org.aspectj.lang.annotation.control.CodeGenerationHint;
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public abstract aspect AbstractDependencyInjectionAspect {
|
||||
|
||||
private pointcut preConstructionCondition() :
|
||||
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
|
||||
|
||||
private pointcut postConstructionCondition() :
|
||||
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
|
||||
/**
|
||||
* Select construction join points for objects to inject dependencies
|
||||
*/
|
||||
public abstract pointcut beanConstruction(Object bean);
|
||||
|
||||
/**
|
||||
* Select least specific super type that is marked for DI
|
||||
* (so that injection occurs only once with pre-construction injection).
|
||||
* Select deserialization join points for objects to inject dependencies
|
||||
*/
|
||||
public abstract pointcut leastSpecificSuperTypeConstruction();
|
||||
public abstract pointcut beanDeserialization(Object bean);
|
||||
|
||||
/**
|
||||
* Select join points in a configurable bean
|
||||
*/
|
||||
public abstract pointcut inConfigurableBean();
|
||||
|
||||
/**
|
||||
* Select join points in beans to be configured prior to construction?
|
||||
* By default, use post-construction injection matching the default in the Configurable annotation.
|
||||
*/
|
||||
public pointcut preConstructionConfiguration() : if(false);
|
||||
|
||||
/**
|
||||
* Select the most-specific initialization join point
|
||||
@@ -46,29 +54,24 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||
*/
|
||||
@CodeGenerationHint(ifNameSuffix="6f1")
|
||||
public pointcut mostSpecificSubTypeConstruction() :
|
||||
if (thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
|
||||
if(thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
|
||||
|
||||
/**
|
||||
* Select join points in beans to be configured prior to construction?
|
||||
* By default, use post-construction injection matching the default in the Configurable annotation.
|
||||
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
|
||||
*/
|
||||
public pointcut preConstructionConfiguration() : if (false);
|
||||
public abstract pointcut leastSpecificSuperTypeConstruction();
|
||||
|
||||
/**
|
||||
* Select construction join points for objects to inject dependencies.
|
||||
* Configure the bean
|
||||
*/
|
||||
public abstract pointcut beanConstruction(Object bean);
|
||||
public abstract void configureBean(Object bean);
|
||||
|
||||
/**
|
||||
* Select deserialization join points for objects to inject dependencies.
|
||||
*/
|
||||
public abstract pointcut beanDeserialization(Object bean);
|
||||
|
||||
/**
|
||||
* Select join points in a configurable bean.
|
||||
*/
|
||||
public abstract pointcut inConfigurableBean();
|
||||
private pointcut preConstructionCondition() :
|
||||
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
|
||||
|
||||
private pointcut postConstructionCondition() :
|
||||
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
|
||||
|
||||
/**
|
||||
* Pre-construction configuration.
|
||||
@@ -97,10 +100,4 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||
configureBean(bean);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure the given bean.
|
||||
*/
|
||||
public abstract void configureBean(Object bean);
|
||||
|
||||
}
|
||||
|
||||
+54
-50
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,48 +20,49 @@ import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* An aspect that injects dependency into any object whose type implements the
|
||||
* {@link ConfigurableObject} interface.
|
||||
*
|
||||
* <p>This aspect supports injecting into domain objects when they are created
|
||||
* for the first time as well as upon deserialization. Subaspects need to simply
|
||||
* provide definition for the configureBean() method. This method may be
|
||||
* implemented without relying on Spring container if so desired.
|
||||
*
|
||||
* <p>There are two cases that needs to be handled:
|
||||
* An aspect that injects dependency into any object whose type implements the {@link ConfigurableObject} interface.
|
||||
* <p>
|
||||
* This aspect supports injecting into domain objects when they are created for the first time as well as
|
||||
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
|
||||
* method may be implemented without relying on Spring container if so desired.
|
||||
* </p>
|
||||
* <p>
|
||||
* There are two cases that needs to be handled:
|
||||
* <ol>
|
||||
* <li>Normal object creation via the '{@code new}' operator: this is
|
||||
* taken care of by advising {@code initialization()} join points.</li>
|
||||
* <li>Object creation through deserialization: since no constructor is
|
||||
* invoked during deserialization, the aspect needs to advise a method that a
|
||||
* deserialization mechanism is going to invoke. Ideally, we should not
|
||||
* require user classes to implement any specific method. This implies that
|
||||
* we need to <i>introduce</i> the chosen method. We should also handle the cases
|
||||
* where the chosen method is already implemented in classes (in which case,
|
||||
* the user's implementation for that method should take precedence over the
|
||||
* introduced implementation). There are a few choices for the chosen method:
|
||||
* <ul>
|
||||
* <li>readObject(ObjectOutputStream): Java requires that the method must be
|
||||
* {@code private}</p>. Since aspects cannot introduce a private member,
|
||||
* while preserving its name, this option is ruled out.</li>
|
||||
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
||||
* Problem solved! There is one (minor) limitation of this approach in
|
||||
* that if a user class already has this method, that method must be
|
||||
* {@code public}. However, this shouldn't be a big burden, since
|
||||
* use cases that need classes to implement readResolve() (custom enums,
|
||||
* for example) are unlikely to be marked as @Configurable, and
|
||||
* in any case asking to make that method {@code public} should not
|
||||
* pose any undue burden.</li>
|
||||
* </ul>
|
||||
* The minor collaboration needed by user classes (i.e., that the implementation of
|
||||
* {@code readResolve()}, if any, must be {@code public}) can be lifted as well if we
|
||||
* were to use an experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
|
||||
* <li>Normal object creation via the '{@code new}' operator: this is
|
||||
* taken care of by advising {@code initialization()} join points.</li>
|
||||
* <li>Object creation through deserialization: since no constructor is
|
||||
* invoked during deserialization, the aspect needs to advise a method that a
|
||||
* deserialization mechanism is going to invoke. Ideally, we should not
|
||||
* require user classes to implement any specific method. This implies that
|
||||
* we need to <i>introduce</i> the chosen method. We should also handle the cases
|
||||
* where the chosen method is already implemented in classes (in which case,
|
||||
* the user's implementation for that method should take precedence over the
|
||||
* introduced implementation). There are a few choices for the chosen method:
|
||||
* <ul>
|
||||
* <li>readObject(ObjectOutputStream): Java requires that the method must be
|
||||
* {@code private}</p>. Since aspects cannot introduce a private member,
|
||||
* while preserving its name, this option is ruled out.</li>
|
||||
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
||||
* Problem solved! There is one (minor) limitation of this approach in
|
||||
* that if a user class already has this method, that method must be
|
||||
* {@code public}. However, this shouldn't be a big burden, since
|
||||
* use cases that need classes to implement readResolve() (custom enums,
|
||||
* for example) are unlikely to be marked as @Configurable, and
|
||||
* in any case asking to make that method {@code public} should not
|
||||
* pose any undue burden.</li>
|
||||
* </ul>
|
||||
* The minor collaboration needed by user classes (i.e., that the
|
||||
* implementation of {@code readResolve()}, if any, must be
|
||||
* {@code public}) can be lifted as well if we were to use an
|
||||
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>While having type implement the {@link ConfigurableObject} interface is certainly
|
||||
* a valid choice, an alternative is to use a 'declare parents' statement another aspect
|
||||
* (a subaspect of this aspect would be a logical choice) that declares the classes that
|
||||
* need to be configured by supplying the {@link ConfigurableObject} interface.
|
||||
|
||||
* <p>
|
||||
* While having type implement the {@link ConfigurableObject} interface is certainly a valid choice, an alternative
|
||||
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
|
||||
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.5.2
|
||||
@@ -71,33 +72,35 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||
* Select initialization join point as object construction
|
||||
*/
|
||||
public pointcut beanConstruction(Object bean) :
|
||||
initialization(ConfigurableObject+.new(..)) && this(bean);
|
||||
initialization(ConfigurableObject+.new(..)) && this(bean);
|
||||
|
||||
/**
|
||||
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
|
||||
*/
|
||||
public pointcut beanDeserialization(Object bean) :
|
||||
execution(Object ConfigurableDeserializationSupport+.readResolve()) && this(bean);
|
||||
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
|
||||
this(bean);
|
||||
|
||||
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
|
||||
|
||||
|
||||
|
||||
// Implementation to support re-injecting dependencies once an object is deserialized
|
||||
|
||||
/**
|
||||
* Declare any class implementing Serializable and ConfigurableObject as also implementing
|
||||
* ConfigurableDeserializationSupport. This allows us to introduce the {@code readResolve()}
|
||||
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
|
||||
* method and select it with the beanDeserialization() pointcut.
|
||||
*
|
||||
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
|
||||
* even the minor requirement on user classes:
|
||||
* <pre class="code">
|
||||
* declare parents: ConfigurableObject+ Serializable+
|
||||
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
||||
* implements ConfigurableDeserializationSupport;
|
||||
*
|
||||
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
|
||||
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
||||
* implements ConfigurableDeserializationSupport;
|
||||
* </pre>
|
||||
*/
|
||||
declare parents: ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
|
||||
declare parents:
|
||||
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
|
||||
|
||||
/**
|
||||
* A marker interface to which the {@code readResolve()} is introduced.
|
||||
@@ -108,6 +111,7 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||
/**
|
||||
* Introduce the {@code readResolve()} method so that we can advise its
|
||||
* execution to configure the object.
|
||||
*
|
||||
* <p>Note if a method with the same signature already exists in a
|
||||
* {@code Serializable} class of ConfigurableObject type,
|
||||
* that implementation will take precedence (a good thing, since we are
|
||||
|
||||
+28
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.springframework.beans.factory.aspectj;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.aspectj.lang.annotation.control.CodeGenerationHint;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -44,47 +44,48 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
* @see org.springframework.beans.factory.annotation.Configurable
|
||||
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
|
||||
*/
|
||||
public aspect AnnotationBeanConfigurerAspect extends AbstractInterfaceDrivenDependencyInjectionAspect
|
||||
public aspect AnnotationBeanConfigurerAspect
|
||||
extends AbstractInterfaceDrivenDependencyInjectionAspect
|
||||
implements BeanFactoryAware, InitializingBean, DisposableBean {
|
||||
|
||||
private BeanConfigurerSupport beanConfigurerSupport = new BeanConfigurerSupport();
|
||||
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
|
||||
this.beanConfigurerSupport.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.beanConfigurerSupport.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void configureBean(Object bean) {
|
||||
this.beanConfigurerSupport.configureBean(bean);
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
this.beanConfigurerSupport.destroy();
|
||||
}
|
||||
|
||||
|
||||
public pointcut inConfigurableBean() : @this(Configurable);
|
||||
|
||||
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
|
||||
|
||||
declare parents: @Configurable * implements ConfigurableObject;
|
||||
|
||||
public void configureBean(Object bean) {
|
||||
beanConfigurerSupport.configureBean(bean);
|
||||
}
|
||||
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
beanConfigurerSupport.setBeanFactory(beanFactory);
|
||||
beanConfigurerSupport.setBeanWiringInfoResolver(new AnnotationBeanWiringInfoResolver());
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
beanConfigurerSupport.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
beanConfigurerSupport.destroy();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
|
||||
*/
|
||||
@CodeGenerationHint(ifNameSuffix="bb0")
|
||||
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if (c.preConstruction());
|
||||
|
||||
|
||||
declare parents: @Configurable * implements ConfigurableObject;
|
||||
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
|
||||
|
||||
/*
|
||||
* This declaration shouldn't be needed,
|
||||
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
|
||||
*/
|
||||
declare parents: @Configurable Serializable+ implements ConfigurableDeserializationSupport;
|
||||
declare parents: @Configurable Serializable+
|
||||
implements ConfigurableDeserializationSupport;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,7 +35,7 @@ import org.springframework.context.annotation.Role;
|
||||
@Configuration
|
||||
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
|
||||
@Bean(name=AnnotationConfigUtils.CACHE_ASPECT_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public AnnotationCacheAspect cacheAspect() {
|
||||
AnnotationCacheAspect cacheAspect = AnnotationCacheAspect.aspectOf();
|
||||
@@ -47,5 +47,4 @@ public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
|
||||
}
|
||||
return cacheAspect;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+72
-126
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,140 +18,86 @@ package org.springframework.mock.staticmock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
||||
*
|
||||
* <p>Sub-aspects must define:
|
||||
* <ul>
|
||||
* <li>The {@link #mockStaticsTestMethod()} pointcut to indicate call stacks
|
||||
* when mocking should be triggered
|
||||
* <li>The {@link #methodToMock()} pointcut to pick out method invocations to mock
|
||||
* </ul>
|
||||
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
||||
* indicate call stacks when mocking should be triggered, and the
|
||||
* methodToMock() pointcut to pick out a method invocations to mock.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) {
|
||||
|
||||
private final Expectations expectations = new Expectations();
|
||||
protected abstract pointcut mockStaticsTestMethod();
|
||||
|
||||
protected abstract pointcut methodToMock();
|
||||
|
||||
private boolean recording = true;
|
||||
|
||||
static enum CallResponse { nothing, return_, throw_ };
|
||||
|
||||
protected void expectReturnInternal(Object retVal) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||
}
|
||||
expectations.expectReturn(retVal);
|
||||
}
|
||||
|
||||
protected void expectThrowInternal(Throwable throwable) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set throwable value");
|
||||
}
|
||||
expectations.expectThrow(throwable);
|
||||
}
|
||||
|
||||
protected void playbackInternal() {
|
||||
recording = false;
|
||||
}
|
||||
|
||||
protected void verifyInternal() {
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
protected void resetInternal() {
|
||||
expectations.reset();
|
||||
recording = true;
|
||||
}
|
||||
|
||||
|
||||
private static enum CallResponse {
|
||||
undefined, return_, throw_
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a list of expected calls to methods.
|
||||
*/
|
||||
// Represents a list of expected calls to static entity methods
|
||||
// Public to allow inserted code to access: is this normal??
|
||||
public class Expectations {
|
||||
|
||||
/**
|
||||
* Represents an expected call to a method.
|
||||
*/
|
||||
// Represents an expected call to a static entity method
|
||||
private class Call {
|
||||
|
||||
private final String signature;
|
||||
private final Object[] args;
|
||||
|
||||
private CallResponse responseType = CallResponse.undefined;
|
||||
private Object responseObject; // return value or throwable
|
||||
private CallResponse responseType = CallResponse.nothing;
|
||||
|
||||
|
||||
Call(String signature, Object[] args) {
|
||||
this.signature = signature;
|
||||
public Call(String name, Object[] args) {
|
||||
this.signature = name;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
boolean responseTypeAlreadySet() {
|
||||
return responseType != CallResponse.undefined;
|
||||
public boolean hasResponseSpecified() {
|
||||
return responseType != CallResponse.nothing;
|
||||
}
|
||||
|
||||
void setReturnValue(Object retVal) {
|
||||
public void setReturnVal(Object retVal) {
|
||||
this.responseObject = retVal;
|
||||
responseType = CallResponse.return_;
|
||||
}
|
||||
|
||||
void setThrowable(Throwable throwable) {
|
||||
public void setThrow(Throwable throwable) {
|
||||
this.responseObject = throwable;
|
||||
responseType = CallResponse.throw_;
|
||||
}
|
||||
|
||||
Object returnValue(String lastSig, Object[] args) {
|
||||
public Object returnValue(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
Object throwException(String lastSig, Object[] args) {
|
||||
public Object throwException(String lastSig, Object[] args) {
|
||||
checkSignature(lastSig, args);
|
||||
throw (RuntimeException) responseObject;
|
||||
throw (RuntimeException)responseObject;
|
||||
}
|
||||
|
||||
private void checkSignature(String lastSig, Object[] args) {
|
||||
if (!signature.equals(lastSig)) {
|
||||
throw new IllegalArgumentException("Signatures do not match");
|
||||
throw new IllegalArgumentException("Signature doesn't match");
|
||||
}
|
||||
if (!Arrays.equals(this.args, args)) {
|
||||
throw new IllegalArgumentException("Arguments do not match");
|
||||
throw new IllegalArgumentException("Arguments don't match");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Call with signature [%s] and arguments %s", this.signature,
|
||||
ObjectUtils.nullSafeToString(args));
|
||||
}
|
||||
}
|
||||
|
||||
private List<Call> calls = new LinkedList<Call>();
|
||||
|
||||
/**
|
||||
* The list of recorded calls.
|
||||
*/
|
||||
private final LinkedList<Call> calls = new LinkedList<Call>();
|
||||
|
||||
/**
|
||||
* The number of calls already verified.
|
||||
*/
|
||||
// Calls already verified
|
||||
private int verified;
|
||||
|
||||
|
||||
public void verify() {
|
||||
if (verified != calls.size()) {
|
||||
throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified);
|
||||
throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,32 +105,31 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
* Validate the call and provide the expected return value.
|
||||
*/
|
||||
public Object respond(String lastSig, Object[] args) {
|
||||
Call c = nextCall();
|
||||
|
||||
switch (c.responseType) {
|
||||
case return_: {
|
||||
return c.returnValue(lastSig, args);
|
||||
}
|
||||
case throw_: {
|
||||
return c.throwException(lastSig, args);
|
||||
}
|
||||
default: {
|
||||
throw new IllegalStateException("Behavior of " + c + " not specified");
|
||||
}
|
||||
Call call = nextCall();
|
||||
CallResponse responseType = call.responseType;
|
||||
if (responseType == CallResponse.return_) {
|
||||
return call.returnValue(lastSig, args);
|
||||
}
|
||||
else if (responseType == CallResponse.throw_) {
|
||||
return call.throwException(lastSig, args);
|
||||
}
|
||||
else if (responseType == CallResponse.nothing) {
|
||||
// do nothing
|
||||
}
|
||||
throw new IllegalStateException("Behavior of " + call + " not specified");
|
||||
}
|
||||
|
||||
private Call nextCall() {
|
||||
verified++;
|
||||
if (verified > calls.size()) {
|
||||
throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified);
|
||||
throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified);
|
||||
}
|
||||
// The 'verified' count is 1-based; whereas, 'calls' is 0-based.
|
||||
return calls.get(verified - 1);
|
||||
return calls.get(verified);
|
||||
}
|
||||
|
||||
public void expectCall(String lastSig, Object[] lastArgs) {
|
||||
calls.add(new Call(lastSig, lastArgs));
|
||||
public void expectCall(String lastSig, Object lastArgs[]) {
|
||||
Call call = new Call(lastSig, lastArgs);
|
||||
calls.add(call);
|
||||
}
|
||||
|
||||
public boolean hasCalls() {
|
||||
@@ -192,48 +137,31 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
}
|
||||
|
||||
public void expectReturn(Object retVal) {
|
||||
Call c = calls.getLast();
|
||||
if (c.responseTypeAlreadySet()) {
|
||||
throw new IllegalStateException("No method invoked before setting return value");
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting return value");
|
||||
}
|
||||
c.setReturnValue(retVal);
|
||||
call.setReturnVal(retVal);
|
||||
}
|
||||
|
||||
public void expectThrow(Throwable throwable) {
|
||||
Call c = calls.getLast();
|
||||
if (c.responseTypeAlreadySet()) {
|
||||
throw new IllegalStateException("No method invoked before setting throwable");
|
||||
Call call = calls.get(calls.size() - 1);
|
||||
if (call.hasResponseSpecified()) {
|
||||
throw new IllegalStateException("No static method invoked before setting throwable");
|
||||
}
|
||||
c.setThrowable(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the internal state of this {@code Expectations} instance.
|
||||
*/
|
||||
public void reset() {
|
||||
this.calls.clear();
|
||||
this.verified = 0;
|
||||
call.setThrow(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut that identifies call stacks when mocking should be triggered.
|
||||
*/
|
||||
protected abstract pointcut mockStaticsTestMethod();
|
||||
|
||||
/**
|
||||
* Pointcut that identifies which method invocations to mock.
|
||||
*/
|
||||
protected abstract pointcut methodToMock();
|
||||
private Expectations expectations = new Expectations();
|
||||
|
||||
after() returning : mockStaticsTestMethod() {
|
||||
if (recording && (expectations.hasCalls())) {
|
||||
throw new IllegalStateException(
|
||||
"Calls have been recorded, but playback state was never reached. Set expectations and then call "
|
||||
+ this.getClass().getSimpleName() + ".playback();");
|
||||
"Calls recorded, yet playback state never reached: Create expectations then call "
|
||||
+ this.getClass().getSimpleName() + ".playback()");
|
||||
}
|
||||
verifyInternal();
|
||||
expectations.verify();
|
||||
}
|
||||
|
||||
Object around() : methodToMock() && cflowbelow(mockStaticsTestMethod()) {
|
||||
@@ -247,4 +175,22 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
}
|
||||
}
|
||||
|
||||
public void expectReturnInternal(Object retVal) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||
}
|
||||
expectations.expectReturn(retVal);
|
||||
}
|
||||
|
||||
public void expectThrowInternal(Throwable throwable) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set throwable value");
|
||||
}
|
||||
expectations.expectThrow(throwable);
|
||||
}
|
||||
|
||||
public void playbackInternal() {
|
||||
recording = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-71
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,98 +17,50 @@
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
/**
|
||||
* Annotation-based aspect to use in test builds to enable mocking of static methods
|
||||
* on JPA-annotated {@code @Entity} classes, as used by Spring Roo for so-called
|
||||
* <em>finder methods</em>.
|
||||
* Annotation-based aspect to use in test build to enable mocking static methods
|
||||
* on JPA-annotated {@code @Entity} classes, as used by Roo for finders.
|
||||
*
|
||||
* <p>Mocking will occur within the call stack of any {@code public} method in a
|
||||
* class (typically a test class) that is annotated with {@code @MockStaticEntityMethods}.
|
||||
* Thus mocking is not limited to {@code @Test} methods. Furthermore, new mock
|
||||
* state will be created for the invocation of each such public method, even when
|
||||
* the method is invoked from another such public method.
|
||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||
*
|
||||
* <p>This aspect also provides static methods to simplify the programming model for
|
||||
* setting expectations and entering playback mode.
|
||||
* <p>Also provides static methods to simplify the programming model for
|
||||
* entering playback mode and setting expected return values.
|
||||
*
|
||||
* <h3>Usage</h3>
|
||||
* <p>Usage:
|
||||
* <ol>
|
||||
* <li>Annotate a test class with {@code @MockStaticEntityMethods}.
|
||||
* <li>In each test method, the {@code AnnotationDrivenStaticEntityMockingControl}
|
||||
* will begin in <em>recording</em> mode.
|
||||
* <li>Invoke static methods on JPA-annotated {@code @Entity} classes, with each
|
||||
* recording-mode invocation being followed by an invocation of either
|
||||
* {@link #expectReturn(Object)} or {@link #expectThrow(Throwable)} on the
|
||||
* {@code AnnotationDrivenStaticEntityMockingControl}.
|
||||
* <li>Invoke the {@link #playback()} method.
|
||||
* <li>Call the code you wish to test that uses the static methods on the
|
||||
* JPA-annotated {@code @Entity} classes.
|
||||
* <li>Verification will occur automatically after the test method has executed
|
||||
* and returned. However, mock verification will not occur if the test method
|
||||
* throws an exception.
|
||||
* <li>Annotate a test class with @MockStaticEntityMethods.
|
||||
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
||||
* Invoke static methods on Entity classes, with each recording-mode invocation
|
||||
* being followed by an invocation to the static expectReturn() or expectThrow()
|
||||
* method on AnnotationDrivenStaticEntityMockingControl.
|
||||
* <li>Invoke the static AnnotationDrivenStaticEntityMockingControl() method.
|
||||
* <li>Call the code you wish to test that uses the static methods. Verification will
|
||||
* occur automatically.
|
||||
* </ol>
|
||||
*
|
||||
* <h3>Programmatic Control of the Mock</h3>
|
||||
* <p>For scenarios where it would be convenient to programmatically <em>verify</em>
|
||||
* the recorded expectations or <em>reset</em> the state of the mock, consider
|
||||
* using combinations of {@link #verify()} and {@link #reset()}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
* @see MockStaticEntityMethods
|
||||
*/
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
/**
|
||||
* Expect the supplied {@link Object} to be returned by the previous static
|
||||
* method invocation.
|
||||
* @see #playback()
|
||||
*/
|
||||
public static void expectReturn(Object retVal) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expect the supplied {@link Throwable} to be thrown by the previous static
|
||||
* method invocation.
|
||||
* @see #playback()
|
||||
*/
|
||||
public static void expectThrow(Throwable throwable) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop recording mock expectations and enter <em>playback</em> mode.
|
||||
* @see #expectReturn(Object)
|
||||
* @see #expectThrow(Throwable)
|
||||
* Stop recording mock calls and enter playback state
|
||||
*/
|
||||
public static void playback() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that all expectations have been fulfilled.
|
||||
* @since 4.0.2
|
||||
* @see #reset()
|
||||
*/
|
||||
public static void verify() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().verifyInternal();
|
||||
public static void expectReturn(Object retVal) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the state of the mock and enter <em>recording</em> mode.
|
||||
* @since 4.0.2
|
||||
* @see #verify()
|
||||
*/
|
||||
public static void reset() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().resetInternal();
|
||||
public static void expectThrow(Throwable throwable) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable);
|
||||
}
|
||||
|
||||
// Apparently, the following pointcut was originally defined to only match
|
||||
// methods directly annotated with @Test (in order to allow methods in
|
||||
// @MockStaticEntityMethods classes to invoke each other without creating a
|
||||
// new mocking environment); however, this is no longer the case. The current
|
||||
// pointcut applies to all public methods in @MockStaticEntityMethods classes.
|
||||
// Only matches directly annotated @Test methods, to allow methods in
|
||||
// @MockStatics classes to invoke each other without resetting the mocking environment
|
||||
protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..));
|
||||
|
||||
protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..));
|
||||
|
||||
+4
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,11 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation to indicate a test class for whose {@code @Test} methods
|
||||
* static methods on JPA-annotated {@code @Entity} classes should be mocked.
|
||||
*
|
||||
* <p>See {@link AnnotationDrivenStaticEntityMockingControl} for details.
|
||||
* Annotation to indicate a test class for whose @Test methods
|
||||
* static methods on Entity classes should be mocked. See
|
||||
* {@code AbstractMethodMockingControl}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
@Configuration
|
||||
public class AspectJAsyncConfiguration extends AbstractAsyncConfiguration {
|
||||
|
||||
@Bean(name = AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
|
||||
@Bean(name=AnnotationConfigUtils.ASYNC_EXECUTION_ASPECT_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public AnnotationAsyncExecutionAspect asyncAdvisor() {
|
||||
AnnotationAsyncExecutionAspect asyncAspect = AnnotationAsyncExecutionAspect.aspectOf();
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,7 +37,7 @@ import org.springframework.transaction.config.TransactionManagementConfigUtils;
|
||||
@Configuration
|
||||
public class AspectJTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
|
||||
|
||||
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
|
||||
@Bean(name=TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME)
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public AnnotationTransactionAspect transactionAspect() {
|
||||
AnnotationTransactionAspect txAspect = AnnotationTransactionAspect.aspectOf();
|
||||
@@ -46,5 +46,4 @@ public class AspectJTransactionManagementConfiguration extends AbstractTransacti
|
||||
}
|
||||
return txAspect;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,6 @@ package org.springframework.cache.config;
|
||||
|
||||
import org.springframework.cache.interceptor.DefaultKeyGenerator;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SomeKeyGenerator extends DefaultKeyGenerator {
|
||||
|
||||
}
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.mock.staticmock;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectReturn;
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectThrow;
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.playback;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Test for static entity mocking framework.
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*
|
||||
*/
|
||||
@MockStaticEntityMethods
|
||||
@RunWith(JUnit4.class)
|
||||
public class AnnotationDrivenStaticEntityMockingControlTest {
|
||||
|
||||
@Test
|
||||
public void testNoArgIntReturn() {
|
||||
int expectedCount = 13;
|
||||
Person.countPeople();
|
||||
expectReturn(expectedCount);
|
||||
playback();
|
||||
assertEquals(expectedCount, Person.countPeople());
|
||||
}
|
||||
|
||||
@Test(expected=PersistenceException.class)
|
||||
public void testNoArgThrows() {
|
||||
Person.countPeople();
|
||||
expectThrow(new PersistenceException());
|
||||
playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodMatches() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLongSeriesOfCalls() {
|
||||
long id1 = 13;
|
||||
long id2 = 24;
|
||||
Person found1 = new Person();
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person found2 = new Person();
|
||||
Person.findPerson(id2);
|
||||
expectReturn(found2);
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person.countPeople();
|
||||
expectReturn(0);
|
||||
playback();
|
||||
|
||||
assertEquals(found1, Person.findPerson(id1));
|
||||
assertEquals(found2, Person.findPerson(id2));
|
||||
assertEquals(found1, Person.findPerson(id1));
|
||||
assertEquals(0, Person.countPeople());
|
||||
}
|
||||
|
||||
// Note delegation is used when tests are invalid and should fail, as otherwise
|
||||
// the failure will occur on the verify() method in the aspect after
|
||||
// this method returns, failing the test case
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
try {
|
||||
new Delegate().testArgMethodNoMatchExpectReturn();
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
new Delegate().testArgMethodNoMatchExpectThrow();
|
||||
}
|
||||
|
||||
private void called(Person found, long id) {
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReentrant() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
called(found, id);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testRejectUnexpectedCall() {
|
||||
new Delegate().rejectUnexpectedCall();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testFailTooFewCalls() {
|
||||
new Delegate().failTooFewCalls();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty() {
|
||||
// Test that verification check doesn't blow up if no replay() call happened
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverReplay() {
|
||||
new Delegate().doesntEverReplay();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testDoesntEverSetReturn() {
|
||||
new Delegate().doesntEverSetReturn();
|
||||
}
|
||||
}
|
||||
|
||||
-300
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.mock.staticmock;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*;
|
||||
|
||||
/**
|
||||
* Tests for Spring's static entity mocking framework (i.e., @{@link MockStaticEntityMethods}
|
||||
* and {@link AnnotationDrivenStaticEntityMockingControl}).
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@MockStaticEntityMethods
|
||||
public class AnnotationDrivenStaticEntityMockingControlTests {
|
||||
|
||||
@Test
|
||||
public void noArgumentMethodInvocationReturnsInt() {
|
||||
int expectedCount = 13;
|
||||
Person.countPeople();
|
||||
expectReturn(expectedCount);
|
||||
playback();
|
||||
assertEquals(expectedCount, Person.countPeople());
|
||||
}
|
||||
|
||||
@Test(expected = PersistenceException.class)
|
||||
public void noArgumentMethodInvocationThrowsException() {
|
||||
Person.countPeople();
|
||||
expectThrow(new PersistenceException());
|
||||
playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void methodArgumentsMatch() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void longSeriesOfCalls() {
|
||||
long id1 = 13;
|
||||
long id2 = 24;
|
||||
Person found1 = new Person();
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person found2 = new Person();
|
||||
Person.findPerson(id2);
|
||||
expectReturn(found2);
|
||||
Person.findPerson(id1);
|
||||
expectReturn(found1);
|
||||
Person.countPeople();
|
||||
expectReturn(0);
|
||||
playback();
|
||||
|
||||
assertEquals(found1, Person.findPerson(id1));
|
||||
assertEquals(found2, Person.findPerson(id2));
|
||||
assertEquals(found1, Person.findPerson(id1));
|
||||
assertEquals(0, Person.countPeople());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void methodArgumentsDoNotMatchAndReturnsObject() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void methodArgumentsDoNotMatchAndThrowsException() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectThrow(new PersistenceException());
|
||||
playback();
|
||||
assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reentrantCallToPrivateMethod() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
privateMethod(found, id);
|
||||
}
|
||||
|
||||
private void privateMethod(Person found, long id) {
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reentrantCallToPublicMethod() {
|
||||
final Long ID = 13L;
|
||||
Person.findPerson(ID);
|
||||
expectReturn(new Person());
|
||||
playback();
|
||||
try {
|
||||
publicMethod();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
String snippet = "Calls have been recorded, but playback state was never reached.";
|
||||
assertTrue("Exception message should contain [" + snippet + "]", e.getMessage().contains(snippet));
|
||||
}
|
||||
|
||||
// Now to keep the mock for "this" method happy:
|
||||
Person.findPerson(ID);
|
||||
}
|
||||
|
||||
public void publicMethod() {
|
||||
// At this point, since publicMethod() is a public method in a class
|
||||
// annotated with @MockStaticEntityMethods, the current mock state is
|
||||
// fresh. In other words, we are again in recording mode. As such, any
|
||||
// call to a mocked method will return null. See the implementation of
|
||||
// the <methodToMock() && cflowbelow(mockStaticsTestMethod())> around
|
||||
// advice in AbstractMethodMockingControl for details.
|
||||
assertNull(Person.findPerson(99L));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void unexpectedCall() {
|
||||
playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void tooFewCalls() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
expectReturn(found);
|
||||
Person.countPeople();
|
||||
expectReturn(25);
|
||||
playback();
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noExpectationsAndNoPlayback() {
|
||||
// Ensure that mock verification doesn't blow up if playback() was not invoked and
|
||||
// no expectations were set.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noExpectationsButWithPlayback() {
|
||||
// Ensure that mock verification doesn't blow up if playback() was invoked but no
|
||||
// expectations were set.
|
||||
playback();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void doesNotEnterPlaybackMode() {
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void doesNotSetExpectedReturnValue() {
|
||||
Person.countPeople();
|
||||
playback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently, the method mocking aspect will not verify the state of the
|
||||
* expectations within the mock if a test method throws an exception.
|
||||
*
|
||||
* <p>The reason is that the {@code mockStaticsTestMethod()} advice in
|
||||
* {@link AbstractMethodMockingControl} is declared as
|
||||
* {@code after() returning} instead of simply {@code after()}.
|
||||
*
|
||||
* <p>If the aforementioned advice is changed to a generic "after" advice,
|
||||
* this test method will fail with an {@link IllegalStateException} (thrown
|
||||
* by the mock aspect) instead of the {@link UnsupportedOperationException}
|
||||
* thrown by the test method itself.
|
||||
*/
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void mockVerificationDoesNotOccurIfTestFailsWithAnExpectedException() {
|
||||
Person.countPeople();
|
||||
playback();
|
||||
// We intentionally do not execute any of the recorded method invocations in order
|
||||
// to demonstrate that mock verification does not occur if an
|
||||
// exception is thrown.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resetMockWithoutVerficationAndStartOverWithoutRedeclaringExpectations() {
|
||||
final Long ID = 13L;
|
||||
Person.findPerson(ID);
|
||||
expectReturn(new Person());
|
||||
|
||||
reset();
|
||||
|
||||
Person.findPerson(ID);
|
||||
// Omit expectation.
|
||||
playback();
|
||||
|
||||
try {
|
||||
Person.findPerson(ID);
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
String snippet = "Behavior of Call with signature";
|
||||
assertTrue("Exception message should contain [" + snippet + "]", e.getMessage().contains(snippet));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resetMockWithoutVerificationAndStartOver() {
|
||||
final Long ID = 13L;
|
||||
Person found = new Person();
|
||||
Person.findPerson(ID);
|
||||
expectReturn(found);
|
||||
|
||||
reset();
|
||||
|
||||
// Intentionally use a different ID:
|
||||
final long ID_2 = ID + 1;
|
||||
Person.findPerson(ID_2);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
|
||||
assertEquals(found, Person.findPerson(ID_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyResetAndStartOver() {
|
||||
final Long ID_1 = 13L;
|
||||
Person found1 = new Person();
|
||||
Person.findPerson(ID_1);
|
||||
expectReturn(found1);
|
||||
playback();
|
||||
|
||||
assertEquals(found1, Person.findPerson(ID_1));
|
||||
verify();
|
||||
reset();
|
||||
|
||||
// Intentionally use a different ID:
|
||||
final long ID_2 = ID_1 + 1;
|
||||
Person found2 = new Person();
|
||||
Person.findPerson(ID_2);
|
||||
expectReturn(found2);
|
||||
playback();
|
||||
|
||||
assertEquals(found2, Person.findPerson(ID_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyWithTooFewCalls() {
|
||||
final Long ID = 13L;
|
||||
Person found = new Person();
|
||||
Person.findPerson(ID);
|
||||
expectReturn(found);
|
||||
Person.findPerson(ID);
|
||||
expectReturn(found);
|
||||
playback();
|
||||
|
||||
assertEquals(found, Person.findPerson(ID));
|
||||
|
||||
try {
|
||||
verify();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
assertEquals("Expected 2 calls, but received 1", e.getMessage());
|
||||
// Since verify() failed, we need to manually reset so that the test method
|
||||
// does not fail.
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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.mock.staticmock;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl;
|
||||
import org.springframework.mock.staticmock.MockStaticEntityMethods;
|
||||
|
||||
//Used because verification failures occur after method returns,
|
||||
//so we can't test for them in the test case itself
|
||||
@MockStaticEntityMethods
|
||||
@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl
|
||||
public class Delegate {
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectReturn() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArgMethodNoMatchExpectThrow() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException());
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
assertEquals(found, Person.findPerson(id + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failTooFewCalls() {
|
||||
long id = 13;
|
||||
Person found = new Person();
|
||||
Person.findPerson(id);
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(found);
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.expectReturn(25);
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
assertEquals(found, Person.findPerson(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverReplay() {
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesntEverSetReturn() {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectUnexpectedCall() {
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
Person.countPeople();
|
||||
}
|
||||
|
||||
@Test(expected=RemoteException.class)
|
||||
public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException {
|
||||
Person.countPeople();
|
||||
AnnotationDrivenStaticEntityMockingControl.playback();
|
||||
// No calls to allow verification failure
|
||||
throw new RemoteException();
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n
|
||||
|
||||
log4j.rootCategory=WARN, console
|
||||
log4j.logger.org.springframework.beans=WARN
|
||||
log4j.logger.org.springframework.binding=DEBUG
|
||||
|
||||
#log4j.logger.org.springframework=TRACE
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.binding">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="warn" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
@@ -398,8 +398,7 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
|
||||
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
|
||||
return TypeDescriptor.nested(property(pd), tokens.keys.length);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (pd.getReadMethod() != null || pd.getWriteMethod() != null) {
|
||||
return new TypeDescriptor(property(pd));
|
||||
}
|
||||
|
||||
+10
-6
@@ -21,7 +21,7 @@ import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -94,15 +94,14 @@ public class CachedIntrospectionResults {
|
||||
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";
|
||||
|
||||
|
||||
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses =
|
||||
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
|
||||
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
|
||||
|
||||
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses;
|
||||
|
||||
/** Stores the BeanInfoFactory instances */
|
||||
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
|
||||
|
||||
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
|
||||
|
||||
/**
|
||||
* Set of ClassLoaders that this CachedIntrospectionResults class will always
|
||||
* accept classes from, even if the classes do not qualify as cache-safe.
|
||||
@@ -117,6 +116,11 @@ public class CachedIntrospectionResults {
|
||||
static final Map<Class<?>, Object> classCache = new WeakHashMap<Class<?>, Object>();
|
||||
|
||||
|
||||
static {
|
||||
shouldIntrospectorIgnoreBeaninfoClasses = SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accept the given ClassLoader as cache-safe, even if its classes would
|
||||
* not qualify as cache-safe in this CachedIntrospectionResults class.
|
||||
@@ -196,7 +200,7 @@ public class CachedIntrospectionResults {
|
||||
}
|
||||
results = new CachedIntrospectionResults(beanClass);
|
||||
synchronized (classCache) {
|
||||
classCache.put(beanClass, new SoftReference<CachedIntrospectionResults>(results));
|
||||
classCache.put(beanClass, new WeakReference<CachedIntrospectionResults>(results));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||
matches.add(method);
|
||||
}
|
||||
}
|
||||
// Sort non-void returning write methods to guard against the ill effects of
|
||||
// sort non-void returning write methods to guard against the ill effects of
|
||||
// non-deterministic sorting of methods returned from Class#getDeclaredMethods
|
||||
// under JDK 7. See http://bugs.sun.com/view_bug.do?bug_id=7023180
|
||||
Collections.sort(matches, new Comparator<Method>() {
|
||||
@@ -437,24 +437,24 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor {
|
||||
* See java.beans.IndexedPropertyDescriptor#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof IndexedPropertyDescriptor)) {
|
||||
return false;
|
||||
if (obj != null && obj instanceof IndexedPropertyDescriptor) {
|
||||
IndexedPropertyDescriptor other = (IndexedPropertyDescriptor) obj;
|
||||
if (!compareMethods(getIndexedReadMethod(), other.getIndexedReadMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (!compareMethods(getIndexedWriteMethod(), other.getIndexedWriteMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (getIndexedPropertyType() != other.getIndexedPropertyType()) {
|
||||
return false;
|
||||
}
|
||||
return PropertyDescriptorUtils.equals(this, obj);
|
||||
}
|
||||
IndexedPropertyDescriptor otherPd = (IndexedPropertyDescriptor) other;
|
||||
if (!compareMethods(getIndexedReadMethod(), otherPd.getIndexedReadMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (!compareMethods(getIndexedWriteMethod(), otherPd.getIndexedWriteMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (getIndexedPropertyType() != otherPd.getIndexedPropertyType()) {
|
||||
return false;
|
||||
}
|
||||
return PropertyDescriptorUtils.equals(this, other);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -595,23 +595,25 @@ class PropertyDescriptorUtils {
|
||||
* editor and flags are equivalent.
|
||||
* @see PropertyDescriptor#equals(Object)
|
||||
*/
|
||||
public static boolean equals(PropertyDescriptor pd, Object other) {
|
||||
if (pd == other) {
|
||||
public static boolean equals(PropertyDescriptor pd1, Object obj) {
|
||||
if (pd1 == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof PropertyDescriptor)) {
|
||||
return false;
|
||||
if (obj != null && obj instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor pd2 = (PropertyDescriptor) obj;
|
||||
if (!compareMethods(pd1.getReadMethod(), pd2.getReadMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (!compareMethods(pd1.getWriteMethod(), pd2.getWriteMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (pd1.getPropertyType() == pd2.getPropertyType() &&
|
||||
pd1.getPropertyEditorClass() == pd2.getPropertyEditorClass() &&
|
||||
pd1.isBound() == pd2.isBound() && pd1.isConstrained() == pd2.isConstrained()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
PropertyDescriptor otherPd = (PropertyDescriptor) other;
|
||||
if (!compareMethods(pd.getReadMethod(), otherPd.getReadMethod())) {
|
||||
return false;
|
||||
}
|
||||
if (!compareMethods(pd.getWriteMethod(), otherPd.getWriteMethod())) {
|
||||
return false;
|
||||
}
|
||||
return (pd.getPropertyType() == otherPd.getPropertyType() &&
|
||||
pd.getPropertyEditorClass() == otherPd.getPropertyEditorClass() &&
|
||||
pd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,7 +89,7 @@ public class PropertyEditorRegistrySupport implements PropertyEditorRegistry {
|
||||
|
||||
static {
|
||||
try {
|
||||
zoneIdClass = ClassUtils.forName("java.time.ZoneId", PropertyEditorRegistrySupport.class.getClassLoader());
|
||||
zoneIdClass = PropertyEditorRegistrySupport.class.getClassLoader().loadClass("java.time.ZoneId");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 8 ZoneId class not available
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -172,8 +172,7 @@ final class PropertyMatches {
|
||||
char t_j = s2.charAt(j - 1);
|
||||
if (s_i == t_j) {
|
||||
cost = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cost = 1;
|
||||
}
|
||||
d[i][j] = Math.min(Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -289,19 +289,19 @@ class TypeConverterDelegate {
|
||||
if (index > - 1) {
|
||||
String enumType = trimmedValue.substring(0, index);
|
||||
String fieldName = trimmedValue.substring(index + 1);
|
||||
ClassLoader cl = this.targetObject.getClass().getClassLoader();
|
||||
ClassLoader loader = this.targetObject.getClass().getClassLoader();
|
||||
try {
|
||||
Class<?> enumValueType = ClassUtils.forName(enumType, cl);
|
||||
Class<?> enumValueType = loader.loadClass(enumType);
|
||||
Field enumField = enumValueType.getField(fieldName);
|
||||
convertedValue = enumField.get(null);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Enum class [" + enumType + "] cannot be loaded", ex);
|
||||
if(logger.isTraceEnabled()) {
|
||||
logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex);
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
if(logger.isTraceEnabled()) {
|
||||
logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -170,7 +170,8 @@ public interface BeanFactory {
|
||||
* <p>Allows for specifying explicit constructor arguments / factory method arguments,
|
||||
* overriding the specified default arguments (if any) in the bean definition.
|
||||
* @param name the name of the bean to retrieve
|
||||
* @param args arguments to use if creating a prototype using explicit arguments
|
||||
* @param args arguments to use if creating a prototype using explicit arguments to a
|
||||
* static factory method. It is invalid to use a non-null args value in any other case.
|
||||
* @return an instance of the bean
|
||||
* @throws NoSuchBeanDefinitionException if there is no such bean definition
|
||||
* @throws BeanDefinitionStoreException if arguments have been given but
|
||||
|
||||
+4
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.beans.factory.access.el;
|
||||
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELException;
|
||||
import javax.el.ELResolver;
|
||||
@@ -77,14 +78,8 @@ public abstract class SpringBeanELResolver extends ELResolver {
|
||||
String beanName = property.toString();
|
||||
BeanFactory bf = getBeanFactory(elContext);
|
||||
if (bf.containsBean(beanName)) {
|
||||
if (value == bf.getBean(beanName)) {
|
||||
// Setting the bean reference to the same value is alright - can simply be ignored...
|
||||
elContext.setPropertyResolved(true);
|
||||
}
|
||||
else {
|
||||
throw new PropertyNotWritableException(
|
||||
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
|
||||
}
|
||||
throw new PropertyNotWritableException(
|
||||
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -135,9 +135,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
public AutowiredAnnotationBeanPostProcessor() {
|
||||
this.autowiredAnnotationTypes.add(Autowired.class);
|
||||
this.autowiredAnnotationTypes.add(Value.class);
|
||||
ClassLoader cl = AutowiredAnnotationBeanPostProcessor.class.getClassLoader();
|
||||
try {
|
||||
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
|
||||
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
|
||||
this.autowiredAnnotationTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Inject"));
|
||||
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
@@ -239,8 +239,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
AnnotationAttributes annotation = findAutowiredAnnotation(candidate);
|
||||
if (annotation != null) {
|
||||
if (requiredConstructor != null) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Invalid autowire-marked constructor: " + candidate +
|
||||
throw new BeanCreationException("Invalid autowire-marked constructor: " + candidate +
|
||||
". Found another constructor with 'required' Autowired annotation: " +
|
||||
requiredConstructor);
|
||||
}
|
||||
@@ -251,10 +250,10 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
|
||||
boolean required = determineRequiredStatus(annotation);
|
||||
if (required) {
|
||||
if (!candidates.isEmpty()) {
|
||||
throw new BeanCreationException(beanName,
|
||||
throw new BeanCreationException(
|
||||
"Invalid autowire-marked constructors: " + candidates +
|
||||
". Found another constructor with 'required' Autowired annotation: " +
|
||||
candidate);
|
||||
requiredConstructor);
|
||||
}
|
||||
requiredConstructor = candidate;
|
||||
}
|
||||
|
||||
+3
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,6 @@ import org.springframework.util.ObjectUtils;
|
||||
* Spring's {@link Qualifier @Qualifier} annotation.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1.2
|
||||
* @see BeanFactoryUtils
|
||||
*/
|
||||
@@ -91,13 +90,9 @@ public class BeanFactoryAnnotationUtils {
|
||||
if (matchingBean != null) {
|
||||
return matchingBean;
|
||||
}
|
||||
else if (bf.containsBean(qualifier)) {
|
||||
// Fallback: target bean at least found by bean name - probably a manually registered singleton.
|
||||
return bf.getBean(qualifier, beanType);
|
||||
}
|
||||
else {
|
||||
throw new NoSuchBeanDefinitionException(qualifier, "No matching " + beanType.getSimpleName() +
|
||||
" bean found for qualifier '" + qualifier + "' - neither qualifier match nor bean name match!");
|
||||
" bean found for qualifier '" + qualifier + "' - neither qualifier " + "match nor bean name match!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +128,7 @@ public class BeanFactoryAnnotationUtils {
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// Ignore - can't compare qualifiers for a manually registered singleton object
|
||||
// ignore - can't compare qualifiers for a manually registered singleton object
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,9 +66,9 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
|
||||
@SuppressWarnings("unchecked")
|
||||
public QualifierAnnotationAutowireCandidateResolver() {
|
||||
this.qualifierTypes.add(Qualifier.class);
|
||||
ClassLoader cl = QualifierAnnotationAutowireCandidateResolver.class.getClassLoader();
|
||||
try {
|
||||
this.qualifierTypes.add((Class<? extends Annotation>)
|
||||
ClassUtils.forName("javax.inject.Qualifier", QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
|
||||
this.qualifierTypes.add((Class<? extends Annotation>) cl.loadClass("javax.inject.Qualifier"));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - simply skip.
|
||||
|
||||
-132
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Simple method invoker bean: just invoking a target method, not expecting a result
|
||||
* to expose to the container (in contrast to {@link MethodInvokingFactoryBean}).
|
||||
*
|
||||
* <p>This invoker supports any kind of target method. A static method may be specified
|
||||
* by setting the {@link #setTargetMethod targetMethod} property to a String representing
|
||||
* the static method name, with {@link #setTargetClass targetClass} specifying the Class
|
||||
* that the static method is defined on. Alternatively, a target instance method may be
|
||||
* specified, by setting the {@link #setTargetObject targetObject} property as the target
|
||||
* object, and the {@link #setTargetMethod targetMethod} property as the name of the
|
||||
* method to call on that target object. Arguments for the method invocation may be
|
||||
* specified by setting the {@link #setArguments arguments} property.
|
||||
*
|
||||
* <p>This class depends on {@link #afterPropertiesSet()} being called once
|
||||
* all properties have been set, as per the InitializingBean contract.
|
||||
*
|
||||
* <p>An example (in an XML based bean factory definition) of a bean definition
|
||||
* which uses this class to call a static initialization method:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingBean">
|
||||
* <property name="staticMethod" value="com.whatever.MyClass.init"/>
|
||||
* </bean></pre>
|
||||
*
|
||||
* <p>An example of calling an instance method to start some server bean:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="myStarter" class="org.springframework.beans.factory.config.MethodInvokingBean">
|
||||
* <property name="targetObject" ref="myServer"/>
|
||||
* <property name="targetMethod" value="start"/>
|
||||
* </bean></pre>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0.3
|
||||
* @see MethodInvokingFactoryBean
|
||||
* @see org.springframework.util.MethodInvoker
|
||||
*/
|
||||
public class MethodInvokingBean extends ArgumentConvertingMethodInvoker
|
||||
implements BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private ConfigurableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClassName(String className) throws ClassNotFoundException {
|
||||
return ClassUtils.forName(className, this.beanClassLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the TypeConverter from the BeanFactory that this bean runs in,
|
||||
* if possible.
|
||||
* @see ConfigurableBeanFactory#getTypeConverter()
|
||||
*/
|
||||
@Override
|
||||
protected TypeConverter getDefaultTypeConverter() {
|
||||
if (this.beanFactory != null) {
|
||||
return this.beanFactory.getTypeConverter();
|
||||
}
|
||||
else {
|
||||
return super.getDefaultTypeConverter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
prepare();
|
||||
invokeWithTargetException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the invocation and convert InvocationTargetException
|
||||
* into the underlying target exception.
|
||||
*/
|
||||
protected Object invokeWithTargetException() throws Exception {
|
||||
try {
|
||||
return invoke();
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof Exception) {
|
||||
throw (Exception) ex.getTargetException();
|
||||
}
|
||||
if (ex.getTargetException() instanceof Error) {
|
||||
throw (Error) ex.getTargetException();
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+90
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,17 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} which returns a value which is the result of a static or instance
|
||||
@@ -35,14 +44,10 @@ import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
* {@link #setSingleton singleton} property may be set to "false", to cause this
|
||||
* factory to invoke the target method each time it is asked for an object.
|
||||
*
|
||||
* <p><b>NOTE: If your target method does not produce a result to expose, consider
|
||||
* {@link MethodInvokingBean} instead, which avoids the type determination and
|
||||
* lifecycle limitations that this {@link MethodInvokingFactoryBean} comes with.</b>
|
||||
*
|
||||
* <p>This invoker supports any kind of target method. A static method may be specified
|
||||
* by setting the {@link #setTargetMethod targetMethod} property to a String representing
|
||||
* the static method name, with {@link #setTargetClass targetClass} specifying the Class
|
||||
* that the static method is defined on. Alternatively, a target instance method may be
|
||||
* <p>A static target method may be specified by setting the
|
||||
* {@link #setTargetMethod targetMethod} property to a String representing the static
|
||||
* method name, with {@link #setTargetClass targetClass} specifying the Class that
|
||||
* the static method is defined on. Alternatively, a target instance method may be
|
||||
* specified, by setting the {@link #setTargetObject targetObject} property as the target
|
||||
* object, and the {@link #setTargetMethod targetMethod} property as the name of the
|
||||
* method to call on that target object. Arguments for the method invocation may be
|
||||
@@ -56,7 +61,7 @@ import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
* <property name="staticMethod" value="com.whatever.MyClassFactory.getInstance"/>
|
||||
* <property name="staticMethod"><value>com.whatever.MyClassFactory.getInstance</value></property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* <p>An example of calling a static method then an instance method to get at a
|
||||
@@ -64,26 +69,33 @@ import org.springframework.beans.factory.FactoryBeanNotInitializedException;
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
* <property name="targetClass" value="java.lang.System"/>
|
||||
* <property name="targetMethod" value="getProperties"/>
|
||||
* <property name="targetClass"><value>java.lang.System</value></property>
|
||||
* <property name="targetMethod"><value>getProperties</value></property>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
* <property name="targetObject" value="sysProps"/>
|
||||
* <property name="targetMethod" value="getProperty"/>
|
||||
* <property name="arguments" value="java.version"/>
|
||||
* <property name="targetObject"><ref local="sysProps"/></property>
|
||||
* <property name="targetMethod"><value>getProperty</value></property>
|
||||
* <property name="arguments">
|
||||
* <list>
|
||||
* <value>java.version</value>
|
||||
* </list>
|
||||
* </property>
|
||||
* </bean></pre>
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @since 21.11.2003
|
||||
* @see MethodInvokingBean
|
||||
* @see org.springframework.util.MethodInvoker
|
||||
*/
|
||||
public class MethodInvokingFactoryBean extends MethodInvokingBean implements FactoryBean<Object> {
|
||||
public class MethodInvokingFactoryBean extends ArgumentConvertingMethodInvoker
|
||||
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware, InitializingBean {
|
||||
|
||||
private boolean singleton = true;
|
||||
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private ConfigurableBeanFactory beanFactory;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
/** Method call result in the singleton case */
|
||||
@@ -92,18 +104,75 @@ public class MethodInvokingFactoryBean extends MethodInvokingBean implements Fac
|
||||
|
||||
/**
|
||||
* Set if a singleton should be created, or a new object on each
|
||||
* {@link #getObject()} request otherwise. Default is "true".
|
||||
* request else. Default is "true".
|
||||
*/
|
||||
public void setSingleton(boolean singleton) {
|
||||
this.singleton = singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClassName(String className) throws ClassNotFoundException {
|
||||
return ClassUtils.forName(className, this.beanClassLoader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the TypeConverter from the BeanFactory that this bean runs in,
|
||||
* if possible.
|
||||
* @see ConfigurableBeanFactory#getTypeConverter()
|
||||
*/
|
||||
@Override
|
||||
protected TypeConverter getDefaultTypeConverter() {
|
||||
if (this.beanFactory != null) {
|
||||
return this.beanFactory.getTypeConverter();
|
||||
}
|
||||
else {
|
||||
return super.getDefaultTypeConverter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
prepare();
|
||||
if (this.singleton) {
|
||||
this.initialized = true;
|
||||
this.singletonObject = invokeWithTargetException();
|
||||
this.singletonObject = doInvoke();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the invocation and convert InvocationTargetException
|
||||
* into the underlying target exception.
|
||||
*/
|
||||
private Object doInvoke() throws Exception {
|
||||
try {
|
||||
return invoke();
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof Exception) {
|
||||
throw (Exception) ex.getTargetException();
|
||||
}
|
||||
if (ex.getTargetException() instanceof Error) {
|
||||
throw (Error) ex.getTargetException();
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +193,7 @@ public class MethodInvokingFactoryBean extends MethodInvokingBean implements Fac
|
||||
}
|
||||
else {
|
||||
// Prototype: new object on each call.
|
||||
return invokeWithTargetException();
|
||||
return doInvoke();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,9 +210,4 @@ public class MethodInvokingFactoryBean extends MethodInvokingBean implements Fac
|
||||
return getPreparedMethod().getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return this.singleton;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -286,7 +286,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Use prototype bean definition, to avoid registering bean as dependent bean.
|
||||
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
|
||||
bd.setScope(SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
|
||||
bd.allowCaching = false;
|
||||
return (T) createBean(beanClass.getName(), bd, null);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
|
||||
RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = ClassUtils.isCacheSafe(bd.getBeanClass(), getBeanClassLoader());
|
||||
bd.allowCaching = false;
|
||||
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
||||
initBeanWrapper(bw);
|
||||
populateBean(bd.getBeanClass().getName(), bd, bw);
|
||||
@@ -315,7 +315,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
bd = new RootBeanDefinition(mbd);
|
||||
}
|
||||
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
|
||||
bd.allowCaching = ClassUtils.isCacheSafe(ClassUtils.getUserClass(existingBean), getBeanClassLoader());
|
||||
bd.allowCaching = false;
|
||||
}
|
||||
BeanWrapper bw = new BeanWrapperImpl(existingBean);
|
||||
initBeanWrapper(bw);
|
||||
@@ -832,8 +832,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (bw != null) {
|
||||
return (FactoryBean<?>) bw.getWrappedInstance();
|
||||
}
|
||||
if (isSingletonCurrentlyInCreation(beanName) ||
|
||||
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
|
||||
if (isSingletonCurrentlyInCreation(beanName)) {
|
||||
return null;
|
||||
}
|
||||
Object instance = null;
|
||||
@@ -1413,7 +1412,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
MutablePropertyValues mpvs = null;
|
||||
List<PropertyValue> original;
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
if (System.getSecurityManager()!= null) {
|
||||
if (bw instanceof BeanWrapperImpl) {
|
||||
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
|
||||
}
|
||||
@@ -1710,7 +1709,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
|
||||
/**
|
||||
* Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
|
||||
* Special DependencyDescriptor variant for autowire="byType".
|
||||
* Always optional; never considering the parameter name for choosing a primary candidate.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
+10
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,8 +38,8 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* Base class for concrete, full-fledged
|
||||
* {@link org.springframework.beans.factory.config.BeanDefinition} classes,
|
||||
* factoring out common properties of {@link GenericBeanDefinition},
|
||||
* {@link RootBeanDefinition} and {@link ChildBeanDefinition}.
|
||||
* factoring out common properties of {@link RootBeanDefinition} and
|
||||
* {@link ChildBeanDefinition}.
|
||||
*
|
||||
* <p>The autowire constants match the ones defined in the
|
||||
* {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
|
||||
@@ -123,14 +123,11 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
public static final int DEPENDENCY_CHECK_ALL = 3;
|
||||
|
||||
/**
|
||||
* Constant that indicates the container should attempt to infer the
|
||||
* {@link #setDestroyMethodName destroy method name} for a bean as opposed to
|
||||
* explicit specification of a method name. The value {@value} is specifically
|
||||
* designed to include characters otherwise illegal in a method name, ensuring
|
||||
* no possibility of collisions with legitimately named methods having the same
|
||||
* name.
|
||||
* <p>Currently, the method names detected during destroy method inference
|
||||
* are "close" and "shutdown", if present on the specific bean class.
|
||||
* Constant that indicates the container should attempt to infer the {@link
|
||||
* #setDestroyMethodName destroy method name} for a bean as opposed to explicit
|
||||
* specification of a method name. The value {@value} is specifically designed to
|
||||
* include characters otherwise illegal in a method name, ensuring no possibility of
|
||||
* collisions with legitimately named methods having the same name.
|
||||
*/
|
||||
public static final String INFER_METHOD = "(inferred)";
|
||||
|
||||
@@ -647,8 +644,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
|
||||
/**
|
||||
* Specify whether to allow access to non-public constructors and methods,
|
||||
* for the case of externalized metadata pointing to those. The default is
|
||||
* {@code true}; switch this to {@code false} for public access only.
|
||||
* for the case of externalized metadata pointing to those.
|
||||
* <p>This applies to constructor resolution, factory method resolution,
|
||||
* and also init/destroy methods. Bean property accessors have to be public
|
||||
* in any case and are not affected by this setting.
|
||||
@@ -670,7 +666,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
|
||||
/**
|
||||
* Specify whether to resolve constructors in lenient mode ({@code true},
|
||||
* which is the default) or to switch to strict resolution (throwing an exception
|
||||
* in case of ambiguous constructors that all match when converting the arguments,
|
||||
* in case of ambigious constructors that all match when converting the arguments,
|
||||
* whereas lenient mode would use the one with the 'closest' type matches).
|
||||
*/
|
||||
public void setLenientConstructorResolution(boolean lenientConstructorResolution) {
|
||||
|
||||
+10
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -124,7 +124,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
/** Resolution strategy for expressions in bean definition values */
|
||||
private BeanExpressionResolver beanExpressionResolver;
|
||||
|
||||
/** Spring ConversionService to use instead of PropertyEditors */
|
||||
/** Spring 3.0 ConversionService to use instead of PropertyEditors */
|
||||
private ConversionService conversionService;
|
||||
|
||||
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
|
||||
@@ -160,7 +160,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
|
||||
new ConcurrentHashMap<String, RootBeanDefinition>(64);
|
||||
|
||||
/** Names of beans that have already been created at least once */
|
||||
/**
|
||||
* Names of beans that have already been created at least once
|
||||
*/
|
||||
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64));
|
||||
|
||||
/** Names of beans that are currently in creation */
|
||||
@@ -285,8 +287,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
if (dependsOn != null) {
|
||||
for (String dependsOnBean : dependsOn) {
|
||||
if (isDependent(beanName, dependsOnBean)) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
|
||||
throw new BeanCreationException("Circular depends-on relationship between '" +
|
||||
beanName + "' and '" + dependsOnBean + "'");
|
||||
}
|
||||
registerDependentBean(dependsOnBean, beanName);
|
||||
getBean(dependsOnBean);
|
||||
@@ -1274,7 +1276,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
// Check validity of the usage of the args parameter. This can
|
||||
// only be used for prototypes constructed via a factory method.
|
||||
if (args != null && !mbd.isPrototype()) {
|
||||
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
|
||||
throw new BeanDefinitionStoreException(
|
||||
"Can only specify arguments for the getBean method when referring to a prototype bean definition");
|
||||
}
|
||||
}
|
||||
@@ -1625,7 +1627,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* instantiation within this class is performed by this method.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the merged bean definition for the bean
|
||||
* @param args arguments to use if creating a prototype using explicit arguments
|
||||
* @param args arguments to use if creating a prototype using explicit arguments to a
|
||||
* static factory method. This parameter must be {@code null} except in this case.
|
||||
* @return a new instance of the bean
|
||||
* @throws BeanCreationException if the bean could not be created
|
||||
*/
|
||||
|
||||
+5
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -81,7 +81,6 @@ class BeanDefinitionValueResolver {
|
||||
this.typeConverter = typeConverter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a PropertyValue, return a value, resolving any references to other
|
||||
* beans in the factory if necessary. The value could be:
|
||||
@@ -124,9 +123,7 @@ class BeanDefinitionValueResolver {
|
||||
else if (value instanceof BeanDefinition) {
|
||||
// Resolve plain BeanDefinition, without contained name: use dummy name.
|
||||
BeanDefinition bd = (BeanDefinition) value;
|
||||
String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR +
|
||||
ObjectUtils.getIdentityHexString(bd);
|
||||
return resolveInnerBean(argName, innerBeanName, bd);
|
||||
return resolveInnerBean(argName, "(inner bean)", bd);
|
||||
}
|
||||
else if (value instanceof ManagedArray) {
|
||||
// May need to resolve contained runtime references.
|
||||
@@ -259,25 +256,20 @@ class BeanDefinitionValueResolver {
|
||||
mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
|
||||
// Check given bean name whether it is unique. If not already unique,
|
||||
// add counter - increasing the counter until the name is unique.
|
||||
String actualInnerBeanName = innerBeanName;
|
||||
if (mbd.isSingleton()) {
|
||||
actualInnerBeanName = adaptInnerBeanName(innerBeanName);
|
||||
}
|
||||
String actualInnerBeanName = adaptInnerBeanName(innerBeanName);
|
||||
this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
|
||||
// Guarantee initialization of beans that the inner bean depends on.
|
||||
String[] dependsOn = mbd.getDependsOn();
|
||||
if (dependsOn != null) {
|
||||
for (String dependsOnBean : dependsOn) {
|
||||
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
|
||||
this.beanFactory.getBean(dependsOnBean);
|
||||
this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
|
||||
}
|
||||
}
|
||||
// Actually create the inner bean instance now...
|
||||
Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
|
||||
if (innerBean instanceof FactoryBean) {
|
||||
boolean synthetic = mbd.isSynthetic();
|
||||
return this.beanFactory.getObjectFromFactoryBean(
|
||||
(FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
|
||||
return this.beanFactory.getObjectFromFactoryBean((FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
|
||||
}
|
||||
else {
|
||||
return innerBean;
|
||||
|
||||
+100
-150
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,27 +22,22 @@ import java.lang.reflect.Method;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cglib.core.SpringNamingPolicy;
|
||||
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.Factory;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
|
||||
/**
|
||||
* Default object instantiation strategy for use in BeanFactories.
|
||||
*
|
||||
* <p>Uses CGLIB to generate subclasses dynamically if methods need to be
|
||||
* overridden by the container to implement <em>Method Injection</em>.
|
||||
* Uses CGLIB to generate subclasses dynamically if methods need to be
|
||||
* overridden by the container, to implement Method Injection.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.1
|
||||
*/
|
||||
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
|
||||
@@ -55,29 +50,30 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
|
||||
/**
|
||||
* Index in the CGLIB callback array for a method that should
|
||||
* be overridden to provide <em>method lookup</em>.
|
||||
* be overridden to provide method lookup.
|
||||
*/
|
||||
private static final int LOOKUP_OVERRIDE = 1;
|
||||
|
||||
/**
|
||||
* Index in the CGLIB callback array for a method that should
|
||||
* be overridden using generic <em>method replacer</em> functionality.
|
||||
* be overridden using generic Methodreplacer functionality.
|
||||
*/
|
||||
private static final int METHOD_REPLACER = 2;
|
||||
|
||||
|
||||
@Override
|
||||
protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName,
|
||||
BeanFactory owner) {
|
||||
protected Object instantiateWithMethodInjection(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
|
||||
|
||||
return instantiateWithMethodInjection(beanDefinition, beanName, owner, null, null);
|
||||
// Must generate CGLIB subclass.
|
||||
return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName,
|
||||
BeanFactory owner, Constructor<?> ctor, Object[] args) {
|
||||
protected Object instantiateWithMethodInjection(
|
||||
RootBeanDefinition beanDefinition, String beanName, BeanFactory owner,
|
||||
Constructor<?> ctor, Object[] args) {
|
||||
|
||||
// Must generate CGLIB subclass.
|
||||
return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args);
|
||||
}
|
||||
|
||||
@@ -88,169 +84,123 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt
|
||||
*/
|
||||
private static class CglibSubclassCreator {
|
||||
|
||||
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
|
||||
{NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};
|
||||
private static final Log logger = LogFactory.getLog(CglibSubclassCreator.class);
|
||||
|
||||
private final RootBeanDefinition beanDefinition;
|
||||
|
||||
private final BeanFactory owner;
|
||||
|
||||
CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
|
||||
public CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
|
||||
this.beanDefinition = beanDefinition;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of a dynamically generated subclass implementing the
|
||||
* Create a new instance of a dynamically generated subclasses implementing the
|
||||
* required lookups.
|
||||
* @param ctor constructor to use. If this is {@code null}, use the
|
||||
* no-arg constructor (no parameterization, or Setter Injection)
|
||||
* @param args arguments to use for the constructor.
|
||||
* Ignored if the {@code ctor} parameter is {@code null}.
|
||||
* @return new instance of the dynamically generated subclass
|
||||
* Ignored if the ctor parameter is {@code null}.
|
||||
* @return new instance of the dynamically generated class
|
||||
*/
|
||||
Object instantiate(Constructor<?> ctor, Object[] args) {
|
||||
Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
|
||||
Object instance;
|
||||
if (ctor == null) {
|
||||
instance = BeanUtils.instantiate(subclass);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
|
||||
instance = enhancedSubclassConstructor.newInstance(args);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format(
|
||||
"Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex);
|
||||
}
|
||||
}
|
||||
// SPR-10785: set callbacks directly on the instance instead of in the
|
||||
// enhanced class (via the Enhancer) in order to avoid memory leaks.
|
||||
Factory factory = (Factory) instance;
|
||||
factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
|
||||
new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
|
||||
new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
|
||||
return instance;
|
||||
public Object instantiate(Constructor<?> ctor, Object[] args) {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(this.beanDefinition.getBeanClass());
|
||||
enhancer.setCallbackFilter(new CallbackFilterImpl());
|
||||
enhancer.setCallbacks(new Callback[] {
|
||||
NoOp.INSTANCE,
|
||||
new LookupOverrideMethodInterceptor(),
|
||||
new ReplaceOverrideMethodInterceptor()
|
||||
});
|
||||
|
||||
return (ctor == null) ?
|
||||
enhancer.create() :
|
||||
enhancer.create(ctor.getParameterTypes(), args);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an enhanced subclass of the bean class for the provided bean
|
||||
* definition, using CGLIB.
|
||||
* Class providing hashCode and equals methods required by CGLIB to
|
||||
* ensure that CGLIB doesn't generate a distinct class per bean.
|
||||
* Identity is based on class and bean definition.
|
||||
*/
|
||||
private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(beanDefinition.getBeanClass());
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
|
||||
enhancer.setCallbackTypes(CALLBACK_TYPES);
|
||||
return enhancer.createClass();
|
||||
}
|
||||
}
|
||||
private class CglibIdentitySupport {
|
||||
|
||||
|
||||
/**
|
||||
* Class providing hashCode and equals methods required by CGLIB to
|
||||
* ensure that CGLIB doesn't generate a distinct class per bean.
|
||||
* Identity is based on class and bean definition.
|
||||
*/
|
||||
private static class CglibIdentitySupport {
|
||||
|
||||
private final RootBeanDefinition beanDefinition;
|
||||
|
||||
CglibIdentitySupport(RootBeanDefinition beanDefinition) {
|
||||
this.beanDefinition = beanDefinition;
|
||||
}
|
||||
|
||||
RootBeanDefinition getBeanDefinition() {
|
||||
return this.beanDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (getClass().equals(other.getClass()) &&
|
||||
this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.beanDefinition.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB callback for filtering method interception behavior.
|
||||
*/
|
||||
private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class);
|
||||
|
||||
MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
|
||||
super(beanDefinition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int accept(Method method) {
|
||||
MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
|
||||
/**
|
||||
* Exposed for equals method to allow access to enclosing class field
|
||||
*/
|
||||
protected RootBeanDefinition getBeanDefinition() {
|
||||
return beanDefinition;
|
||||
}
|
||||
if (methodOverride == null) {
|
||||
return PASSTHROUGH;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (other.getClass().equals(getClass()) &&
|
||||
((CglibIdentitySupport) other).getBeanDefinition().equals(beanDefinition));
|
||||
}
|
||||
else if (methodOverride instanceof LookupOverride) {
|
||||
return LOOKUP_OVERRIDE;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return beanDefinition.hashCode();
|
||||
}
|
||||
else if (methodOverride instanceof ReplaceOverride) {
|
||||
return METHOD_REPLACER;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB MethodInterceptor to override methods, replacing them with an
|
||||
* implementation that returns a bean looked up in the container.
|
||||
*/
|
||||
private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
|
||||
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
|
||||
// Cast is safe, as CallbackFilter filters are used selectively.
|
||||
LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method);
|
||||
return owner.getBean(lo.getBeanName());
|
||||
}
|
||||
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
|
||||
methodOverride.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB MethodInterceptor to override methods, replacing them with an
|
||||
* implementation that returns a bean looked up in the container.
|
||||
*/
|
||||
private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
|
||||
|
||||
private final BeanFactory owner;
|
||||
|
||||
LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
|
||||
super(beanDefinition);
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
|
||||
// Cast is safe, as CallbackFilter filters are used selectively.
|
||||
LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
|
||||
return this.owner.getBean(lo.getBeanName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CGLIB MethodInterceptor to override methods, replacing them with a call
|
||||
* to a generic MethodReplacer.
|
||||
*/
|
||||
private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
|
||||
/**
|
||||
* CGLIB MethodInterceptor to override methods, replacing them with a call
|
||||
* to a generic MethodReplacer.
|
||||
*/
|
||||
private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
|
||||
|
||||
private final BeanFactory owner;
|
||||
|
||||
ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
|
||||
super(beanDefinition);
|
||||
this.owner = owner;
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
|
||||
ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method);
|
||||
// TODO could cache if a singleton for minor performance optimization
|
||||
MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName());
|
||||
return mr.reimplement(obj, method, args);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
|
||||
ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
|
||||
// TODO could cache if a singleton for minor performance optimization
|
||||
MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
|
||||
return mr.reimplement(obj, method, args);
|
||||
|
||||
/**
|
||||
* CGLIB object to filter method interception behavior.
|
||||
*/
|
||||
private class CallbackFilterImpl extends CglibIdentitySupport implements CallbackFilter {
|
||||
|
||||
@Override
|
||||
public int accept(Method method) {
|
||||
MethodOverride methodOverride = beanDefinition.getMethodOverrides().getOverride(method);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]");
|
||||
}
|
||||
if (methodOverride == null) {
|
||||
return PASSTHROUGH;
|
||||
}
|
||||
else if (methodOverride instanceof LookupOverride) {
|
||||
return LOOKUP_OVERRIDE;
|
||||
}
|
||||
else if (methodOverride instanceof ReplaceOverride) {
|
||||
return METHOD_REPLACER;
|
||||
}
|
||||
throw new UnsupportedOperationException(
|
||||
"Unexpected MethodOverride subclass: " + methodOverride.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+48
-53
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,9 +54,12 @@ import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Delegate for resolving constructors and factory methods.
|
||||
* Helper class for resolving constructors and factory methods.
|
||||
* Performs constructor resolution through argument matching.
|
||||
*
|
||||
* <p>Operates on an {@link AbstractBeanFactory} and an {@link InstantiationStrategy}.
|
||||
* Used by {@link AbstractAutowireCapableBeanFactory}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Mark Fisher
|
||||
@@ -68,6 +71,11 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class ConstructorResolver {
|
||||
|
||||
private static final String CONSTRUCTOR_PROPERTIES_CLASS_NAME = "java.beans.ConstructorProperties";
|
||||
|
||||
private static final boolean constructorPropertiesAnnotationAvailable =
|
||||
ClassUtils.isPresent(CONSTRUCTOR_PROPERTIES_CLASS_NAME, ConstructorResolver.class.getClassLoader());
|
||||
|
||||
private final AbstractAutowireCapableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@@ -175,7 +183,10 @@ class ConstructorResolver {
|
||||
ArgumentsHolder argsHolder;
|
||||
if (resolvedValues != null) {
|
||||
try {
|
||||
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
|
||||
String[] paramNames = null;
|
||||
if (constructorPropertiesAnnotationAvailable) {
|
||||
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
|
||||
}
|
||||
if (paramNames == null) {
|
||||
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
|
||||
if (pnd != null) {
|
||||
@@ -286,21 +297,17 @@ class ConstructorResolver {
|
||||
*/
|
||||
public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
|
||||
Class<?> factoryClass;
|
||||
boolean isStatic;
|
||||
if (mbd.getFactoryBeanName() != null) {
|
||||
factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
|
||||
isStatic = false;
|
||||
}
|
||||
else {
|
||||
factoryClass = mbd.getBeanClass();
|
||||
isStatic = true;
|
||||
}
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
|
||||
Method[] candidates = getCandidateMethods(factoryClass, mbd);
|
||||
Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
|
||||
Method uniqueCandidate = null;
|
||||
for (Method candidate : candidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
|
||||
if (mbd.isFactoryMethod(candidate)) {
|
||||
if (uniqueCandidate == null) {
|
||||
uniqueCandidate = candidate;
|
||||
}
|
||||
@@ -315,27 +322,6 @@ class ConstructorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all candidate methods for the given class, considering
|
||||
* the {@link RootBeanDefinition#isNonPublicAccessAllowed()} flag.
|
||||
* Called as the starting point for factory method determination.
|
||||
*/
|
||||
private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
|
||||
if (System.getSecurityManager() != null) {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
||||
@Override
|
||||
public Method[] run() {
|
||||
return (mbd.isNonPublicAccessAllowed() ?
|
||||
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return (mbd.isNonPublicAccessAllowed() ?
|
||||
ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the bean using a named factory method. The method may be static, if the
|
||||
* bean definition parameter specifies a class, rather than a "factory-bean", or
|
||||
@@ -351,9 +337,7 @@ class ConstructorResolver {
|
||||
* method, or {@code null} if none (-> use constructor argument values from bean definition)
|
||||
* @return a BeanWrapper for the new instance
|
||||
*/
|
||||
public BeanWrapper instantiateUsingFactoryMethod(
|
||||
final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
|
||||
|
||||
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
|
||||
BeanWrapperImpl bw = new BeanWrapperImpl();
|
||||
this.beanFactory.initBeanWrapper(bw);
|
||||
|
||||
@@ -370,7 +354,7 @@ class ConstructorResolver {
|
||||
factoryBean = this.beanFactory.getBean(factoryBeanName);
|
||||
if (factoryBean == null) {
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
|
||||
"factory-bean '" + factoryBeanName + "' returned null");
|
||||
}
|
||||
factoryClass = factoryBean.getClass();
|
||||
isStatic = false;
|
||||
@@ -414,11 +398,28 @@ class ConstructorResolver {
|
||||
// Need to determine the factory method...
|
||||
// Try all methods with this name to see if they match the given arguments.
|
||||
factoryClass = ClassUtils.getUserClass(factoryClass);
|
||||
Method[] rawCandidates;
|
||||
|
||||
final Class<?> factoryClazz = factoryClass;
|
||||
if (System.getSecurityManager() != null) {
|
||||
rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
|
||||
@Override
|
||||
public Method[] run() {
|
||||
return (mbd.isNonPublicAccessAllowed() ?
|
||||
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
rawCandidates = (mbd.isNonPublicAccessAllowed() ?
|
||||
ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
|
||||
}
|
||||
|
||||
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
|
||||
List<Method> candidateSet = new ArrayList<Method>();
|
||||
for (Method candidate : rawCandidates) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
|
||||
if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
|
||||
candidate.getName().equals(mbd.getFactoryMethodName()) &&
|
||||
mbd.isFactoryMethod(candidate)) {
|
||||
candidateSet.add(candidate);
|
||||
}
|
||||
}
|
||||
@@ -523,30 +524,24 @@ class ConstructorResolver {
|
||||
}
|
||||
|
||||
if (factoryMethodToUse == null) {
|
||||
List<String> argTypes = new ArrayList<String>(minNrOfArgs);
|
||||
if (explicitArgs != null) {
|
||||
for (Object arg : explicitArgs) {
|
||||
argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Set<ValueHolder> valueHolders = new LinkedHashSet<ValueHolder>(resolvedValues.getArgumentCount());
|
||||
valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
|
||||
valueHolders.addAll(resolvedValues.getGenericArgumentValues());
|
||||
for (ValueHolder value : valueHolders) {
|
||||
String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
|
||||
(value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
|
||||
boolean hasArgs = (resolvedValues.getArgumentCount() > 0);
|
||||
String argDesc = "";
|
||||
if (hasArgs) {
|
||||
List<String> argTypes = new ArrayList<String>();
|
||||
for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {
|
||||
String argType = (value.getType() != null ?
|
||||
ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName());
|
||||
argTypes.add(argType);
|
||||
}
|
||||
argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
|
||||
}
|
||||
String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
|
||||
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
|
||||
"No matching factory method found: " +
|
||||
(mbd.getFactoryBeanName() != null ?
|
||||
"factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
|
||||
"factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
|
||||
"Check that a method with the specified name " +
|
||||
(minNrOfArgs > 0 ? "and arguments " : "") +
|
||||
(hasArgs ? "and arguments " : "") +
|
||||
"exists and that it is " +
|
||||
(isStatic ? "static" : "non-static") + ".");
|
||||
}
|
||||
@@ -885,11 +880,11 @@ class ConstructorResolver {
|
||||
|
||||
|
||||
/**
|
||||
* Delegate for checking Java 6's {@link ConstructorProperties} annotation.
|
||||
* Inner class to avoid a Java 6 dependency.
|
||||
*/
|
||||
private static class ConstructorPropertiesChecker {
|
||||
|
||||
public static String[] evaluate(Constructor<?> candidate, int paramCount) {
|
||||
public static String[] evaluateAnnotation(Constructor<?> candidate, int paramCount) {
|
||||
ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
|
||||
if (cp != null) {
|
||||
String[] names = cp.value();
|
||||
|
||||
+12
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -61,7 +61,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -105,9 +104,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
private static Class<?> javaxInjectProviderClass = null;
|
||||
|
||||
static {
|
||||
ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
|
||||
try {
|
||||
javaxInjectProviderClass =
|
||||
ClassUtils.forName("javax.inject.Provider", DefaultListableBeanFactory.class.getClassLoader());
|
||||
javaxInjectProviderClass = cl.loadClass("javax.inject.Provider");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - Provider interface simply not supported then.
|
||||
@@ -284,7 +283,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (beanNames.length > 1) {
|
||||
ArrayList<String> autowireCandidates = new ArrayList<String>();
|
||||
for (String beanName : beanNames) {
|
||||
if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
if (getBeanDefinition(beanName).isAutowireCandidate()) {
|
||||
autowireCandidates.add(beanName);
|
||||
}
|
||||
}
|
||||
@@ -350,7 +349,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
|
||||
@Override
|
||||
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
|
||||
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
|
||||
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
|
||||
return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
|
||||
}
|
||||
Map<Class<?>, String[]> cache =
|
||||
@@ -360,9 +359,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
return resolvedBeanNames;
|
||||
}
|
||||
resolvedBeanNames = doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit);
|
||||
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
|
||||
cache.put(type, resolvedBeanNames);
|
||||
}
|
||||
cache.put(type, resolvedBeanNames);
|
||||
return resolvedBeanNames;
|
||||
}
|
||||
|
||||
@@ -671,15 +668,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Pre-instantiating singletons in " + this);
|
||||
}
|
||||
|
||||
List<String> beanNames;
|
||||
synchronized (this.beanDefinitionMap) {
|
||||
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
|
||||
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
|
||||
beanNames = new ArrayList<String>(this.beanDefinitionNames);
|
||||
}
|
||||
|
||||
// Trigger initialization of all non-lazy singleton beans...
|
||||
for (String beanName : beanNames) {
|
||||
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
|
||||
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
|
||||
@@ -731,10 +725,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
|
||||
BeanDefinition oldBeanDefinition;
|
||||
|
||||
synchronized (this.beanDefinitionMap) {
|
||||
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
|
||||
BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
|
||||
if (oldBeanDefinition != null) {
|
||||
if (!this.allowBeanDefinitionOverriding) {
|
||||
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
|
||||
@@ -763,9 +755,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
this.beanDefinitionMap.put(beanName, beanDefinition);
|
||||
}
|
||||
|
||||
if (oldBeanDefinition != null || containsSingleton(beanName)) {
|
||||
resetBeanDefinition(beanName);
|
||||
}
|
||||
resetBeanDefinition(beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -801,6 +791,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
|
||||
destroySingleton(beanName);
|
||||
|
||||
// Remove any assumptions about by-type mappings.
|
||||
clearByTypeCache();
|
||||
|
||||
// Reset all bean definitions that have the given bean as parent (recursively).
|
||||
for (String bdName : this.beanDefinitionNames) {
|
||||
if (!beanName.equals(bdName)) {
|
||||
@@ -1017,7 +1010,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
}
|
||||
}
|
||||
for (String candidateName : candidateNames) {
|
||||
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||
if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) {
|
||||
result.put(candidateName, getBean(candidateName));
|
||||
}
|
||||
}
|
||||
@@ -1095,17 +1088,6 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given beanName/candidateName pair indicates a self reference,
|
||||
* i.e. whether the candidate points back to the original bean or to a factory method
|
||||
* on the original bean.
|
||||
*/
|
||||
private boolean isSelfReference(String beanName, String candidateName) {
|
||||
return (beanName != null && candidateName != null &&
|
||||
(beanName.equals(candidateName) || (containsBeanDefinition(candidateName) &&
|
||||
beanName.equals(getMergedLocalBeanDefinition(candidateName).getFactoryBeanName()))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a NoSuchBeanDefinitionException for an unresolvable dependency.
|
||||
*/
|
||||
|
||||
+6
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -277,7 +277,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
|
||||
@Override
|
||||
public boolean containsSingleton(String beanName) {
|
||||
return this.singletonObjects.containsKey(beanName);
|
||||
return (this.singletonObjects.containsKey(beanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,7 +330,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
* @see #isSingletonCurrentlyInCreation
|
||||
*/
|
||||
protected void beforeSingletonCreation(String beanName) {
|
||||
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
|
||||
if (!this.inCreationCheckExclusions.contains(beanName) &&
|
||||
!this.singletonsCurrentlyInCreation.add(beanName)) {
|
||||
throw new BeanCurrentlyInCreationException(beanName);
|
||||
}
|
||||
}
|
||||
@@ -342,7 +343,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||
* @see #isSingletonCurrentlyInCreation
|
||||
*/
|
||||
protected void afterSingletonCreation(String beanName) {
|
||||
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
|
||||
if (!this.inCreationCheckExclusions.contains(beanName) &&
|
||||
!this.singletonsCurrentlyInCreation.remove(beanName)) {
|
||||
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -69,8 +69,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||
|
||||
static {
|
||||
try {
|
||||
closeableInterface = ClassUtils.forName("java.lang.AutoCloseable",
|
||||
DisposableBeanAdapter.class.getClassLoader());
|
||||
closeableInterface = DisposableBeanAdapter.class.getClassLoader().loadClass("java.lang.AutoCloseable");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
closeableInterface = Closeable.class;
|
||||
|
||||
+19
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,7 +90,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
* Obtain an object to expose from the given FactoryBean.
|
||||
* @param factory the FactoryBean instance
|
||||
* @param beanName the name of the bean
|
||||
* @param shouldPostProcess whether the bean is subject to post-processing
|
||||
* @param shouldPostProcess whether the bean is subject for post-processing
|
||||
* @return the object obtained from the FactoryBean
|
||||
* @throws BeanCreationException if FactoryBean object creation failed
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
@@ -100,40 +100,14 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
synchronized (getSingletonMutex()) {
|
||||
Object object = this.factoryBeanObjectCache.get(beanName);
|
||||
if (object == null) {
|
||||
object = doGetObjectFromFactoryBean(factory, beanName);
|
||||
// Only post-process and store if not put there already during getObject() call above
|
||||
// (e.g. because of circular reference processing triggered by custom getBean calls)
|
||||
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
|
||||
if (alreadyThere != null) {
|
||||
object = alreadyThere;
|
||||
}
|
||||
else {
|
||||
if (object != null && shouldPostProcess) {
|
||||
try {
|
||||
object = postProcessObjectFromFactoryBean(object, beanName);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName,
|
||||
"Post-processing of FactoryBean's singleton object failed", ex);
|
||||
}
|
||||
}
|
||||
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
|
||||
}
|
||||
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
|
||||
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
|
||||
}
|
||||
return (object != NULL_OBJECT ? object : null);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object object = doGetObjectFromFactoryBean(factory, beanName);
|
||||
if (object != null && shouldPostProcess) {
|
||||
try {
|
||||
object = postProcessObjectFromFactoryBean(object, beanName);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
|
||||
}
|
||||
}
|
||||
return object;
|
||||
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,11 +115,13 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
* Obtain an object to expose from the given FactoryBean.
|
||||
* @param factory the FactoryBean instance
|
||||
* @param beanName the name of the bean
|
||||
* @param shouldPostProcess whether the bean is subject for post-processing
|
||||
* @return the object obtained from the FactoryBean
|
||||
* @throws BeanCreationException if FactoryBean object creation failed
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObject()
|
||||
*/
|
||||
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
|
||||
private Object doGetObjectFromFactoryBean(
|
||||
final FactoryBean<?> factory, final String beanName, final boolean shouldPostProcess)
|
||||
throws BeanCreationException {
|
||||
|
||||
Object object;
|
||||
@@ -175,12 +151,23 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
|
||||
}
|
||||
|
||||
|
||||
// Do not accept a null value for a FactoryBean that's not fully
|
||||
// initialized yet: Many FactoryBeans just return null then.
|
||||
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
|
||||
throw new BeanCurrentlyInCreationException(
|
||||
beanName, "FactoryBean which is currently in creation returned null from getObject");
|
||||
}
|
||||
|
||||
if (object != null && shouldPostProcess) {
|
||||
try {
|
||||
object = postProcessObjectFromFactoryBean(object, beanName);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
+2
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,12 +89,7 @@ public class GenericBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("Generic bean");
|
||||
if (this.parentName != null) {
|
||||
sb.append(" with parent '").append(this.parentName).append("'");
|
||||
}
|
||||
sb.append(": ").append(super.toString());
|
||||
return sb.toString();
|
||||
return "Generic bean: " + super.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -106,10 +106,12 @@ public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandid
|
||||
}
|
||||
}
|
||||
}
|
||||
if (targetType == null || (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics())) {
|
||||
if (targetType == null) {
|
||||
return true;
|
||||
}
|
||||
// Full check for complex generic type match...
|
||||
if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) {
|
||||
return descriptor.getDependencyType().isAssignableFrom(targetType.getRawClass());
|
||||
}
|
||||
return dependencyType.isAssignableFrom(targetType);
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,9 +37,10 @@ public class LookupOverride extends MethodOverride {
|
||||
|
||||
/**
|
||||
* Construct a new LookupOverride.
|
||||
* @param methodName the name of the method to override
|
||||
* @param beanName the name of the bean in the current BeanFactory
|
||||
* that the overridden method should return
|
||||
* @param methodName the name of the method to override.
|
||||
* This method must have no arguments.
|
||||
* @param beanName name of the bean in the current BeanFactory
|
||||
* that the overriden method should return
|
||||
*/
|
||||
public LookupOverride(String methodName, String beanName) {
|
||||
super(methodName);
|
||||
@@ -47,7 +48,6 @@ public class LookupOverride extends MethodOverride {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the bean that should be returned by this method.
|
||||
*/
|
||||
@@ -55,8 +55,9 @@ public class LookupOverride extends MethodOverride {
|
||||
return this.beanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Match the method of the given name, with no parameters.
|
||||
* Match method of the given name, with no parameters.
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Method method) {
|
||||
@@ -64,6 +65,11 @@ public class LookupOverride extends MethodOverride {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof LookupOverride && super.equals(other) &&
|
||||
@@ -75,9 +81,4 @@ public class LookupOverride extends MethodOverride {
|
||||
return (29 * super.hashCode() + ObjectUtils.nullSafeHashCode(this.beanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LookupOverride for method '" + getMethodName() + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,15 +23,14 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Object representing the override of a method on a managed object by the IoC
|
||||
* container.
|
||||
* Object representing the override of a method on a managed
|
||||
* object by the IoC container.
|
||||
*
|
||||
* <p>Note that the override mechanism is <em>not</em> intended as a generic
|
||||
* means of inserting crosscutting code: use AOP for that.
|
||||
* <p>Note that the override mechanism is <i>not</i> intended as a
|
||||
* generic means of inserting crosscutting code: use AOP for that.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.1
|
||||
*/
|
||||
public abstract class MethodOverride implements BeanMetadataElement {
|
||||
@@ -52,7 +51,6 @@ public abstract class MethodOverride implements BeanMetadataElement {
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the method to be overridden.
|
||||
*/
|
||||
@@ -61,18 +59,17 @@ public abstract class MethodOverride implements BeanMetadataElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the overridden method is <em>overloaded</em> (i.e., whether argument
|
||||
* type matching needs to occur to disambiguate methods of the same name).
|
||||
* <p>Default is {@code true}; can be switched to {@code false} to optimize
|
||||
* runtime performance.
|
||||
* Set whether the overridden method has to be considered as overloaded
|
||||
* (that is, whether arg type matching has to happen).
|
||||
* <p>Default is "true"; can be switched to "false" to optimize runtime performance.
|
||||
*/
|
||||
protected void setOverloaded(boolean overloaded) {
|
||||
this.overloaded = overloaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the overridden method is <em>overloaded</em> (i.e., whether argument
|
||||
* type matching needs to occur to disambiguate methods of the same name).
|
||||
* Return whether the overridden method has to be considered as overloaded
|
||||
* (that is, whether arg type matching has to happen).
|
||||
*/
|
||||
protected boolean isOverloaded() {
|
||||
return this.overloaded;
|
||||
@@ -91,10 +88,11 @@ public abstract class MethodOverride implements BeanMetadataElement {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must override this to indicate whether they <em>match</em> the
|
||||
* given method. This allows for argument list checking as well as method
|
||||
* name checking.
|
||||
* Subclasses must override this to indicate whether they match
|
||||
* the given method. This allows for argument list checking
|
||||
* as well as method name checking.
|
||||
* @param method the method to check
|
||||
* @return whether this override matches the given method
|
||||
*/
|
||||
@@ -111,6 +109,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
|
||||
}
|
||||
MethodOverride that = (MethodOverride) other;
|
||||
return (ObjectUtils.nullSafeEquals(this.methodName, that.methodName) &&
|
||||
this.overloaded == that.overloaded &&
|
||||
ObjectUtils.nullSafeEquals(this.source, that.source));
|
||||
}
|
||||
|
||||
@@ -118,6 +117,7 @@ public abstract class MethodOverride implements BeanMetadataElement {
|
||||
public int hashCode() {
|
||||
int hashCode = ObjectUtils.nullSafeHashCode(this.methodName);
|
||||
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.source);
|
||||
hashCode = 29 * hashCode + (this.overloaded ? 1 : 0);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
|
||||
+15
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,6 @@ public class ReplaceOverride extends MethodOverride {
|
||||
this.methodReplacerBeanName = methodReplacerBeanName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the bean implementing MethodReplacer.
|
||||
*/
|
||||
@@ -69,22 +68,28 @@ public class ReplaceOverride extends MethodOverride {
|
||||
this.typeIdentifiers.add(identifier);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method) {
|
||||
// TODO could cache result for efficiency
|
||||
if (!method.getName().equals(getMethodName())) {
|
||||
// It can't match.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isOverloaded()) {
|
||||
// Not overloaded: don't worry about arg type matching...
|
||||
// No overloaded: don't worry about arg type matching.
|
||||
return true;
|
||||
}
|
||||
// If we get here, we need to insist on precise argument matching...
|
||||
|
||||
// If we get to here, we need to insist on precise argument matching.
|
||||
if (this.typeIdentifiers.size() != method.getParameterTypes().length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < this.typeIdentifiers.size(); i++) {
|
||||
String identifier = this.typeIdentifiers.get(i);
|
||||
if (!method.getParameterTypes()[i].getName().contains(identifier)) {
|
||||
// This parameter cannot match.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -92,6 +97,12 @@ public class ReplaceOverride extends MethodOverride {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Replace override for method '" + getMethodName() + "; will call bean '" +
|
||||
this.methodReplacerBeanName + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ReplaceOverride) || !super.equals(other)) {
|
||||
@@ -110,9 +121,4 @@ public class ReplaceOverride extends MethodOverride {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Replace override for method '" + getMethodName() + "'";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -133,7 +133,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||
public Object getBean(String name, Object... args) throws BeansException {
|
||||
if (args != null) {
|
||||
throw new UnsupportedOperationException(
|
||||
"StaticListableBeanFactory does not support explicit bean creation arguments");
|
||||
"StaticListableBeanFactory does not support explicit bean creation arguments)");
|
||||
}
|
||||
return getBean(name);
|
||||
}
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ public abstract class AbstractSimpleBeanDefinitionParser extends AbstractSingleB
|
||||
*/
|
||||
protected boolean isEligibleAttribute(Attr attribute, ParserContext parserContext) {
|
||||
boolean eligible = isEligibleAttribute(attribute);
|
||||
if (!eligible) {
|
||||
if(!eligible) {
|
||||
String fullName = attribute.getName();
|
||||
eligible = (!fullName.equals("xmlns") && !fullName.startsWith("xmlns:") &&
|
||||
isEligibleAttribute(parserContext.getDelegate().getLocalName(attribute)));
|
||||
|
||||
+14
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,22 +13,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.xml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Simple {@code NamespaceHandler} implementation that maps custom
|
||||
@@ -36,7 +34,8 @@ import org.springframework.util.StringUtils;
|
||||
* that this {@code NamespaceHandler} does not have a corresponding schema
|
||||
* since there is no way to know in advance all possible attribute names.
|
||||
*
|
||||
* <p>An example of the usage of this {@code NamespaceHandler} is shown below:
|
||||
* <p>
|
||||
* An example of the usage of this {@code NamespaceHandler} is shown below:
|
||||
*
|
||||
* <pre class="code">
|
||||
* <bean id="author" class="..TestBean" c:name="Enescu" c:work-ref="compositions"/>
|
||||
@@ -52,17 +51,14 @@ import org.springframework.util.StringUtils;
|
||||
* support for indexes or types. Further more, the names are used as hints by
|
||||
* the container which, by default, does type introspection.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @since 3.1
|
||||
* @see SimplePropertyNamespaceHandler
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
|
||||
|
||||
private static final String REF_SUFFIX = "-ref";
|
||||
|
||||
private static final String DELIMITER_PREFIX = "_";
|
||||
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
}
|
||||
@@ -106,8 +102,7 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
|
||||
int index = -1;
|
||||
try {
|
||||
index = Integer.parseInt(arg);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
} catch (NumberFormatException ex) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Constructor argument '" + argName + "' specifies an invalid integer", attr);
|
||||
}
|
||||
@@ -141,8 +136,11 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
|
||||
}
|
||||
|
||||
private boolean containsArgWithName(String name, ConstructorArgumentValues cvs) {
|
||||
return (checkName(name, cvs.getGenericArgumentValues()) ||
|
||||
checkName(name, cvs.getIndexedArgumentValues().values()));
|
||||
if (!checkName(name, cvs.getGenericArgumentValues())) {
|
||||
return checkName(name, cvs.getIndexedArgumentValues().values());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean checkName(String name, Collection<ValueHolder> values) {
|
||||
@@ -153,5 +151,4 @@ public class SimpleConstructorNamespaceHandler implements NamespaceHandler {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.springframework.beans.propertyeditors;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link java.beans.PropertyEditor} implementation for
|
||||
* {@link java.util.ResourceBundle ResourceBundles}.
|
||||
@@ -87,8 +87,7 @@ public class ResourceBundleEditor extends PropertyEditorSupport {
|
||||
int indexOfBaseNameSeparator = rawBaseName.indexOf(BASE_NAME_SEPARATOR);
|
||||
if (indexOfBaseNameSeparator == -1) {
|
||||
bundle = ResourceBundle.getBundle(rawBaseName);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// it potentially has locale information
|
||||
String baseName = rawBaseName.substring(0, indexOfBaseNameSeparator);
|
||||
if (!StringUtils.hasText(baseName)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
@@ -39,8 +40,6 @@ import org.springframework.tests.sample.beans.GenericIntegerBean;
|
||||
import org.springframework.tests.sample.beans.GenericSetOfIntegerBean;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -486,29 +485,6 @@ public class BeanWrapperGenericsTests {
|
||||
assertEquals(new Long(10), bean.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUntypedPropertyWithMapAtRuntime() {
|
||||
class Holder<D> {
|
||||
private final D data;
|
||||
public Holder(D data) {
|
||||
this.data = data;
|
||||
}
|
||||
public D getData() {
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
data.put("x", "y");
|
||||
Holder<Map<String, Object>> context = new Holder<Map<String,Object>>(data);
|
||||
|
||||
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(context);
|
||||
assertEquals("y", bw.getPropertyValue("data['x']"));
|
||||
|
||||
bw.setPropertyValue("data['message']", "it works!");
|
||||
assertEquals(data.get("message"), "it works!");
|
||||
}
|
||||
|
||||
|
||||
private static abstract class BaseGenericCollectionBean {
|
||||
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
<bean id="bean1" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
|
||||
<constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1"/>
|
||||
<property name="instanceName" value="beanImpl1"/>
|
||||
</bean>
|
||||
|
||||
<bean id="beanImpl1" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl1">
|
||||
<property name="impl2" ref="bean2"/>
|
||||
</bean>
|
||||
|
||||
<bean id="bean2" class="org.springframework.beans.factory.FactoryBeanTests$PassThroughFactoryBean" primary="true">
|
||||
<constructor-arg value="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2"/>
|
||||
<property name="instanceName" value="beanImpl2"/>
|
||||
</bean>
|
||||
|
||||
<bean id="beanImpl2" class="org.springframework.beans.factory.FactoryBeanTests$BeanImpl2">
|
||||
<property name="impl1" ref="bean1"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
+5
-135
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,24 +16,19 @@
|
||||
|
||||
package org.springframework.beans.factory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.springframework.tests.TestResourceUtils.qualifiedResource;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.tests.TestResourceUtils.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -45,7 +40,6 @@ public final class FactoryBeanTests {
|
||||
private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");
|
||||
private static final Resource WITH_AUTOWIRING_CONTEXT = qualifiedResource(CLASS, "withAutowiring.xml");
|
||||
private static final Resource ABSTRACT_CONTEXT = qualifiedResource(CLASS, "abstract.xml");
|
||||
private static final Resource CIRCULAR_CONTEXT = qualifiedResource(CLASS, "circular.xml");
|
||||
|
||||
@Test
|
||||
public void testFactoryBeanReturnsNull() throws Exception {
|
||||
@@ -102,23 +96,6 @@ public final class FactoryBeanTests {
|
||||
factory.getBeansOfType(AbstractFactoryBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularReferenceWithPostProcessor() {
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(factory).loadBeanDefinitions(CIRCULAR_CONTEXT);
|
||||
|
||||
CountingPostProcessor counter = new CountingPostProcessor();
|
||||
factory.addBeanPostProcessor(counter);
|
||||
|
||||
BeanImpl1 impl1 = factory.getBean(BeanImpl1.class);
|
||||
assertNotNull(impl1);
|
||||
assertNotNull(impl1.getImpl2());
|
||||
assertNotNull(impl1.getImpl2());
|
||||
assertSame(impl1, impl1.getImpl2().getImpl1());
|
||||
assertEquals(1, counter.getCount("bean1"));
|
||||
assertEquals(1, counter.getCount("bean2"));
|
||||
}
|
||||
|
||||
|
||||
public static class NullReturningFactoryBean implements FactoryBean<Object> {
|
||||
|
||||
@@ -216,114 +193,7 @@ public final class FactoryBeanTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public abstract static class AbstractFactoryBean implements FactoryBean<Object> {
|
||||
}
|
||||
|
||||
|
||||
public static class PassThroughFactoryBean<T> implements FactoryBean<T>, BeanFactoryAware {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private String instanceName;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private T instance;
|
||||
|
||||
public PassThroughFactoryBean(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setInstanceName(String instanceName) {
|
||||
this.instanceName = instanceName;
|
||||
}
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T getObject() {
|
||||
if (instance == null) {
|
||||
instance = beanFactory.getBean(instanceName, type);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class CountingPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final Map<String, AtomicInteger> count = new HashMap<String, AtomicInteger>();
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof FactoryBean) {
|
||||
return bean;
|
||||
}
|
||||
AtomicInteger c = count.get(beanName);
|
||||
if (c == null) {
|
||||
c = new AtomicInteger(0);
|
||||
count.put(beanName, c);
|
||||
}
|
||||
c.incrementAndGet();
|
||||
return bean;
|
||||
}
|
||||
|
||||
public int getCount(String beanName) {
|
||||
AtomicInteger c = count.get(beanName);
|
||||
if (c != null) {
|
||||
return c.intValue();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class BeanImpl1 {
|
||||
|
||||
private BeanImpl2 impl2;
|
||||
|
||||
public BeanImpl2 getImpl2() {
|
||||
return impl2;
|
||||
}
|
||||
|
||||
public void setImpl2(BeanImpl2 impl2) {
|
||||
this.impl2 = impl2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class BeanImpl2 {
|
||||
|
||||
private BeanImpl1 impl1;
|
||||
|
||||
public BeanImpl1 getImpl1() {
|
||||
return impl1;
|
||||
}
|
||||
|
||||
public void setImpl1(BeanImpl1 impl1) {
|
||||
this.impl1 = impl1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-165
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1647,75 +1647,6 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
assertSame(ngr, bean.integerRepositoryMap.get("simpleRepo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedInjectionIntoMatchingTypeVariable() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(GenericInterface1Impl.class);
|
||||
bd.setFactoryMethodName("create");
|
||||
bf.registerBeanDefinition("bean1", bd);
|
||||
bf.registerBeanDefinition("bean2", new RootBeanDefinition(GenericInterface2Impl.class));
|
||||
|
||||
GenericInterface1Impl bean1 = (GenericInterface1Impl) bf.getBean("bean1");
|
||||
GenericInterface2Impl bean2 = (GenericInterface2Impl) bf.getBean("bean2");
|
||||
assertSame(bean2, bean1.gi2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedInjectionIntoUnresolvedTypeVariable() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(GenericInterface1Impl.class);
|
||||
bd.setFactoryMethodName("createPlain");
|
||||
bf.registerBeanDefinition("bean1", bd);
|
||||
bf.registerBeanDefinition("bean2", new RootBeanDefinition(GenericInterface2Impl.class));
|
||||
|
||||
GenericInterface1Impl bean1 = (GenericInterface1Impl) bf.getBean("bean1");
|
||||
GenericInterface2Impl bean2 = (GenericInterface2Impl) bf.getBean("bean2");
|
||||
assertSame(bean2, bean1.gi2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericsBasedInjectionIntoTypeVariableSelectingBestMatch() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
RootBeanDefinition bd = new RootBeanDefinition(GenericInterface1Impl.class);
|
||||
bd.setFactoryMethodName("create");
|
||||
bf.registerBeanDefinition("bean1", bd);
|
||||
bf.registerBeanDefinition("bean2", new RootBeanDefinition(GenericInterface2Impl.class));
|
||||
bf.registerBeanDefinition("bean2a", new RootBeanDefinition(ReallyGenericInterface2Impl.class));
|
||||
bf.registerBeanDefinition("bean2b", new RootBeanDefinition(PlainGenericInterface2Impl.class));
|
||||
|
||||
GenericInterface1Impl bean1 = (GenericInterface1Impl) bf.getBean("bean1");
|
||||
GenericInterface2Impl bean2 = (GenericInterface2Impl) bf.getBean("bean2");
|
||||
assertSame(bean2, bean1.gi2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCircularTypeReference() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
bpp.setBeanFactory(bf);
|
||||
bf.addBeanPostProcessor(bpp);
|
||||
bf.registerBeanDefinition("bean1", new RootBeanDefinition(StockServiceImpl.class));
|
||||
bf.registerBeanDefinition("bean2", new RootBeanDefinition(StockMovementDaoImpl.class));
|
||||
bf.registerBeanDefinition("bean3", new RootBeanDefinition(StockMovementImpl.class));
|
||||
bf.registerBeanDefinition("bean4", new RootBeanDefinition(StockMovementInstructionImpl.class));
|
||||
|
||||
StockServiceImpl service = bf.getBean(StockServiceImpl.class);
|
||||
assertSame(bf.getBean(StockMovementDaoImpl.class), service.stockMovementDao);
|
||||
}
|
||||
|
||||
|
||||
public static class ResourceInjectionBean {
|
||||
|
||||
@@ -2593,7 +2524,7 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createMock(Class<T> toMock) {
|
||||
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[] {toMock},
|
||||
return (T) Proxy.newProxyInstance(AutowiredAnnotationBeanPostProcessorTests.class.getClassLoader(), new Class<?>[]{toMock},
|
||||
new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
@@ -2603,98 +2534,4 @@ public class AutowiredAnnotationBeanPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface GenericInterface1<T> {
|
||||
|
||||
public String doSomethingGeneric(T o);
|
||||
}
|
||||
|
||||
|
||||
public static class GenericInterface1Impl<T> implements GenericInterface1<T>{
|
||||
|
||||
@Autowired
|
||||
private GenericInterface2<T> gi2;
|
||||
|
||||
@Override
|
||||
public String doSomethingGeneric(T o) {
|
||||
return gi2.doSomethingMoreGeneric(o) + "_somethingGeneric_" + o;
|
||||
}
|
||||
|
||||
public static GenericInterface1<String> create() {
|
||||
return new StringGenericInterface1Impl();
|
||||
}
|
||||
|
||||
public static GenericInterface1 createPlain() {
|
||||
return new GenericInterface1Impl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class StringGenericInterface1Impl extends GenericInterface1Impl<String> {
|
||||
}
|
||||
|
||||
|
||||
public interface GenericInterface2<K> {
|
||||
|
||||
public String doSomethingMoreGeneric(K o);
|
||||
}
|
||||
|
||||
|
||||
public static class GenericInterface2Impl implements GenericInterface2<String> {
|
||||
|
||||
@Override
|
||||
public String doSomethingMoreGeneric(String o) {
|
||||
return "somethingMoreGeneric_" + o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ReallyGenericInterface2Impl implements GenericInterface2<Object> {
|
||||
|
||||
@Override
|
||||
public String doSomethingMoreGeneric(Object o) {
|
||||
return "somethingMoreGeneric_" + o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class PlainGenericInterface2Impl implements GenericInterface2 {
|
||||
|
||||
@Override
|
||||
public String doSomethingMoreGeneric(Object o) {
|
||||
return "somethingMoreGeneric_" + o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface StockMovement<P extends StockMovementInstruction> {
|
||||
}
|
||||
|
||||
|
||||
public interface StockMovementInstruction<C extends StockMovement> {
|
||||
}
|
||||
|
||||
|
||||
public interface StockMovementDao<S extends StockMovement> {
|
||||
}
|
||||
|
||||
|
||||
public static class StockMovementImpl<P extends StockMovementInstruction> implements StockMovement<P> {
|
||||
}
|
||||
|
||||
|
||||
public static class StockMovementInstructionImpl<C extends StockMovement> implements StockMovementInstruction<C> {
|
||||
}
|
||||
|
||||
|
||||
public static class StockMovementDaoImpl<E extends StockMovement> implements StockMovementDao<E> {
|
||||
}
|
||||
|
||||
|
||||
public static class StockServiceImpl {
|
||||
|
||||
@Autowired
|
||||
private StockMovementDao<StockMovement> stockMovementDao;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,27 +16,26 @@
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||
import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
|
||||
import org.springframework.util.MethodInvoker;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link MethodInvokingFactoryBean} and {@link MethodInvokingBean}.
|
||||
* Unit tests for {@link MethodInvokingFactoryBean}.
|
||||
*
|
||||
* @author Colin Sampaleanu
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 21.11.2003
|
||||
*/
|
||||
public class MethodInvokingFactoryBeanTests {
|
||||
public final class MethodInvokingFactoryBeanTests {
|
||||
|
||||
@Test
|
||||
public void testParameterValidation() throws Exception {
|
||||
@@ -247,7 +246,7 @@ public class MethodInvokingFactoryBeanTests {
|
||||
mcfb = new MethodInvokingFactoryBean();
|
||||
mcfb.setTargetClass(TestClass1.class);
|
||||
mcfb.setTargetMethod("supertypes");
|
||||
mcfb.setArguments(new Object[] {1, new Object()});
|
||||
mcfb.setArguments(new Object[] {new Integer(1), new Object()});
|
||||
try {
|
||||
mcfb.afterPropertiesSet();
|
||||
mcfb.getObject();
|
||||
@@ -292,7 +291,7 @@ public class MethodInvokingFactoryBeanTests {
|
||||
ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArgument");
|
||||
methodInvoker.setArguments(new Object[] {5});
|
||||
methodInvoker.setArguments(new Object[] {new Integer(5)});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
@@ -306,44 +305,49 @@ public class MethodInvokingFactoryBeanTests {
|
||||
|
||||
@Test
|
||||
public void testInvokeWithIntArguments() throws Exception {
|
||||
MethodInvokingBean methodInvoker = new MethodInvokingBean();
|
||||
ArgumentConvertingMethodInvoker methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new Object[] {new Integer[] {new Integer(5), new Integer(10)}});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
methodInvoker = new MethodInvokingBean();
|
||||
methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new Object[]{new String[]{"5", "10"}});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new Object[] {new String[] {"5", "10"}});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
methodInvoker = new MethodInvokingBean();
|
||||
methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new Integer[] {new Integer(5), new Integer(10)});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
methodInvoker = new MethodInvokingBean();
|
||||
methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new String[]{"5", "10"});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new String[] {"5", "10"});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
methodInvoker = new MethodInvokingBean();
|
||||
methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new Object[]{new Integer[] {5, 10}});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new Object[] {new Integer(5), new Integer(10)});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
|
||||
methodInvoker = new MethodInvokingBean();
|
||||
methodInvoker = new ArgumentConvertingMethodInvoker();
|
||||
methodInvoker.setTargetClass(TestClass1.class);
|
||||
methodInvoker.setTargetMethod("intArguments");
|
||||
methodInvoker.setArguments(new Object[]{"5", "10"});
|
||||
methodInvoker.afterPropertiesSet();
|
||||
methodInvoker.setArguments(new Object[] {"5", "10"});
|
||||
methodInvoker.prepare();
|
||||
methodInvoker.invoke();
|
||||
}
|
||||
|
||||
|
||||
public static class TestClass1 {
|
||||
|
||||
public static int _staticField1;
|
||||
@@ -391,4 +395,5 @@ public class MethodInvokingFactoryBeanTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+20
-58
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,95 +16,62 @@
|
||||
|
||||
package org.springframework.beans.factory.support;
|
||||
|
||||
import org.junit.Test;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@code equals()} and {@code hashCode()} in bean definitions.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class DefinitionMetadataEqualsHashCodeTests {
|
||||
public class DefinitionMetadataEqualsHashCodeTests extends TestCase {
|
||||
|
||||
@Test
|
||||
public void rootBeanDefinition() {
|
||||
@SuppressWarnings("serial")
|
||||
public void testRootBeanDefinitionEqualsAndHashCode() throws Exception {
|
||||
RootBeanDefinition master = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition equal = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition notEqual = new RootBeanDefinition(String.class);
|
||||
RootBeanDefinition subclass = new RootBeanDefinition(TestBean.class) {
|
||||
};
|
||||
RootBeanDefinition subclass = new RootBeanDefinition(TestBean.class) {};
|
||||
setBaseProperties(master);
|
||||
setBaseProperties(equal);
|
||||
setBaseProperties(notEqual);
|
||||
setBaseProperties(subclass);
|
||||
|
||||
assertEqualsAndHashCodeContracts(master, equal, notEqual, subclass);
|
||||
assertEqualsContract(master, equal, notEqual, subclass);
|
||||
assertEquals("Hash code for equal instances should match", master.hashCode(), equal.hashCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.8
|
||||
* @see <a href="https://jira.spring.io/browse/SPR-11420">SPR-11420</a>
|
||||
*/
|
||||
@Test
|
||||
public void rootBeanDefinitionAndMethodOverridesWithDifferentOverloadedValues() {
|
||||
RootBeanDefinition master = new RootBeanDefinition(TestBean.class);
|
||||
RootBeanDefinition equal = new RootBeanDefinition(TestBean.class);
|
||||
|
||||
setBaseProperties(master);
|
||||
setBaseProperties(equal);
|
||||
|
||||
// Simulate AbstractBeanDefinition.validate() which delegates to
|
||||
// AbstractBeanDefinition.prepareMethodOverrides():
|
||||
master.getMethodOverrides().getOverrides().iterator().next().setOverloaded(false);
|
||||
// But do not simulate validation of the 'equal' bean. As a consequence, a method
|
||||
// override in 'equal' will be marked as overloaded, but the corresponding
|
||||
// override in 'master' will not. But... the bean definitions should still be
|
||||
// considered equal.
|
||||
|
||||
assertEquals("Should be equal", master, equal);
|
||||
assertEquals("Hash code for equal instances must match", master.hashCode(), equal.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childBeanDefinition() {
|
||||
@SuppressWarnings("serial")
|
||||
public void testChildBeanDefinitionEqualsAndHashCode() throws Exception {
|
||||
ChildBeanDefinition master = new ChildBeanDefinition("foo");
|
||||
ChildBeanDefinition equal = new ChildBeanDefinition("foo");
|
||||
ChildBeanDefinition notEqual = new ChildBeanDefinition("bar");
|
||||
ChildBeanDefinition subclass = new ChildBeanDefinition("foo") {
|
||||
};
|
||||
ChildBeanDefinition subclass = new ChildBeanDefinition("foo"){};
|
||||
setBaseProperties(master);
|
||||
setBaseProperties(equal);
|
||||
setBaseProperties(notEqual);
|
||||
setBaseProperties(subclass);
|
||||
|
||||
assertEqualsAndHashCodeContracts(master, equal, notEqual, subclass);
|
||||
assertEqualsContract(master, equal, notEqual, subclass);
|
||||
assertEquals("Hash code for equal instances should match", master.hashCode(), equal.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runtimeBeanReference() {
|
||||
public void testRuntimeBeanReference() throws Exception {
|
||||
RuntimeBeanReference master = new RuntimeBeanReference("name");
|
||||
RuntimeBeanReference equal = new RuntimeBeanReference("name");
|
||||
RuntimeBeanReference notEqual = new RuntimeBeanReference("someOtherName");
|
||||
RuntimeBeanReference subclass = new RuntimeBeanReference("name") {
|
||||
};
|
||||
assertEqualsAndHashCodeContracts(master, equal, notEqual, subclass);
|
||||
RuntimeBeanReference subclass = new RuntimeBeanReference("name"){};
|
||||
assertEqualsContract(master, equal, notEqual, subclass);
|
||||
}
|
||||
|
||||
private void setBaseProperties(AbstractBeanDefinition definition) {
|
||||
definition.setAbstract(true);
|
||||
definition.setAttribute("foo", "bar");
|
||||
definition.setAutowireCandidate(false);
|
||||
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
|
||||
// definition.getConstructorArgumentValues().addGenericArgumentValue("foo");
|
||||
//definition.getConstructorArgumentValues().addGenericArgumentValue("foo");
|
||||
definition.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
|
||||
definition.setDependsOn(new String[] { "foo", "bar" });
|
||||
definition.setDependsOn(new String[]{"foo", "bar"});
|
||||
definition.setDestroyMethodName("destroy");
|
||||
definition.setEnforceDestroyMethod(false);
|
||||
definition.setEnforceInitMethod(true);
|
||||
@@ -121,15 +88,10 @@ public class DefinitionMetadataEqualsHashCodeTests {
|
||||
definition.setSource("foo");
|
||||
}
|
||||
|
||||
private void assertEqualsAndHashCodeContracts(Object master, Object equal, Object notEqual, Object subclass) {
|
||||
private void assertEqualsContract(Object master, Object equal, Object notEqual, Object subclass) {
|
||||
assertEquals("Should be equal", master, equal);
|
||||
assertEquals("Hash code for equal instances should match", master.hashCode(), equal.hashCode());
|
||||
|
||||
assertNotEquals("Should not be equal", master, notEqual);
|
||||
assertNotEquals("Hash code for non-equal instances should not match", master.hashCode(), notEqual.hashCode());
|
||||
|
||||
assertFalse("Should not be equal", master.equals(notEqual));
|
||||
assertEquals("Subclass should be equal", master, subclass);
|
||||
assertEquals("Hash code for subclass should match", master.hashCode(), subclass.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
@@ -29,8 +30,6 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
@@ -260,34 +259,6 @@ public class FactoryMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonExistingFactoryMethod() {
|
||||
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
|
||||
try {
|
||||
xbf.getBean("invalidPrototype");
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getMessage().contains("nonExisting(TestBean)"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryMethodArgumentsForNonExistingMethod() {
|
||||
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
|
||||
reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass()));
|
||||
try {
|
||||
xbf.getBean("invalidPrototype", new TestBean());
|
||||
fail("Should have thrown BeanCreationException");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
assertTrue(ex.getMessage().contains("nonExisting(TestBean)"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanSpecifyFactoryMethodArgumentsOnFactoryMethodPrototype() {
|
||||
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
|
||||
@@ -389,9 +360,7 @@ public class FactoryMethodTests {
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MailSession {
|
||||
|
||||
private Properties props;
|
||||
|
||||
private MailSession() {
|
||||
@@ -408,6 +377,6 @@ class MailSession {
|
||||
}
|
||||
|
||||
public Object getProperty(String key) {
|
||||
return this.props.get(key);
|
||||
return props.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
log4j.appender.console=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.console.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} [%c] - %m%n
|
||||
|
||||
log4j.rootCategory=ERROR, console
|
||||
log4j.logger.org.springframework.beans.factory.config.DeprecatedBeanWarnerTests$MyDeprecatedBeanWarner=WARN
|
||||
|
||||
#log4j.logger.org.springframework.beans=TRACE
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.beans.factory.config.DeprecatedBeanWarnerTests$MyDeprecatedBeanWarner">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="error" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
+3
-6
@@ -84,11 +84,6 @@
|
||||
<property name="stringValue"><value>testBeanOnlyPrototypeDISetterString</value></property>
|
||||
</bean>
|
||||
|
||||
<bean id="invalidPrototype" class="org.springframework.beans.factory.xml.FactoryMethods"
|
||||
factory-method="nonExisting" scope="prototype">
|
||||
<constructor-arg><ref local="juergen"/></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="fullPrototype" class="org.springframework.beans.factory.xml.FactoryMethods"
|
||||
factory-method="newInstance" scope="prototype">
|
||||
<constructor-arg type="int"><value>27</value></constructor-arg>
|
||||
@@ -125,7 +120,9 @@
|
||||
<constructor-arg><value type="java.lang.Integer">33</value></constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="instanceFactoryMethodWithoutArgs" factory-bean="instanceFactory" factory-method="defaultInstance"/>
|
||||
<bean id="instanceFactoryMethodWithoutArgs"
|
||||
factory-bean="instanceFactory"
|
||||
factory-method="defaultInstance"/>
|
||||
|
||||
<!-- Unnamed bean with factory-bean declaration -->
|
||||
<bean factory-bean="instanceFactory" factory-method="defaultInstance"/>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -70,7 +70,7 @@ public class EhCacheCache implements Cache {
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Element element = this.cache.get(key);
|
||||
Object value = (element != null ? element.getObjectValue() : null);
|
||||
if (value != null && type != null && !type.isInstance(value)) {
|
||||
if (type != null && !type.isInstance(value)) {
|
||||
throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
|
||||
}
|
||||
return (T) value;
|
||||
|
||||
Vendored
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -89,11 +89,12 @@ public class EhCacheCacheManager extends AbstractTransactionSupportingCacheManag
|
||||
public Cache getCache(String name) {
|
||||
Cache cache = super.getCache(name);
|
||||
if (cache == null) {
|
||||
// Check the EhCache cache again (in case the cache was added at runtime)
|
||||
// check the EhCache cache again
|
||||
// (in case the cache was added at runtime)
|
||||
Ehcache ehcache = getCacheManager().getEhcache(name);
|
||||
if (ehcache != null) {
|
||||
addCache(new EhCacheCache(ehcache));
|
||||
cache = super.getCache(name); // potentially decorated
|
||||
cache = new EhCacheCache(ehcache);
|
||||
addCache(cache);
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,7 +45,7 @@ import org.springframework.core.io.Resource;
|
||||
* also necessary for loading EhCache configuration from a non-default config location.
|
||||
*
|
||||
* <p>Note: As of Spring 4.0, Spring's EhCache support requires EhCache 2.1 or higher.
|
||||
* We strongly recommend the use of EhCache 2.5 or higher.
|
||||
* We recommend the use of EhCache 2.5 or higher.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Dmitriy Kopylenko
|
||||
@@ -132,7 +132,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws CacheException, IOException {
|
||||
public void afterPropertiesSet() throws IOException, CacheException {
|
||||
logger.info("Initializing EhCache CacheManager");
|
||||
InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null);
|
||||
try {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,7 +90,7 @@ public class GuavaCache implements Cache {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Object value = fromStoreValue(this.cache.getIfPresent(key));
|
||||
if (value != null && type != null && !type.isInstance(value)) {
|
||||
if (type != null && !type.isInstance(value)) {
|
||||
throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
|
||||
}
|
||||
return (T) value;
|
||||
|
||||
Vendored
+6
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ package org.springframework.cache.guava;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -30,7 +29,6 @@ import com.google.common.cache.CacheLoader;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link CacheManager} implementation that lazily builds {@link GuavaCache}
|
||||
@@ -47,7 +45,6 @@ import org.springframework.util.ObjectUtils;
|
||||
* <p>Requires Google Guava 12.0 or higher.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
* @since 4.0
|
||||
* @see GuavaCache
|
||||
*/
|
||||
@@ -84,8 +81,6 @@ public class GuavaCacheManager implements CacheManager {
|
||||
* Specify the set of cache names for this CacheManager's 'static' mode.
|
||||
* <p>The number of caches and their names will be fixed after a call to this method,
|
||||
* with no creation of further cache regions at runtime.
|
||||
* <p>Calling this with a {@code null} collection argument resets the
|
||||
* mode to 'dynamic', allowing for further creation of caches again.
|
||||
*/
|
||||
public void setCacheNames(Collection<String> cacheNames) {
|
||||
if (cacheNames != null) {
|
||||
@@ -94,9 +89,6 @@ public class GuavaCacheManager implements CacheManager {
|
||||
}
|
||||
this.dynamic = false;
|
||||
}
|
||||
else {
|
||||
this.dynamic = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +99,7 @@ public class GuavaCacheManager implements CacheManager {
|
||||
*/
|
||||
public void setCacheBuilder(CacheBuilder<Object, Object> cacheBuilder) {
|
||||
Assert.notNull(cacheBuilder, "CacheBuilder must not be null");
|
||||
doSetCacheBuilder(cacheBuilder);
|
||||
this.cacheBuilder = cacheBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +109,7 @@ public class GuavaCacheManager implements CacheManager {
|
||||
* @see com.google.common.cache.CacheBuilder#from(CacheBuilderSpec)
|
||||
*/
|
||||
public void setCacheBuilderSpec(CacheBuilderSpec cacheBuilderSpec) {
|
||||
doSetCacheBuilder(CacheBuilder.from(cacheBuilderSpec));
|
||||
this.cacheBuilder = CacheBuilder.from(cacheBuilderSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +120,7 @@ public class GuavaCacheManager implements CacheManager {
|
||||
* @see com.google.common.cache.CacheBuilder#from(String)
|
||||
*/
|
||||
public void setCacheSpecification(String cacheSpecification) {
|
||||
doSetCacheBuilder(CacheBuilder.from(cacheSpecification));
|
||||
this.cacheBuilder = CacheBuilder.from(cacheSpecification);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,10 +131,7 @@ public class GuavaCacheManager implements CacheManager {
|
||||
* @see com.google.common.cache.LoadingCache
|
||||
*/
|
||||
public void setCacheLoader(CacheLoader<Object, Object> cacheLoader) {
|
||||
if (!ObjectUtils.nullSafeEquals(this.cacheLoader, cacheLoader)) {
|
||||
this.cacheLoader = cacheLoader;
|
||||
refreshKnownCaches();
|
||||
}
|
||||
this.cacheLoader = cacheLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,10 +141,7 @@ public class GuavaCacheManager implements CacheManager {
|
||||
* An internal holder object will be used to store user-level {@code null}s.
|
||||
*/
|
||||
public void setAllowNullValues(boolean allowNullValues) {
|
||||
if (this.allowNullValues != allowNullValues) {
|
||||
this.allowNullValues = allowNullValues;
|
||||
refreshKnownCaches();
|
||||
}
|
||||
this.allowNullValues = allowNullValues;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,20 +196,4 @@ public class GuavaCacheManager implements CacheManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void doSetCacheBuilder(CacheBuilder<Object, Object> cacheBuilder) {
|
||||
if (!ObjectUtils.nullSafeEquals(this.cacheBuilder, cacheBuilder)) {
|
||||
this.cacheBuilder = cacheBuilder;
|
||||
refreshKnownCaches();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the known caches again with the current state of this manager.
|
||||
*/
|
||||
private void refreshKnownCaches() {
|
||||
for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
|
||||
entry.setValue(createGuavaCache(entry.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -84,7 +84,7 @@ public class JCacheCache implements Cache {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Object value = fromStoreValue(this.cache.get(key));
|
||||
if (value != null && type != null && !type.isInstance(value)) {
|
||||
if (type != null && !type.isInstance(value)) {
|
||||
throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
|
||||
}
|
||||
return (T) value;
|
||||
|
||||
Vendored
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -114,8 +114,8 @@ public class JCacheCacheManager extends AbstractTransactionSupportingCacheManage
|
||||
// Check the JCache cache again (in case the cache was added at runtime)
|
||||
javax.cache.Cache<Object, Object> jcache = getCacheManager().getCache(name);
|
||||
if (jcache != null) {
|
||||
addCache(new JCacheCache(jcache, isAllowNullValues()));
|
||||
cache = super.getCache(name); // potentially decorated
|
||||
cache = new JCacheCache(jcache, isAllowNullValues());
|
||||
addCache(cache);
|
||||
}
|
||||
}
|
||||
return cache;
|
||||
|
||||
Vendored
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import java.net.URI;
|
||||
import java.util.Properties;
|
||||
import javax.cache.CacheManager;
|
||||
import javax.cache.Caching;
|
||||
import javax.cache.spi.CachingProvider;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -74,7 +75,8 @@ public class JCacheManagerFactoryBean
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
this.cacheManager = Caching.getCachingProvider().getCacheManager(
|
||||
CachingProvider provider = Caching.getCachingProvider();
|
||||
this.cacheManager = provider.getCacheManager(
|
||||
this.cacheManagerUri, this.beanClassLoader, this.cacheManagerProperties);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -68,7 +68,7 @@ public class TransactionAwareCacheManagerProxy implements CacheManager, Initiali
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
if (this.targetCacheManager == null) {
|
||||
throw new IllegalArgumentException("Property 'targetCacheManager' is required");
|
||||
throw new IllegalStateException("'targetCacheManager' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user