Compare commits

..

1 Commits

Author SHA1 Message Date
Spring Buildmaster 88d3ce96c1 Release version 4.0.1 2014-01-28 12:16:11 -08:00
1107 changed files with 16714 additions and 33945 deletions
+64 -78
View File
@@ -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
+37 -37
View File
@@ -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
View File
@@ -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)
}
}
@@ -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
View File
@@ -1 +1 @@
version=4.0.7.RELEASE
version=4.0.1.RELEASE
Binary file not shown.
+2 -2
View File
@@ -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
View File
@@ -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]);
@@ -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);
}
@@ -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();
}
}
@@ -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;
}
@@ -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;
}
@@ -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)));
}
/**
@@ -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) {
@@ -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
@@ -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;
}
@@ -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) {
@@ -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
@@ -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));
@@ -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);
}
@@ -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;
}
@@ -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("]");
@@ -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.
@@ -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
+28
View File
@@ -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>
@@ -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);
}
@@ -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 &#64;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 &#64;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
@@ -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;
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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 *).*(..));
@@ -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)
@@ -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();
@@ -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;
}
}
@@ -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 {
}
@@ -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();
}
}
@@ -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));
}
@@ -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;
}
/*
@@ -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
@@ -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");
}
}
}
@@ -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;
}
@@ -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;
@@ -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.
@@ -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">
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingBean">
* &lt;property name="staticMethod" value="com.whatever.MyClass.init"/>
* &lt;/bean></pre>
*
* <p>An example of calling an instance method to start some server bean:
*
* <pre class="code">
* &lt;bean id="myStarter" class="org.springframework.beans.factory.config.MethodInvokingBean">
* &lt;property name="targetObject" ref="myServer"/>
* &lt;property name="targetMethod" value="start"/>
* &lt;/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;
}
}
}
@@ -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">
* &lt;bean id="myObject" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="staticMethod" value="com.whatever.MyClassFactory.getInstance"/>
* &lt;property name="staticMethod">&lt;value>com.whatever.MyClassFactory.getInstance&lt;/value>&lt;/property>
* &lt;/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">
* &lt;bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="targetClass" value="java.lang.System"/>
* &lt;property name="targetMethod" value="getProperties"/>
* &lt;property name="targetClass">&lt;value>java.lang.System&lt;/value>&lt;/property>
* &lt;property name="targetMethod">&lt;value>getProperties&lt;/value>&lt;/property>
* &lt;/bean>
*
* &lt;bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
* &lt;property name="targetObject" value="sysProps"/>
* &lt;property name="targetMethod" value="getProperty"/>
* &lt;property name="arguments" value="java.version"/>
* &lt;property name="targetObject">&lt;ref local="sysProps"/>&lt;/property>
* &lt;property name="targetMethod">&lt;value>getProperty&lt;/value>&lt;/property>
* &lt;property name="arguments">
* &lt;list>
* &lt;value>java.version&lt;/value>
* &lt;/list>
* &lt;/property>
* &lt;/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;
}
}
@@ -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")
@@ -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) {
@@ -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
*/
@@ -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;
@@ -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());
}
}
}
@@ -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();
@@ -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.
*/
@@ -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");
}
}
@@ -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;
@@ -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;
}
@@ -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();
}
}
@@ -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);
}
@@ -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() + "'";
}
}
@@ -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;
}
@@ -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() + "'";
}
}
@@ -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);
}
@@ -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)));
@@ -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">
* &lt;bean id=&quot;author&quot; class=&quot;..TestBean&quot; c:name=&quot;Enescu&quot; c:work-ref=&quot;compositions&quot;/&gt;
@@ -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;
}
}
@@ -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 {
@@ -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>
@@ -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;
}
}
}
@@ -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;
}
}
@@ -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 {
}
}
}
@@ -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());
}
}
@@ -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
+24
View File
@@ -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>
@@ -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"/>
@@ -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;
@@ -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;
@@ -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 {
@@ -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;
@@ -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()));
}
}
}
@@ -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;
@@ -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;
@@ -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);
}
@@ -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