mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d6636aab1 |
@@ -1,44 +0,0 @@
|
||||
= Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open
|
||||
and welcoming community, we pledge to respect all people who contribute through reporting
|
||||
issues, posting feature requests, updating documentation, submitting pull requests or
|
||||
patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for
|
||||
everyone, regardless of level of experience, gender, gender identity and expression,
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
|
||||
religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses,
|
||||
without explicit permission
|
||||
* Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments,
|
||||
commits, code, wiki edits, issues, and other contributions that are not aligned to this
|
||||
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
|
||||
that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
|
||||
consistently applying these principles to every aspect of managing this project. Project
|
||||
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
|
||||
from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an
|
||||
individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
||||
contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will
|
||||
be reviewed and investigated and will result in a response that is deemed necessary and
|
||||
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
|
||||
with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
|
||||
http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
|
||||
+14
-16
@@ -6,10 +6,6 @@ to expect from the Spring team when evaluating your submission._
|
||||
_Please refer back to this document as a checklist before issuing any pull
|
||||
request; this will save time for everyone!_
|
||||
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Take Your First Steps
|
||||
|
||||
### Understand the basics
|
||||
@@ -17,15 +13,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
|
||||
Not sure what a pull request is, or how to submit one? Take a look at GitHub's
|
||||
excellent [help documentation][] first.
|
||||
|
||||
### Search Stack Overflow first; discuss if necessary
|
||||
|
||||
If you're unsure why something isn't working or wondering if there is a better
|
||||
way of doing it please check on Stack Overflow first and if necessary start
|
||||
a discussion. This is the official list of
|
||||
[Spring project tags](https://spring.io/questions). In short the issue tracker
|
||||
should be used to report issues and make feature requests.
|
||||
|
||||
### Search JIRA; 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
|
||||
@@ -33,6 +22,14 @@ do not find something similar, please create a new JIRA issue before submitting
|
||||
a pull request unless the change is truly trivial -- for example: typo fixes,
|
||||
removing compiler warnings, etc.
|
||||
|
||||
### Discuss non-trivial contribution ideas with committers
|
||||
|
||||
If you're considering anything more than correcting a typo or fixing a minor
|
||||
bug, please discuss it on the [spring-framework-contrib][] mailing list before
|
||||
submitting a pull request. We're happy to provide guidance, but please spend an
|
||||
hour or two researching the subject on your own, including searching the mailing
|
||||
list for prior discussions.
|
||||
|
||||
### Sign the Individual Contributor License Agreement (ICLA)
|
||||
|
||||
If you have not previously done so, please fill out and submit the
|
||||
@@ -88,14 +85,15 @@ present in the framework.
|
||||
1. Preserve existing formatting; i.e. do not reformat code for its own sake
|
||||
1. Search the codebase using `git grep` and other tools to discover common
|
||||
naming conventions, etc.
|
||||
1. UTF-8 encoding for Java sources
|
||||
1. Latin-1 (ISO-8859-1) encoding for Java sources; use `native2ascii` to convert
|
||||
if necessary
|
||||
|
||||
|
||||
### Add Apache license header to all new classes
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -123,11 +121,11 @@ modified a file in 2015 whose header still reads:
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
Then be sure to update it to 2016 accordingly:
|
||||
Then be sure to update it to 2015 accordingly:
|
||||
|
||||
```java
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
```
|
||||
|
||||
### Use @since tags for newly-added public API types and methods
|
||||
|
||||
@@ -10,10 +10,6 @@ The framework also serves as the foundation for [Spring Integration][], [Spring
|
||||
and the rest of the Spring [family of projects][]. Browse the repositories under
|
||||
the [Spring organization][] on GitHub for a full list.
|
||||
|
||||
## Code of Conduct
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.adoc).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
## Downloading Artifacts
|
||||
See [downloading Spring artifacts][] for Maven repository information. Unable to
|
||||
use Maven or other transitive dependency management tools?
|
||||
|
||||
+225
-211
@@ -10,10 +10,6 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "org.sonarqube" version "1.1"
|
||||
}
|
||||
|
||||
ext {
|
||||
linkHomepage = 'https://projects.spring.io/spring-framework'
|
||||
linkCi = 'https://build.spring.io/browse/SPR'
|
||||
@@ -31,55 +27,57 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.9"
|
||||
ext.caffeineVersion = "2.3.5"
|
||||
ext.aspectjVersion = "1.8.7"
|
||||
ext.eclipselinkVersion = "2.4.2"
|
||||
ext.ehcacheVersion = "2.10.4"
|
||||
ext.ehcacheVersion = "2.10.0"
|
||||
ext.ehcachejcacheVersion = "1.0.1"
|
||||
ext.ehcache3Version = "3.1.4"
|
||||
ext.ejbVersion = "3.0"
|
||||
ext.fileuploadVersion = "1.3.3"
|
||||
ext.ehcache3Version = "3.0.0.m3"
|
||||
ext.ejbApiVersion = "3.0"
|
||||
ext.fileuploadVersion = "1.3.1"
|
||||
ext.freemarkerVersion = "2.3.23"
|
||||
ext.groovyVersion = "2.4.12"
|
||||
ext.gsonVersion = "2.8.2"
|
||||
ext.guavaVersion = "20.0"
|
||||
ext.groovyVersion = "2.4.5"
|
||||
ext.gsonVersion = "2.3.1"
|
||||
ext.guavaVersion = "18.0"
|
||||
ext.hamcrestVersion = "1.3"
|
||||
ext.hibernate3Version = "3.6.10.Final"
|
||||
ext.hibernate4Version = "4.3.11.Final"
|
||||
ext.hibernate5Version = "5.2.10.Final"
|
||||
ext.hibernate5Version = "5.0.2.Final"
|
||||
ext.hibval4Version = "4.3.2.Final"
|
||||
ext.hibval5Version = "5.2.5.Final"
|
||||
ext.hsqldbVersion = "2.3.4"
|
||||
ext.httpasyncVersion = "4.1.3"
|
||||
ext.httpclientVersion = "4.5.3"
|
||||
ext.jackson2Version = "2.8.10"
|
||||
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
|
||||
ext.javamailVersion = "1.5.6"
|
||||
ext.jettyVersion = "9.3.14.v20161028" // as of 9.3.15, Jetty has hard Servlet 3.1 requirement
|
||||
ext.jetty94Version = "9.4.6.v20170531" // for spring-websocket support, optimized for Jetty 9.4
|
||||
ext.jodaVersion = "2.9.9"
|
||||
ext.jrubyVersion = "1.7.27" // JRuby 9000 primarily supported through JSR-223 (StandardScriptFactory)
|
||||
ext.hibval5Version = "5.2.2.Final"
|
||||
ext.hsqldbVersion = "2.3.3"
|
||||
ext.htmlunitVersion = "2.18"
|
||||
ext.httpasyncVersion = "4.1"
|
||||
ext.httpclientVersion = "4.5.1"
|
||||
ext.jackson2Version = "2.6.3"
|
||||
ext.jasperreportsVersion = "6.1.1"
|
||||
ext.javamailVersion = "1.5.4"
|
||||
ext.jettyVersion = "9.3.5.v20151012"
|
||||
ext.jodaVersion = "2.8.2"
|
||||
ext.jrubyVersion = "1.7.22" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
|
||||
ext.jsonassertVersion = "1.2.3"
|
||||
ext.jsonpathVersion = "2.0.0"
|
||||
ext.jtaVersion = "1.2"
|
||||
ext.junitVersion = "4.12"
|
||||
ext.log4jVersion = "1.2.17"
|
||||
ext.nettyVersion = "4.1.16.Final"
|
||||
ext.okhttpVersion = "2.7.5"
|
||||
ext.okhttp3Version = "3.8.1"
|
||||
ext.openjpaVersion = "2.4.2"
|
||||
ext.poiVersion = "3.14"
|
||||
ext.reactorVersion = "2.0.8.RELEASE"
|
||||
ext.romeVersion = "1.7.4"
|
||||
ext.slf4jVersion = "1.7.21"
|
||||
ext.snakeyamlVersion = "1.17"
|
||||
ext.snifferVersion = "1.15"
|
||||
ext.testngVersion = "6.9.10"
|
||||
ext.nettyVersion = "4.0.32.Final"
|
||||
ext.okhttpVersion = "2.5.0"
|
||||
ext.openjpaVersion = "2.4.0"
|
||||
ext.poiVersion = "3.13"
|
||||
ext.protobufVersion = "2.6.1"
|
||||
ext.reactorVersion = "2.0.6.RELEASE"
|
||||
ext.romeVersion = "1.5.1"
|
||||
ext.seleniumVersion = "2.47.1"
|
||||
ext.slf4jVersion = "1.7.12"
|
||||
ext.snakeyamlVersion = "1.16"
|
||||
ext.snifferVersion = "1.14"
|
||||
ext.testngVersion = "6.9.6"
|
||||
ext.tiles2Version = "2.2.2"
|
||||
ext.tiles3Version = "3.0.7"
|
||||
ext.tomcatVersion = "8.5.23"
|
||||
ext.tiles3Version = "3.0.5"
|
||||
ext.tomcatVersion = "8.0.28"
|
||||
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
|
||||
ext.undertowVersion = "1.3.31.Final"
|
||||
ext.undertowVersion = "1.3.0.Final"
|
||||
ext.woodstoxVersion = "5.0.1"
|
||||
ext.xmlunitVersion = "1.6"
|
||||
ext.xstreamVersion = "1.4.9"
|
||||
ext.xstreamVersion = "1.4.8"
|
||||
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
|
||||
@@ -111,13 +109,11 @@ configure(allprojects) { project ->
|
||||
compileJava {
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
options.encoding = 'UTF-8'
|
||||
options.compilerArgs += "-parameters"
|
||||
}
|
||||
|
||||
@@ -134,6 +130,8 @@ configure(allprojects) { project ->
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo.spring.io/libs-release" }
|
||||
maven { url "https://repo.spring.io/milestone" }
|
||||
maven { url "https://repo.spring.io/snapshot" } // reactor 2.0.6 snapshot
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -199,13 +197,13 @@ configure(allprojects) { project ->
|
||||
"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/${ehcacheVersion}",
|
||||
"http://ehcache.org/apidocs/${ehcache3Version}",
|
||||
"http://quartz-scheduler.org/api/2.2.1/",
|
||||
"http://fasterxml.github.io/jackson-core/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-databind/javadoc/2.8/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.8/",
|
||||
"http://ehcache.org/apidocs/",
|
||||
"http://quartz-scheduler.org/api/2.2.0/",
|
||||
"http://fasterxml.github.com/jackson-core/javadoc/2.3.0/",
|
||||
"http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/",
|
||||
"http://fasterxml.github.io/jackson-dataformat-xml/javadoc/2.3.0/",
|
||||
"http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/"
|
||||
] as String[]
|
||||
}
|
||||
@@ -217,12 +215,13 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
configurations {
|
||||
jacoco
|
||||
}
|
||||
|
||||
dependencies {
|
||||
jacoco("org.jacoco:org.jacoco.agent:0.7.5.201505241946:runtime")
|
||||
jacoco("org.jacoco:org.jacoco.agent:0.7.1.201405082137:runtime")
|
||||
}
|
||||
|
||||
gradle.taskGraph.whenReady {taskGraph ->
|
||||
if (taskGraph.hasTask(':sonarqube')) {
|
||||
if (taskGraph.hasTask(':sonarRunner')) {
|
||||
test.jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=org.springframework.*"
|
||||
}
|
||||
}
|
||||
@@ -250,16 +249,16 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
options.links(project.ext.javadocLinks)
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
|
||||
// Suppress warnings due to cross-module @see and @link references.
|
||||
// Note that global 'api' task does display all warnings.
|
||||
// suppress warnings due to cross-module @see and @link references;
|
||||
// note that global 'api' task does display all warnings.
|
||||
logging.captureStandardError LogLevel.INFO
|
||||
logging.captureStandardOutput LogLevel.INFO // suppress "## warnings" message
|
||||
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.
|
||||
// don't include or exclude anything explicitly by default. See SPR-12085.
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar) {
|
||||
@@ -275,7 +274,6 @@ configure(subprojects - project(":spring-build-src")) { subproject ->
|
||||
|
||||
project("spring-build-src") {
|
||||
description = "Exposes gradle buildSrc for IDE support"
|
||||
|
||||
apply plugin: "groovy"
|
||||
|
||||
dependencies {
|
||||
@@ -289,12 +287,12 @@ project("spring-build-src") {
|
||||
project("spring-core") {
|
||||
description = "Spring Core"
|
||||
|
||||
// As of Spring 4.0.3, spring-core includes asm 5.x and repackages cglib 3.2, inlining
|
||||
// both into the spring-core jar. cglib 3.2 itself depends on asm 5.x and is therefore
|
||||
// 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
|
||||
// further transformed by the JarJar task to depend on org.springframework.asm; this
|
||||
// avoids including two different copies of asm unnecessarily.
|
||||
def cglibVersion = "3.2.5"
|
||||
def objenesisVersion = "2.6"
|
||||
def cglibVersion = "3.1"
|
||||
def objenesisVersion = "2.2"
|
||||
|
||||
configurations {
|
||||
jarjar
|
||||
@@ -314,9 +312,9 @@ project("spring-core") {
|
||||
configurations.cglib.each { originalJar ->
|
||||
zipfileset(src: originalJar)
|
||||
}
|
||||
// Repackage net.sf.cglib => org.springframework.cglib
|
||||
// repackage net.sf.cglib => org.springframework.cglib
|
||||
rule(pattern: "net.sf.cglib.**", result: "org.springframework.cglib.@1")
|
||||
// As mentioned above, transform cglib"s internal asm dependencies from
|
||||
// as mentioned above, transform cglib"s internal asm dependencies from
|
||||
// org.objectweb.asm => org.springframework.asm. Doing this counts on the
|
||||
// the fact that Spring and cglib depend on the same version of asm!
|
||||
rule(pattern: "org.objectweb.asm.**", result: "org.springframework.asm.@1")
|
||||
@@ -337,7 +335,7 @@ project("spring-core") {
|
||||
configurations.objenesis.each { originalJar ->
|
||||
zipfileset(src: originalJar)
|
||||
}
|
||||
// Repackage org.objenesis => org.springframework.objenesis
|
||||
// repackage org.objenesis => org.springframework.objenesis
|
||||
rule(pattern: "org.objenesis.**", result: "org.springframework.objenesis.@1")
|
||||
}
|
||||
}
|
||||
@@ -354,17 +352,17 @@ project("spring-core") {
|
||||
compile("commons-logging:commons-logging:1.2")
|
||||
optional("commons-codec:commons-codec:1.10")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("net.sf.jopt-simple:jopt-simple:5.0.3")
|
||||
optional("log4j:log4j:${log4jVersion}")
|
||||
optional("net.sf.jopt-simple:jopt-simple:4.9")
|
||||
optional("log4j:log4j:1.2.17")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:${woodstoxVersion}") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
// Inline repackaged cglib classes directly into spring-core jar
|
||||
// inline repackaged cglib classes directly into the spring-core jar
|
||||
dependsOn cglibRepackJar
|
||||
from(zipTree(cglibRepackJar.archivePath)) {
|
||||
include "org/springframework/cglib/**"
|
||||
@@ -386,14 +384,13 @@ project("spring-beans") {
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("org.yaml:snakeyaml:${snakeyamlVersion}")
|
||||
testCompile("log4j:log4j:${log4jVersion}")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-beans-groovy") {
|
||||
description "Groovy Bean Definitions"
|
||||
|
||||
merge.into = project(":spring-beans")
|
||||
apply plugin: "groovy"
|
||||
|
||||
@@ -402,8 +399,8 @@ project("spring-beans-groovy") {
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
}
|
||||
|
||||
// This module's Java and Groovy sources need to be compiled together.
|
||||
compileJava.enabled = false
|
||||
// this module's Java and Groovy sources need to be compiled together
|
||||
compileJava.enabled=false
|
||||
sourceSets {
|
||||
main {
|
||||
groovy {
|
||||
@@ -426,6 +423,7 @@ project("spring-aop") {
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
compile(files(project(":spring-core").objenesisRepackJar))
|
||||
compile("aopalliance:aopalliance:1.0")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("commons-pool:commons-pool:1.6")
|
||||
optional("org.apache.commons:commons-pool2:2.4.2")
|
||||
@@ -469,74 +467,42 @@ project("spring-instrument-tomcat") {
|
||||
|
||||
project("spring-context") {
|
||||
description = "Spring Context"
|
||||
|
||||
apply plugin: "groovy"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-aop"))
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-expression"))
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").cglibRepackJar))
|
||||
optional(project(":spring-instrument"))
|
||||
optional("javax.inject:javax.inject:1")
|
||||
optional("javax.ejb:ejb-api:${ejbVersion}")
|
||||
optional("javax.ejb:ejb-api:${ejbApiVersion}")
|
||||
optional("javax.enterprise.concurrent:javax.enterprise.concurrent-api:1.0")
|
||||
optional("javax.money:money-api:1.0.1")
|
||||
optional("javax.money:money-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("joda-time:joda-time:${jodaVersion}")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.beanshell:bsh:2.0b5")
|
||||
optional("org.beanshell:bsh:2.0b4")
|
||||
optional("org.jruby:jruby:${jrubyVersion}")
|
||||
testCompile("javax.inject:javax.inject-tck:1")
|
||||
testCompile("org.javamoney:moneta:1.1")
|
||||
testCompile("org.javamoney:moneta:1.0")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("org.apache.commons:commons-pool2:2.4.2")
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-core"))
|
||||
optional("org.codehaus.castor:castor-xml:1.4.1") {
|
||||
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("org.jibx:jibx-run:1.2.6")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("org.ogce:xpp3:1.1.6")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.8") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-messaging") {
|
||||
description = "Spring Messaging"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-context"))
|
||||
optional(project(":spring-oxm"))
|
||||
optional("io.projectreactor:reactor-core:${reactorVersion}")
|
||||
optional("io.projectreactor:reactor-net:${reactorVersion}") {
|
||||
@@ -562,9 +528,10 @@ project("spring-messaging") {
|
||||
}
|
||||
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("io.netty:netty-all:${nettyVersion}")
|
||||
testCompile("commons-dbcp:commons-dbcp:1.4")
|
||||
testCompile("log4j:log4j:${log4jVersion}")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
}
|
||||
@@ -578,13 +545,58 @@ project("spring-tx") {
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-aop"))
|
||||
optional(project(":spring-context")) // for JCA, @EnableTransactionManagement
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
|
||||
optional("javax.resource:connector-api:1.5")
|
||||
optional("javax.ejb:ejb-api:${ejbVersion}")
|
||||
optional("javax.ejb:ejb-api:${ejbApiVersion}")
|
||||
optional("com.ibm.websphere:uow:6.0.2.17")
|
||||
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
testCompile("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
testCompile("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-oxm") {
|
||||
description = "Spring Object/XML Marshalling"
|
||||
apply from: "oxm.gradle"
|
||||
|
||||
compileTestJava {
|
||||
// necessary to avoid java.lang.VerifyError on jibx compilation
|
||||
// see http://jira.codehaus.org/browse/JIBX-465
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
}
|
||||
|
||||
if (!System.getProperty("java.version").contains("1.8.")) {
|
||||
// necessary because castor and xjc tasks cannot find the JDK's compiler on JDK 9
|
||||
compileTestJava.enabled = false
|
||||
}
|
||||
|
||||
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("org.jibx:jibx-run:1.2.6")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("xpp3:xpp3:1.1.4c")
|
||||
testCompile("org.codehaus.jettison:jettison:1.3.7") {
|
||||
exclude group: 'stax', module: 'stax-api'
|
||||
}
|
||||
if (compileTestJava.enabled) {
|
||||
testCompile(files(genCastor.classesDir).builtBy(genCastor))
|
||||
testCompile(files(genJaxb.classesDir).builtBy(genJaxb))
|
||||
testCompile(files(genXmlbeans.classesDir).builtBy(genXmlbeans))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,14 +604,15 @@ project("spring-jms") {
|
||||
description = "Spring JMS"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-aop"))
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-aop"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-messaging"))
|
||||
compile(project(":spring-tx"))
|
||||
provided("javax.jms:jms-api:1.1-rev-1")
|
||||
optional(project(":spring-oxm"))
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
|
||||
optional("javax.resource:connector-api:1.5")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
@@ -615,11 +628,11 @@ project("spring-jdbc") {
|
||||
compile(project(":spring-tx"))
|
||||
optional(project(":spring-context")) // for JndiDataSourceLookup
|
||||
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
|
||||
optional("com.mchange:c3p0:0.9.5.2")
|
||||
optional("com.mchange:c3p0:0.9.5.1")
|
||||
optional("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
optional("com.h2database:h2:1.4.193")
|
||||
optional("org.apache.derby:derby:10.13.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.13.1.1")
|
||||
optional("com.h2database:h2:1.4.190")
|
||||
optional("org.apache.derby:derby:10.12.1.1")
|
||||
optional("org.apache.derby:derbyclient:10.12.1.1")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,17 +640,16 @@ project("spring-context-support") {
|
||||
description = "Spring Context Support"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-jdbc")) // for Quartz support
|
||||
optional(project(":spring-tx")) // for Quartz support
|
||||
optional("javax.mail:javax.mail-api:${javamailVersion}")
|
||||
optional("javax.cache:cache-api:1.0.0")
|
||||
optional("com.google.guava:guava:${guavaVersion}")
|
||||
optional("com.github.ben-manes.caffeine:caffeine:${caffeineVersion}")
|
||||
optional("net.sf.ehcache:ehcache:${ehcacheVersion}")
|
||||
optional("org.quartz-scheduler:quartz:2.2.3")
|
||||
optional("org.quartz-scheduler:quartz:2.2.1")
|
||||
optional("org.codehaus.fabric3.api:commonj:1.1.0")
|
||||
optional("org.apache.velocity:velocity:1.7")
|
||||
optional("org.freemarker:freemarker:${freemarkerVersion}")
|
||||
@@ -658,14 +670,11 @@ project("spring-context-support") {
|
||||
testCompile("org.slf4j:slf4j-api:${slf4jVersion}")
|
||||
testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
|
||||
testRuntime("org.ehcache:jcache:${ehcachejcacheVersion}")
|
||||
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
|
||||
testRuntime("org.terracotta:management-model:2.3.0")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-web") {
|
||||
description = "Spring Web"
|
||||
|
||||
apply plugin: "groovy"
|
||||
|
||||
// Re-generate Protobuf classes from *.proto files and move them in test sources
|
||||
@@ -695,6 +704,7 @@ project("spring-web") {
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("javax.faces:javax.faces-api:2.2")
|
||||
optional("javax.validation:validation-api:1.0.0.GA")
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("com.caucho:hessian:4.0.38")
|
||||
optional("commons-fileupload:commons-fileupload:${fileuploadVersion}")
|
||||
@@ -702,7 +712,6 @@ project("spring-web") {
|
||||
optional("org.apache.httpcomponents:httpasyncclient:${httpasyncVersion}")
|
||||
optional("io.netty:netty-all:${nettyVersion}")
|
||||
optional("com.squareup.okhttp:okhttp:${okhttpVersion}")
|
||||
optional("com.squareup.okhttp3:okhttp:${okhttp3Version}")
|
||||
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
|
||||
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}")
|
||||
optional("com.google.code.gson:gson:${gsonVersion}")
|
||||
@@ -713,9 +722,9 @@ project("spring-web") {
|
||||
optional("org.eclipse.jetty:jetty-server:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet-api"
|
||||
}
|
||||
optional("log4j:log4j:${log4jVersion}")
|
||||
optional("com.google.protobuf:protobuf-java:2.6.1")
|
||||
optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.4")
|
||||
optional("log4j:log4j:1.2.17")
|
||||
optional("com.googlecode.protobuf-java-format:protobuf-java-format:1.2")
|
||||
optional("com.google.protobuf:protobuf-java:${protobufVersion}")
|
||||
optional("javax.mail:javax.mail-api:${javamailVersion}")
|
||||
testCompile(project(":spring-context-support")) // for JafMediaTypeFactory
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
@@ -724,13 +733,58 @@ project("spring-web") {
|
||||
exclude group: "org.apache.taglibs", module: "taglibs-standard-spec"
|
||||
}
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:${jackson2Version}")
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk7:${jackson2Version}")
|
||||
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jackson2Version}")
|
||||
testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:${jackson2Version}")
|
||||
testCompile("com.squareup.okhttp3:mockwebserver:${okhttp3Version}")
|
||||
testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-websocket") {
|
||||
description = "Spring WebSocket"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-web"))
|
||||
optional(project(":spring-messaging"))
|
||||
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}") {
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
|
||||
}
|
||||
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
|
||||
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-server:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-client:${jettyVersion}")
|
||||
optional("org.eclipse.jetty:jetty-client:${jettyVersion}")
|
||||
optional("io.undertow:undertow-core:${undertowVersion}")
|
||||
optional("io.undertow:undertow-servlet:${undertowVersion}") {
|
||||
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:${undertowVersion}") {
|
||||
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_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("io.projectreactor:reactor-net:${reactorVersion}")
|
||||
testCompile("io.netty:netty-all:${nettyVersion}")
|
||||
testCompile("log4j:log4j:1.2.17")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-orm") {
|
||||
description = "Spring Object/Relational Mapping"
|
||||
|
||||
@@ -742,6 +796,7 @@ project("spring-orm") {
|
||||
optional(project(":spring-aop"))
|
||||
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}") {
|
||||
@@ -782,6 +837,7 @@ 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")
|
||||
testCompile("javax.validation:validation-api:1.1.0.GA")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
|
||||
testCompile("javax.el:javax.el-api:2.2.5")
|
||||
@@ -798,8 +854,9 @@ project("spring-orm-hibernate5") {
|
||||
provided(project(":spring-tx"))
|
||||
optional(project(":spring-web"))
|
||||
optional("org.hibernate:hibernate-core:${hibernate5Version}")
|
||||
optional("org.hibernate:hibernate-entitymanager:${hibernate5Version}")
|
||||
optional("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("javax.transaction:javax.transaction-api:${jtaVersion}")
|
||||
optional("aopalliance:aopalliance:1.0")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,14 +864,13 @@ project("spring-webmvc") {
|
||||
description = "Spring Web MVC"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-aop"))
|
||||
compile(project(":spring-beans"))
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-core"))
|
||||
compile(files(project(":spring-core").objenesisRepackJar))
|
||||
compile(project(":spring-expression"))
|
||||
compile(project(":spring-web"))
|
||||
provided("javax.servlet:javax.servlet-api:3.1.0")
|
||||
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")
|
||||
@@ -856,7 +912,9 @@ project("spring-webmvc") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
exclude group: "org.springframework", module: "spring-web"
|
||||
}
|
||||
optional('org.webjars:webjars-locator:0.32-1')
|
||||
optional('org.webjars:webjars-locator:0.28')
|
||||
testCompile(project(":spring-aop"))
|
||||
testCompile("rhino:js:1.7R1")
|
||||
testCompile("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
testCompile("dom4j:dom4j:1.6.1") {
|
||||
exclude group: "xml-apis", module: "xml-apis"
|
||||
@@ -876,13 +934,12 @@ project("spring-webmvc") {
|
||||
testCompile("org.hibernate:hibernate-validator:${hibval4Version}")
|
||||
testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
|
||||
testCompile("commons-fileupload:commons-fileupload:${fileuploadVersion}")
|
||||
testCompile("commons-io:commons-io:1.4")
|
||||
testCompile("commons-io:commons-io:1.3")
|
||||
testCompile("joda-time:joda-time:${jodaVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.mozilla:rhino:1.7.7.2")
|
||||
testRuntime("org.jruby:jruby:${jrubyVersion}")
|
||||
testRuntime("org.python:jython-standalone:2.5.3")
|
||||
testRuntime("org.webjars:underscorejs:1.8.3")
|
||||
testCompile("org.jruby:jruby:${jrubyVersion}")
|
||||
testCompile("org.python:jython-standalone:2.5.3")
|
||||
testCompile("org.webjars:underscorejs:1.8.3")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,66 +990,19 @@ project("spring-webmvc-portlet") {
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-websocket") {
|
||||
description = "Spring WebSocket"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-context"))
|
||||
compile(project(":spring-core"))
|
||||
compile(project(":spring-web"))
|
||||
optional(project(":spring-messaging"))
|
||||
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}") {
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-websocket-api"
|
||||
exclude group: "org.apache.tomcat", module: "tomcat-servlet-api"
|
||||
}
|
||||
optional("org.glassfish.tyrus:tyrus-spi:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-core:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-server:${tyrusVersion}")
|
||||
optional("org.glassfish.tyrus:tyrus-container-servlet:${tyrusVersion}")
|
||||
optional("org.eclipse.jetty:jetty-webapp:${jettyVersion}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-server:${jetty94Version}") {
|
||||
exclude group: "javax.servlet", module: "javax.servlet"
|
||||
}
|
||||
optional("org.eclipse.jetty.websocket:websocket-client:${jetty94Version}")
|
||||
optional("org.eclipse.jetty:jetty-client:${jetty94Version}")
|
||||
optional("io.undertow:undertow-core:${undertowVersion}")
|
||||
optional("io.undertow:undertow-servlet:${undertowVersion}") {
|
||||
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:${undertowVersion}") {
|
||||
exclude group: "org.jboss.spec.javax.websocket", module: "jboss-websocket-api_1.1_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("io.projectreactor:reactor-net:${reactorVersion}")
|
||||
testCompile("io.netty:netty-all:${nettyVersion}")
|
||||
testCompile("log4j:log4j:${log4jVersion}")
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
project("spring-test") {
|
||||
description = "Spring TestContext Framework"
|
||||
|
||||
dependencies {
|
||||
compile(project(":spring-core"))
|
||||
optional(project(":spring-aop"))
|
||||
optional(project(":spring-beans"))
|
||||
optional(project(":spring-context"))
|
||||
optional(project(":spring-jdbc"))
|
||||
optional(project(":spring-orm"))
|
||||
optional(project(":spring-tx"))
|
||||
optional(project(":spring-orm"))
|
||||
optional(project(":spring-web"))
|
||||
optional(project(":spring-webmvc"))
|
||||
optional(project(":spring-webmvc-portlet"))
|
||||
optional(project(":spring-websocket"))
|
||||
optional("junit:junit:${junitVersion}")
|
||||
optional("org.testng:testng:${testngVersion}")
|
||||
optional("javax.inject:javax.inject:1")
|
||||
@@ -1004,20 +1014,18 @@ project("spring-test") {
|
||||
}
|
||||
optional("javax.portlet:portlet-api:2.0")
|
||||
optional("javax.el:javax.el-api:2.2.5")
|
||||
optional("javax.websocket:javax.websocket-api:1.0")
|
||||
optional("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
|
||||
optional("org.hamcrest:hamcrest-core:${hamcrestVersion}")
|
||||
optional("com.jayway.jsonpath:json-path:${jsonpathVersion}")
|
||||
optional("org.skyscreamer:jsonassert:${jsonassertVersion}")
|
||||
optional("xmlunit:xmlunit:${xmlunitVersion}")
|
||||
optional("net.sourceforge.htmlunit:htmlunit:2.23")
|
||||
optional("org.seleniumhq.selenium:htmlunit-driver:2.23.2")
|
||||
optional("org.seleniumhq.selenium:selenium-java:2.53.1")
|
||||
optional("org.skyscreamer:jsonassert:1.4.0")
|
||||
optional("com.jayway.jsonpath:json-path:2.3.0")
|
||||
optional("net.sourceforge.htmlunit:htmlunit:${htmlunitVersion}")
|
||||
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:${seleniumVersion}")
|
||||
testCompile(project(":spring-context-support"))
|
||||
testCompile(project(":spring-oxm"))
|
||||
testCompile("javax.mail:javax.mail-api:${javamailVersion}")
|
||||
testCompile("javax.ejb:ejb-api:${ejbVersion}")
|
||||
testCompile("javax.ejb:ejb-api:${ejbApiVersion}")
|
||||
testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
|
||||
testCompile("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
|
||||
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
|
||||
@@ -1035,7 +1043,7 @@ project("spring-test") {
|
||||
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
|
||||
testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
|
||||
testCompile("javax.cache:cache-api:1.0.0")
|
||||
testRuntime("log4j:log4j:${log4jVersion}")
|
||||
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
|
||||
}
|
||||
|
||||
task testNG(type: Test) {
|
||||
@@ -1070,8 +1078,8 @@ project("spring-aspects") {
|
||||
|
||||
dependencies {
|
||||
aspects(project(":spring-orm"))
|
||||
ajc("org.aspectj:aspectjtools:${aspectjVersion}")
|
||||
rt("org.aspectj:aspectjrt:${aspectjVersion}")
|
||||
ajc("org.aspectj:aspectjtools:1.9.0.BETA-2") // for the ability to build on JDK 9, not exposed in the POMs yet
|
||||
rt("org.aspectj:aspectjrt:${aspectjVersion}") // regular AspectJ version here, to be exposed in the POMs
|
||||
compile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
provided("org.eclipse.persistence:javax.persistence:2.0.0")
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
@@ -1089,7 +1097,8 @@ project("spring-aspects") {
|
||||
|
||||
eclipse.project {
|
||||
natures += "org.eclipse.ajdt.ui.ajnature"
|
||||
buildCommands = [new org.gradle.plugins.ide.eclipse.model.BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
|
||||
buildCommands = [new org.gradle.plugins.ide.eclipse.model.
|
||||
BuildCommand("org.eclipse.ajdt.core.ajbuilder")]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1128,8 +1137,10 @@ project("spring-framework-bom") {
|
||||
}
|
||||
}
|
||||
|
||||
sonarqube {
|
||||
properties {
|
||||
apply plugin: 'sonar-runner'
|
||||
|
||||
sonarRunner {
|
||||
sonarProperties {
|
||||
property "sonar.projectName", "Spring Framework"
|
||||
property "sonar.profile", "Spring Framework"
|
||||
property "sonar.jacoco.reportPath", "${buildDir.name}/jacoco.exec"
|
||||
@@ -1157,7 +1168,10 @@ configure(rootProject) {
|
||||
separateOutputDirs = false
|
||||
backends = ['docbook']
|
||||
options doctype: 'book', eruby: 'erubis'
|
||||
attributes 'spring-version': project.version, 'revnumber': project.version, 'docinfo': ""
|
||||
attributes 'spring-version': project.version,
|
||||
'javadoc-baseurl' : "http://docs.spring.io/spring/docs/current/javadoc-api",
|
||||
revnumber : project.version,
|
||||
docinfo : ""
|
||||
}
|
||||
|
||||
reference {
|
||||
@@ -1180,7 +1194,7 @@ configure(rootProject) {
|
||||
// don't publish the default jar for the root project
|
||||
configurations.archives.artifacts.clear()
|
||||
|
||||
dependencies { // for integration tests
|
||||
dependencies { // for integration tests
|
||||
testCompile(project(":spring-aop"))
|
||||
testCompile(project(":spring-beans"))
|
||||
testCompile(project(":spring-context"))
|
||||
@@ -1229,11 +1243,11 @@ 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" },
|
||||
// Ensure the javadoc process can resolve types compiled from .aj sources
|
||||
// ensure the javadoc process can resolve types compiled from .aj sources
|
||||
project(":spring-aspects").sourceSets.main.output
|
||||
)
|
||||
classpath += files(subprojects.collect { it.sourceSets.main.compileClasspath })
|
||||
@@ -1293,7 +1307,7 @@ configure(rootProject) {
|
||||
baseName = "spring-framework"
|
||||
classifier = "dist"
|
||||
description = "Builds -${classifier} archive, containing all jars and docs, " +
|
||||
"suitable for community download page."
|
||||
"suitable for community download page."
|
||||
|
||||
ext.baseDir = "${baseName}-${project.version}";
|
||||
|
||||
@@ -1366,7 +1380,7 @@ configure(rootProject) {
|
||||
|
||||
task wrapper(type: Wrapper) {
|
||||
description = "Generates gradlew[.bat] scripts"
|
||||
gradleVersion = "2.14.1"
|
||||
gradleVersion = "2.5"
|
||||
|
||||
doLast() {
|
||||
def gradleOpts = "-XX:MaxMetaspaceSize=1024m -Xmx1024m"
|
||||
@@ -1383,14 +1397,14 @@ configure(rootProject) {
|
||||
}
|
||||
|
||||
configure([project(':spring-build-src'), project(':spring-framework-bom')]) {
|
||||
sonarqube {
|
||||
sonarRunner {
|
||||
skipProject = true
|
||||
}
|
||||
}
|
||||
|
||||
configure(project(':spring-core')) {
|
||||
sonarqube {
|
||||
properties {
|
||||
sonarRunner {
|
||||
sonarProperties {
|
||||
property "sonar.exclusions",
|
||||
"src/main/java/org/springframework/cglib/**/*,src/main/java/org/springframework/asm/**/*"
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=4.3.12.RELEASE
|
||||
version=4.2.2.RELEASE
|
||||
|
||||
@@ -29,8 +29,8 @@ def customizePom(pom, gradleProject) {
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name "Apache License, Version 2.0"
|
||||
url "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
name "The Apache Software License, Version 2.0"
|
||||
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
distribution "repo"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+2
-2
@@ -1,6 +1,6 @@
|
||||
#Wed Aug 17 21:21:18 CEST 2016
|
||||
#Thu Jul 09 16:54:55 EEST 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-bin.zip
|
||||
|
||||
@@ -6,31 +6,13 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
GRADLE_OPTS="-XX:MaxMetaspaceSize=1024m -Xmx1024m $GRADLE_OPTS"
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
@@ -49,7 +31,6 @@ die ( ) {
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
@@ -60,11 +41,31 @@ case "`uname`" in
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -90,7 +91,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
@@ -114,7 +115,6 @@ fi
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
|
||||
Vendored
+5
-5
@@ -8,15 +8,15 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set GRADLE_OPTS=-XX:MaxMetaspaceSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set GRADLE_OPTS=-XX:MaxMetaspaceSize=1024m -Xmx1024m -XX:MaxHeapSize=256m %GRADLE_OPTS%
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
@@ -47,7 +47,7 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
@@ -29,8 +29,8 @@ REM - generates OXM test classes to avoid errors on import into Eclipse
|
||||
REM - generates metadata for all subprojects
|
||||
REM - skips metadata gen for the root project (-x :eclipse) to work
|
||||
REM around Eclipse's inability to import hierarchical project structures
|
||||
REM SET COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
SET COMMAND=gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
|
||||
REM SET COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
SET COMMAND=gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
@@ -69,7 +69,7 @@ echo When the above is complete, return here and press the enter key.
|
||||
|
||||
pause
|
||||
|
||||
set COMMAND=gradlew --no-daemon :eclipse
|
||||
set COMMAND=gradlew :eclipse
|
||||
|
||||
echo.
|
||||
echo -----------------------------------------------------------------------
|
||||
|
||||
@@ -42,7 +42,7 @@ read
|
||||
# - generates metadata for all subprojects
|
||||
# - skips metadata gen for the root project (-x :eclipse) to work
|
||||
# around Eclipse's inability to import hierarchical project structures
|
||||
COMMAND="./gradlew --no-daemon cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
COMMAND="./gradlew cleanEclipse :spring-oxm:compileTestJava eclipse -x :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
@@ -84,7 +84,7 @@ EOM
|
||||
|
||||
read
|
||||
|
||||
COMMAND="./gradlew --no-daemon :eclipse"
|
||||
COMMAND="./gradlew :eclipse"
|
||||
|
||||
cat <<EOM
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.aop;
|
||||
|
||||
/**
|
||||
* Tag interface for Advice. Implementations can be any type
|
||||
* of advice, such as Interceptors.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @version $Id: Advice.java,v 1.1 2004/03/19 17:02:16 johnsonr Exp $
|
||||
*/
|
||||
public interface Advice {
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.aop;
|
||||
|
||||
/**
|
||||
* Superclass for all AOP infrastructure exceptions.
|
||||
* Unchecked, as such exceptions are fatal and end user
|
||||
* code shouldn't be forced to catch them.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Bob Lee
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructor for AspectException.
|
||||
* @param message the exception message
|
||||
*/
|
||||
public AspectException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for AspectException.
|
||||
* @param message the exception message
|
||||
* @param cause the root cause, if any
|
||||
*/
|
||||
public AspectException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* Intercepts the construction of a new object.
|
||||
*
|
||||
* <p>The user should implement the {@link
|
||||
* #construct(ConstructorInvocation)} method to modify the original
|
||||
* behavior. E.g. the following class implements a singleton
|
||||
* interceptor (allows only one unique instance for the intercepted
|
||||
* class):
|
||||
*
|
||||
* <pre class=code>
|
||||
* class DebuggingInterceptor implements ConstructorInterceptor {
|
||||
* Object instance=null;
|
||||
*
|
||||
* Object construct(ConstructorInvocation i) throws Throwable {
|
||||
* if(instance==null) {
|
||||
* return instance=i.proceed();
|
||||
* } else {
|
||||
* throw new Exception("singleton does not allow multiple instance");
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface ConstructorInterceptor extends Interceptor {
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the construction of a new object. Polite implementations
|
||||
* would certainly like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the construction joinpoint
|
||||
* @return the newly created object, which is also the result of
|
||||
* the call to {@link Joinpoint#proceed()}; might be replaced by
|
||||
* the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
*/
|
||||
Object construct(ConstructorInvocation invocation) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* Description of an invocation to a constuctor, given to an
|
||||
* interceptor upon constructor-call.
|
||||
*
|
||||
* <p>A constructor invocation is a joinpoint and can be intercepted
|
||||
* by a constructor interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see ConstructorInterceptor
|
||||
*/
|
||||
public interface ConstructorInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the constructor being called.
|
||||
* <p>This method is a friendly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the constructor being called
|
||||
*/
|
||||
Constructor<?> getConstructor();
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
/**
|
||||
* This interface represents a generic interceptor.
|
||||
*
|
||||
* <p>A generic interceptor can intercept runtime events that occur
|
||||
* within a base program. Those events are materialized by (reified
|
||||
* in) joinpoints. Runtime joinpoints can be invocations, field
|
||||
* access, exceptions...
|
||||
*
|
||||
* <p>This interface is not used directly. Use the sub-interfaces
|
||||
* to intercept specific events. For instance, the following class
|
||||
* implements some specific interceptors in order to implement a
|
||||
* debugger:
|
||||
*
|
||||
* <pre class=code>
|
||||
* class DebuggingInterceptor implements MethodInterceptor,
|
||||
* ConstructorInterceptor, FieldInterceptor {
|
||||
*
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
* debug(i.getMethod(), i.getThis(), i.getArgs());
|
||||
* return i.proceed();
|
||||
* }
|
||||
*
|
||||
* Object construct(ConstructorInvocation i) throws Throwable {
|
||||
* debug(i.getConstructor(), i.getThis(), i.getArgs());
|
||||
* return i.proceed();
|
||||
* }
|
||||
*
|
||||
* Object get(FieldAccess fa) throws Throwable {
|
||||
* debug(fa.getField(), fa.getThis(), null);
|
||||
* return fa.proceed();
|
||||
* }
|
||||
*
|
||||
* Object set(FieldAccess fa) throws Throwable {
|
||||
* debug(fa.getField(), fa.getThis(), fa.getValueToSet());
|
||||
* return fa.proceed();
|
||||
* }
|
||||
*
|
||||
* void debug(AccessibleObject ao, Object this, Object value) {
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Joinpoint
|
||||
*/
|
||||
public interface Interceptor extends Advice {
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* This interface represents an invocation in the program.
|
||||
*
|
||||
* <p>An invocation is a joinpoint and can be intercepted by an
|
||||
* interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface Invocation extends Joinpoint {
|
||||
|
||||
/**
|
||||
* Get the arguments as an array object.
|
||||
* It is possible to change element values within this
|
||||
* array to change the arguments.
|
||||
* @return the argument of the invocation
|
||||
*/
|
||||
Object[] getArguments();
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
|
||||
/**
|
||||
* This interface represents a generic runtime joinpoint (in the AOP
|
||||
* terminology).
|
||||
*
|
||||
* <p>A runtime joinpoint is an <i>event</i> that occurs on a static
|
||||
* joinpoint (i.e. a location in a the program). For instance, an
|
||||
* invocation is the runtime joinpoint on a method (static joinpoint).
|
||||
* The static part of a given joinpoint can be generically retrieved
|
||||
* using the {@link #getStaticPart()} method.
|
||||
*
|
||||
* <p>In the context of an interception framework, a runtime joinpoint
|
||||
* is then the reification of an access to an accessible object (a
|
||||
* method, a constructor, a field), i.e. the static part of the
|
||||
* joinpoint. It is passed to the interceptors that are installed on
|
||||
* the static joinpoint.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see Interceptor
|
||||
*/
|
||||
public interface Joinpoint {
|
||||
|
||||
/**
|
||||
* Proceed to the next interceptor in the chain.
|
||||
* <p>The implementation and the semantics of this method depends
|
||||
* on the actual joinpoint type (see the children interfaces).
|
||||
* @return see the children interfaces' proceed definition
|
||||
* @throws Throwable if the joinpoint throws an exception
|
||||
*/
|
||||
Object proceed() throws Throwable;
|
||||
|
||||
/**
|
||||
* Return the object that holds the current joinpoint's static part.
|
||||
* <p>For instance, the target object for an invocation.
|
||||
* @return the object (can be null if the accessible object is static)
|
||||
*/
|
||||
Object getThis();
|
||||
|
||||
/**
|
||||
* Return the static part of this joinpoint.
|
||||
* <p>The static part is an accessible object on which a chain of
|
||||
* interceptors are installed.
|
||||
*/
|
||||
AccessibleObject getStaticPart();
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
/**
|
||||
* Intercepts calls on an interface on its way to the target. These
|
||||
* are nested "on top" of the target.
|
||||
*
|
||||
* <p>The user should implement the {@link #invoke(MethodInvocation)}
|
||||
* method to modify the original behavior. E.g. the following class
|
||||
* implements a tracing interceptor (traces all the calls on the
|
||||
* intercepted method(s)):
|
||||
*
|
||||
* <pre class=code>
|
||||
* class TracingInterceptor implements MethodInterceptor {
|
||||
* Object invoke(MethodInvocation i) throws Throwable {
|
||||
* System.out.println("method "+i.getMethod()+" is called on "+
|
||||
* i.getThis()+" with args "+i.getArguments());
|
||||
* Object ret=i.proceed();
|
||||
* System.out.println("method "+i.getMethod()+" returns "+ret);
|
||||
* return ret;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface MethodInterceptor extends Interceptor {
|
||||
|
||||
/**
|
||||
* Implement this method to perform extra treatments before and
|
||||
* after the invocation. Polite implementations would certainly
|
||||
* like to invoke {@link Joinpoint#proceed()}.
|
||||
* @param invocation the method invocation joinpoint
|
||||
* @return the result of the call to {@link Joinpoint#proceed()};
|
||||
* might be intercepted by the interceptor
|
||||
* @throws Throwable if the interceptors or the target object
|
||||
* throws an exception
|
||||
*/
|
||||
Object invoke(MethodInvocation invocation) throws Throwable;
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.aopalliance.intercept;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Description of an invocation to a method, given to an interceptor
|
||||
* upon method-call.
|
||||
*
|
||||
* <p>A method invocation is a joinpoint and can be intercepted by a
|
||||
* method interceptor.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @see MethodInterceptor
|
||||
*/
|
||||
public interface MethodInvocation extends Invocation {
|
||||
|
||||
/**
|
||||
* Get the method being called.
|
||||
* <p>This method is a frienly implementation of the
|
||||
* {@link Joinpoint#getStaticPart()} method (same result).
|
||||
* @return the method being called
|
||||
*/
|
||||
Method getMethod();
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -86,7 +86,7 @@ public interface MethodMatcher {
|
||||
* @return whether there's a runtime match
|
||||
* @see MethodMatcher#matches(Method, Class)
|
||||
*/
|
||||
boolean matches(Method method, Class<?> targetClass, Object... args);
|
||||
boolean matches(Method method, Class<?> targetClass, Object[] args);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -57,14 +57,14 @@ public interface ProxyMethodInvocation extends MethodInvocation {
|
||||
* @return an invocable clone of this invocation.
|
||||
* {@code proceed()} can be called once per clone.
|
||||
*/
|
||||
MethodInvocation invocableClone(Object... arguments);
|
||||
MethodInvocation invocableClone(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Set the arguments to be used on subsequent invocations in the any advice
|
||||
* in this chain.
|
||||
* @param arguments the argument array
|
||||
*/
|
||||
void setArguments(Object... arguments);
|
||||
void setArguments(Object[] arguments);
|
||||
|
||||
/**
|
||||
* Add the specified user attribute with the given value to this invocation.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*<
|
||||
* Copyright 2002-2017 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,8 +34,9 @@ public interface TargetSource extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Return the type of targets returned by this {@link TargetSource}.
|
||||
* <p>Can return {@code null}, although certain usages of a {@code TargetSource}
|
||||
* might just work with a predetermined target class.
|
||||
* <p>Can return {@code null}, although certain usages of a
|
||||
* {@code TargetSource} might just work with a predetermined
|
||||
* target class.
|
||||
* @return the type of targets returned by this {@link TargetSource}
|
||||
*/
|
||||
@Override
|
||||
@@ -43,8 +44,9 @@ public interface TargetSource extends TargetClassAware {
|
||||
|
||||
/**
|
||||
* Will all calls to {@link #getTarget()} return the same object?
|
||||
* <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
|
||||
* and the AOP framework can cache the return value of {@link #getTarget()}.
|
||||
* <p>In that case, there will be no need to invoke
|
||||
* {@link #releaseTarget(Object)}, and the AOP framework can cache
|
||||
* the return value of {@link #getTarget()}.
|
||||
* @return {@code true} if the target is immutable
|
||||
* @see #getTarget
|
||||
*/
|
||||
@@ -53,15 +55,14 @@ public interface TargetSource extends TargetClassAware {
|
||||
/**
|
||||
* Return a target instance. Invoked immediately before the
|
||||
* AOP framework calls the "target" of an AOP method invocation.
|
||||
* @return the target object which contains the joinpoint,
|
||||
* or {@code null} if there is no actual target instance
|
||||
* @return the target object, which contains the joinpoint
|
||||
* @throws Exception if the target object can't be resolved
|
||||
*/
|
||||
Object getTarget() throws Exception;
|
||||
|
||||
/**
|
||||
* Release the given target object obtained from the
|
||||
* {@link #getTarget()} method, if any.
|
||||
* {@link #getTarget()} method.
|
||||
* @param target object obtained from a call to {@link #getTarget()}
|
||||
* @throws Exception if the object can't be released
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,14 +29,12 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
|
||||
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
|
||||
|
||||
|
||||
/**
|
||||
* Enforce Singleton pattern.
|
||||
*/
|
||||
private TrueMethodMatcher() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRuntime() {
|
||||
return false;
|
||||
@@ -48,17 +46,11 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// Should never be invoked as isRuntime returns false.
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to support serialization. Replaces with canonical
|
||||
* instance on deserialization, protecting Singleton pattern.
|
||||
@@ -68,4 +60,9 @@ class TrueMethodMatcher implements MethodMatcher, Serializable {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodMatcher.TRUE";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+38
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -58,8 +55,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
|
||||
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation {
|
||||
|
||||
/**
|
||||
* Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint.
|
||||
@@ -90,21 +86,18 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
protected final Method aspectJAdviceMethod;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
protected transient Method aspectJAdviceMethod;
|
||||
/** The total number of arguments we have to populate on advice dispatch */
|
||||
private final int adviceInvocationArgumentCount;
|
||||
|
||||
private final AspectJExpressionPointcut pointcut;
|
||||
|
||||
private final AspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
/**
|
||||
* The name of the aspect (ref bean) in which this advice was defined
|
||||
* (used when determining advice precedence so that we can determine
|
||||
* The name of the aspect (ref bean) in which this advice was defined (used
|
||||
* when determining advice precedence so that we can determine
|
||||
* whether two pieces of advice come from the same aspect).
|
||||
*/
|
||||
private String aspectName;
|
||||
@@ -118,13 +111,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
* This will be non-null if the creator of this advice object knows the argument names
|
||||
* and sets them explicitly
|
||||
*/
|
||||
private String[] argumentNames;
|
||||
private String[] argumentNames = null;
|
||||
|
||||
/** Non-null if after throwing advice binds the thrown value */
|
||||
private String throwingName;
|
||||
private String throwingName = null;
|
||||
|
||||
/** Non-null if after returning advice binds the return value */
|
||||
private String returningName;
|
||||
private String returningName = null;
|
||||
|
||||
private Class<?> discoveredReturningType = Object.class;
|
||||
|
||||
@@ -142,7 +135,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
*/
|
||||
private int joinPointStaticPartArgumentIndex = -1;
|
||||
|
||||
private Map<String, Integer> argumentBindings;
|
||||
private Map<String, Integer> argumentBindings = null;
|
||||
|
||||
private boolean argumentsIntrospected = false;
|
||||
|
||||
@@ -161,10 +154,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {
|
||||
|
||||
Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
|
||||
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
|
||||
this.methodName = aspectJAdviceMethod.getName();
|
||||
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
|
||||
this.aspectJAdviceMethod = aspectJAdviceMethod;
|
||||
this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
this.pointcut = pointcut;
|
||||
this.aspectInstanceFactory = aspectInstanceFactory;
|
||||
}
|
||||
@@ -259,17 +250,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
this.argumentNames[i] + "' that is not a valid Java identifier");
|
||||
}
|
||||
}
|
||||
if (this.argumentNames != null) {
|
||||
if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) {
|
||||
if (argumentNames != null) {
|
||||
if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) {
|
||||
// May need to add implicit join point arg name...
|
||||
Class<?> firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0];
|
||||
Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
|
||||
if (firstArgType == JoinPoint.class ||
|
||||
firstArgType == ProceedingJoinPoint.class ||
|
||||
firstArgType == JoinPoint.StaticPart.class) {
|
||||
String[] oldNames = this.argumentNames;
|
||||
this.argumentNames = new String[oldNames.length + 1];
|
||||
this.argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length);
|
||||
String[] oldNames = argumentNames;
|
||||
argumentNames = new String[oldNames.length + 1];
|
||||
argumentNames[0] = "THIS_JOIN_POINT";
|
||||
System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,8 +286,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Returning name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,8 +320,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Throwing name '" + name +
|
||||
"' is neither a valid argument name nor the fully-qualified " +
|
||||
"name of a Java type on the classpath. Root cause: " + ex);
|
||||
"' is neither a valid argument name nor the fully-qualified name of a Java type on the classpath. " +
|
||||
"Root cause: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,11 +359,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
*/
|
||||
public synchronized final void calculateArgumentBindings() {
|
||||
// The simple case... nothing to bind.
|
||||
if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
|
||||
if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numUnboundArgs = this.parameterTypes.length;
|
||||
int numUnboundArgs = this.adviceInvocationArgumentCount;
|
||||
Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
|
||||
if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
|
||||
numUnboundArgs--;
|
||||
@@ -465,13 +456,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
|
||||
int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
|
||||
if (this.argumentNames.length != numExpectedArgumentNames) {
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
|
||||
" arguments to bind by name in advice, but actually found " +
|
||||
throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames
|
||||
+ " arguments to bind by name in advice, but actually found " +
|
||||
this.argumentNames.length + " arguments.");
|
||||
}
|
||||
|
||||
// So we match in number...
|
||||
int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
|
||||
int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind;
|
||||
for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
|
||||
this.argumentBindings.put(this.argumentNames[i], i);
|
||||
}
|
||||
@@ -480,8 +471,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
// specified, and find the discovered argument types.
|
||||
if (this.returningName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.returningName)) {
|
||||
throw new IllegalStateException("Returning argument name '" + this.returningName +
|
||||
"' was not bound in advice arguments");
|
||||
throw new IllegalStateException("Returning argument name '"
|
||||
+ this.returningName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.returningName);
|
||||
@@ -491,8 +482,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
if (this.throwingName != null) {
|
||||
if (!this.argumentBindings.containsKey(this.throwingName)) {
|
||||
throw new IllegalStateException("Throwing argument name '" + this.throwingName +
|
||||
"' was not bound in advice arguments");
|
||||
throw new IllegalStateException("Throwing argument name '"
|
||||
+ this.throwingName + "' was not bound in advice arguments");
|
||||
}
|
||||
else {
|
||||
Integer index = this.argumentBindings.get(this.throwingName);
|
||||
@@ -552,7 +543,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
calculateArgumentBindings();
|
||||
|
||||
// AMC start
|
||||
Object[] adviceInvocationArgs = new Object[this.parameterTypes.length];
|
||||
Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount];
|
||||
int numBound = 0;
|
||||
|
||||
if (this.joinPointArgumentIndex != -1) {
|
||||
@@ -589,10 +580,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
}
|
||||
}
|
||||
|
||||
if (numBound != this.parameterTypes.length) {
|
||||
throw new IllegalStateException("Required to bind " + this.parameterTypes.length +
|
||||
" arguments, but only bound " + numBound + " (JoinPointMatch " +
|
||||
(jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
|
||||
if (numBound != this.adviceInvocationArgumentCount) {
|
||||
throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount
|
||||
+ " arguments, but only bound " + numBound + " (JoinPointMatch " +
|
||||
(jpMatch == null ? "was NOT" : "WAS") +
|
||||
" bound in invocation)");
|
||||
}
|
||||
|
||||
return adviceInvocationArgs;
|
||||
@@ -673,16 +665,6 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence
|
||||
"aspect name '" + this.aspectName + "'";
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MethodMatcher that excludes the specified advice method.
|
||||
|
||||
+13
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -113,7 +113,6 @@ import org.springframework.util.StringUtils;
|
||||
* returning {@code null} in the case that the parameter names cannot be discovered.
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||
@@ -155,17 +154,23 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
}
|
||||
|
||||
|
||||
/** The pointcut expression associated with the advice, as a simple String */
|
||||
private String pointcutExpression;
|
||||
|
||||
private boolean raiseExceptions;
|
||||
|
||||
/** If the advice is afterReturning, and binds the return value, this is the parameter name used */
|
||||
/**
|
||||
* If the advice is afterReturning, and binds the return value, this is the parameter name used.
|
||||
*/
|
||||
private String returningName;
|
||||
|
||||
/** If the advice is afterThrowing, and binds the thrown value, this is the parameter name used */
|
||||
/**
|
||||
* If the advice is afterThrowing, and binds the thrown value, this is the parameter name used.
|
||||
*/
|
||||
private String throwingName;
|
||||
|
||||
/**
|
||||
* The pointcut expression associated with the advice, as a simple String.
|
||||
*/
|
||||
private String pointcutExpression;
|
||||
|
||||
private Class<?>[] argumentTypes;
|
||||
|
||||
private String[] parameterNameBindings;
|
||||
@@ -181,7 +186,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
this.pointcutExpression = pointcutExpression;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicate whether {@link IllegalArgumentException} and {@link AmbiguousBindingException}
|
||||
* must be thrown as appropriate in the case of failing to deduce advice parameter names.
|
||||
@@ -209,7 +213,6 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
this.throwingName = throwingName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deduce the parameter names for an advice method.
|
||||
* <p>See the {@link AspectJAdviceParameterNameDiscoverer class level javadoc}
|
||||
@@ -471,7 +474,7 @@ public class AspectJAdviceParameterNameDiscoverer implements ParameterNameDiscov
|
||||
* If the token starts meets Java identifier conventions, it's in.
|
||||
*/
|
||||
private String maybeExtractVariableName(String candidateToken) {
|
||||
if (!StringUtils.hasLength(candidateToken)) {
|
||||
if (candidateToken == null || candidateToken.equals("")) {
|
||||
return null;
|
||||
}
|
||||
if (Character.isJavaIdentifierStart(candidateToken.charAt(0)) &&
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
implements MethodInterceptor, AfterAdvice, Serializable {
|
||||
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -40,7 +37,6 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
try {
|
||||
|
||||
+3
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@@ -33,9 +32,7 @@ import org.springframework.util.TypeUtils;
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
implements AfterReturningAdvice, AfterAdvice, Serializable {
|
||||
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice {
|
||||
|
||||
public AspectJAfterReturningAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -43,7 +40,6 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -66,7 +62,6 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Following AspectJ semantics, if a returning clause was specified, then the
|
||||
* advice is only invoked if the returned value is an instance of the given
|
||||
@@ -101,7 +96,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
|
||||
else if (Object.class == type && void.class == method.getReturnType()) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
else{
|
||||
return ClassUtils.isAssignable(type, method.getReturnType());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -30,9 +29,7 @@ import org.springframework.aop.AfterAdvice;
|
||||
* @author Rod Johnson
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
implements MethodInterceptor, AfterAdvice, Serializable {
|
||||
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice {
|
||||
|
||||
public AspectJAfterThrowingAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -40,7 +37,6 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -61,11 +57,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
try {
|
||||
return mi.proceed();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (shouldInvokeOnThrowing(ex)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, ex);
|
||||
catch (Throwable t) {
|
||||
if (shouldInvokeOnThrowing(t)) {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, t);
|
||||
}
|
||||
throw ex;
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +69,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
|
||||
* In AspectJ semantics, after throwing advice that specifies a throwing clause
|
||||
* is only invoked if the thrown exception is a subtype of the given throwing type.
|
||||
*/
|
||||
private boolean shouldInvokeOnThrowing(Throwable ex) {
|
||||
return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
|
||||
private boolean shouldInvokeOnThrowing(Throwable t) {
|
||||
return getDiscoveredThrowingType().isAssignableFrom(t.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
@@ -34,8 +33,7 @@ import org.springframework.aop.ProxyMethodInvocation;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
|
||||
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor {
|
||||
|
||||
public AspectJAroundAdvice(
|
||||
Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -43,7 +41,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
super(aspectJAroundAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBeforeAdvice() {
|
||||
return false;
|
||||
@@ -59,6 +56,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
if (!(mi instanceof ProxyMethodInvocation)) {
|
||||
|
||||
+29
-45
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.weaver.BCException;
|
||||
import org.aspectj.weaver.patterns.NamePattern;
|
||||
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
|
||||
import org.aspectj.weaver.reflect.ShadowMatchImpl;
|
||||
@@ -186,24 +187,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
throw new IllegalStateException("Must set property 'expression' before attempting to match");
|
||||
}
|
||||
if (this.pointcutExpression == null) {
|
||||
this.pointcutClassLoader = determinePointcutClassLoader();
|
||||
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the ClassLoader to use for pointcut evaluation.
|
||||
*/
|
||||
private ClassLoader determinePointcutClassLoader() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
}
|
||||
if (this.pointcutDeclarationScope != null) {
|
||||
return this.pointcutDeclarationScope.getClassLoader();
|
||||
}
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the underlying AspectJ pointcut expression.
|
||||
*/
|
||||
@@ -268,7 +258,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (BCException ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
}
|
||||
return false;
|
||||
@@ -315,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
checkReadyToMatch();
|
||||
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
|
||||
@@ -336,6 +326,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// No current invocation...
|
||||
// TODO: Should we really proceed here?
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not access current invocation - matching with limited context: " + ex);
|
||||
}
|
||||
@@ -422,46 +413,39 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
if (shadowMatch == null) {
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
try {
|
||||
fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
|
||||
if (fallbackExpression != null) {
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = this.pointcutExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Failed to introspect target method, probably because it has been loaded
|
||||
// in a special ClassLoader. Let's try the declaring ClassLoader instead...
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex2) {
|
||||
catch (ReflectionWorldException ex4) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Possibly AspectJ 1.8.10 encountering an invalid signature
|
||||
logger.debug("PointcutExpression matching rejected target method", ex);
|
||||
fallbackExpression = null;
|
||||
}
|
||||
if (shadowMatch == null) {
|
||||
shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);
|
||||
|
||||
+11
-18
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -18,8 +18,6 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractGenericPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
|
||||
/**
|
||||
* Spring AOP Advisor that can be used for any AspectJ pointcut expression.
|
||||
@@ -28,11 +26,16 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware {
|
||||
public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor {
|
||||
|
||||
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
|
||||
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
public void setExpression(String expression) {
|
||||
this.pointcut.setExpression(expression);
|
||||
}
|
||||
@@ -49,22 +52,12 @@ public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdv
|
||||
return this.pointcut.getLocation();
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class<?>[] types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
public void setParameterNames(String... names) {
|
||||
this.pointcut.setParameterNames(names);
|
||||
}
|
||||
|
||||
public void setParameterTypes(Class<?>... types) {
|
||||
this.pointcut.setParameterTypes(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.pointcut.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.aop.MethodBeforeAdvice;
|
||||
@@ -28,8 +27,7 @@ import org.springframework.aop.MethodBeforeAdvice;
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {
|
||||
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice {
|
||||
|
||||
public AspectJMethodBeforeAdvice(
|
||||
Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
|
||||
@@ -37,7 +35,6 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements
|
||||
super(aspectJBeforeAdviceMethod, pointcut, aif);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void before(Method method, Object[] args, Object target) throws Throwable {
|
||||
invokeAdviceMethod(getJoinPointMatch(), null, null);
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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,6 +22,7 @@ import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* AspectJPointcutAdvisor that adapts an {@link AbstractAspectJAdvice}
|
||||
@@ -50,11 +51,11 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
this.pointcut = advice.buildSafePointcut();
|
||||
}
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isPerInstance() {
|
||||
return true;
|
||||
@@ -90,12 +91,12 @@ public class AspectJPointcutAdvisor implements PointcutAdvisor, Ordered {
|
||||
return false;
|
||||
}
|
||||
AspectJPointcutAdvisor otherAdvisor = (AspectJPointcutAdvisor) other;
|
||||
return this.advice.equals(otherAdvisor.advice);
|
||||
return (ObjectUtils.nullSafeEquals(this.advice, otherAdvisor.advice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AspectJPointcutAdvisor.class.hashCode() * 29 + this.advice.hashCode();
|
||||
return AspectJPointcutAdvisor.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor {
|
||||
|
||||
/**
|
||||
* Private constructor to share common code between impl-based delegate and reference-based delegate
|
||||
* (cannot use method such as init() to share common code, due the use of final fields)
|
||||
* (cannot use method such as init() to share common code, due the the use of final fields)
|
||||
* @param interfaceType static field defining the introduction
|
||||
* @param typePattern type pattern the introduction is restricted to
|
||||
* @param implementationClass implementation class
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -243,7 +243,6 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
private String toString(boolean includeModifier, boolean includeReturnTypeAndArgs,
|
||||
boolean useLongReturnAndArgumentTypeName, boolean useLongTypeName) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (includeModifier) {
|
||||
sb.append(Modifier.toString(getModifiers()));
|
||||
@@ -263,9 +262,8 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendTypes(StringBuilder sb, Class<?>[] types, boolean includeArgs,
|
||||
boolean useLongReturnAndArgumentTypeName) {
|
||||
|
||||
private void appendTypes(StringBuilder sb, Class<?>[] types,
|
||||
boolean includeArgs, boolean useLongReturnAndArgumentTypeName) {
|
||||
if (includeArgs) {
|
||||
for (int size = types.length, i = 0; i < size; i++) {
|
||||
appendType(sb, types[i], useLongReturnAndArgumentTypeName);
|
||||
|
||||
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -55,12 +55,10 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
||||
return this.aspectClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -31,8 +29,7 @@ import org.springframework.util.Assert;
|
||||
* @since 2.0
|
||||
* @see SimpleAspectInstanceFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Serializable {
|
||||
public class SingletonAspectInstanceFactory implements AspectInstanceFactory {
|
||||
|
||||
private final Object aspectInstance;
|
||||
|
||||
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import org.springframework.util.StringUtils;
|
||||
* Spring AOP {@link ClassFilter} implementation using AspectJ type matching.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class TypePatternClassFilter implements ClassFilter {
|
||||
@@ -77,21 +76,17 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* or is recognized as invalid
|
||||
*/
|
||||
public void setTypePattern(String typePattern) {
|
||||
Assert.notNull(typePattern, "Type pattern must not be null");
|
||||
Assert.notNull(typePattern);
|
||||
this.typePattern = typePattern;
|
||||
this.aspectJTypePatternMatcher =
|
||||
PointcutParser.getPointcutParserSupportingAllPrimitivesAndUsingContextClassloaderForResolution().
|
||||
parseTypePattern(replaceBooleanOperators(typePattern));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AspectJ type pattern to match.
|
||||
*/
|
||||
public String getTypePattern() {
|
||||
return this.typePattern;
|
||||
return typePattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should the pointcut apply to the given interface or target class?
|
||||
* @param clazz candidate target class
|
||||
@@ -100,7 +95,9 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Class<?> clazz) {
|
||||
Assert.state(this.aspectJTypePatternMatcher != null, "No type pattern has been set");
|
||||
if (this.aspectJTypePatternMatcher == null) {
|
||||
throw new IllegalStateException("No 'typePattern' has been set via ctor/setter.");
|
||||
}
|
||||
return this.aspectJTypePatternMatcher.matches(clazz);
|
||||
}
|
||||
|
||||
@@ -111,8 +108,9 @@ public class TypePatternClassFilter implements ClassFilter {
|
||||
* <p>This method converts back to {@code &&} for the AspectJ pointcut parser.
|
||||
*/
|
||||
private String replaceBooleanOperators(String pcExpr) {
|
||||
String result = StringUtils.replace(pcExpr," and "," && ");
|
||||
result = StringUtils.replace(result, " or ", " || ");
|
||||
return StringUtils.replace(result, " not ", " ! ");
|
||||
pcExpr = StringUtils.replace(pcExpr," and "," && ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " or ", " || ");
|
||||
pcExpr = StringUtils.replace(pcExpr, " not ", " ! ");
|
||||
return pcExpr;
|
||||
}
|
||||
}
|
||||
|
||||
+62
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -38,6 +38,7 @@ import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -60,6 +61,34 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
Class<?>[] classesToLookFor = new Class<?>[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<?> c : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<A>(result);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -121,35 +150,48 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and return the first AspectJ annotation on the given method
|
||||
* (there <i>should</i> only be one anyway...)
|
||||
* The pointcut and advice annotations both have an "argNames" member which contains a
|
||||
* comma-separated list of the argument names. We use this (if non-empty) to build the
|
||||
* formal parameters for the pointcut.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
|
||||
Class<?>[] classesToLookFor = new Class<?>[] {
|
||||
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
|
||||
for (Class<?> c : classesToLookFor) {
|
||||
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
|
||||
if (foundAnnotation != null) {
|
||||
return foundAnnotation;
|
||||
}
|
||||
protected AspectJExpressionPointcut createPointcutExpression(
|
||||
Method annotatedMethod, Class<?> declarationScope, String[] pointcutParameterNames) {
|
||||
|
||||
Class<?> [] pointcutParameterTypes = new Class<?>[0];
|
||||
if (pointcutParameterNames != null) {
|
||||
pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod);
|
||||
}
|
||||
return null;
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes);
|
||||
ajexp.setLocation(annotatedMethod.toString());
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
|
||||
A result = AnnotationUtils.findAnnotation(method, toLookFor);
|
||||
if (result != null) {
|
||||
return new AspectJAnnotation<A>(result);
|
||||
/**
|
||||
* Create the pointcut parameters needed by aspectj based on the given argument names
|
||||
* and the argument types that are available from the adviceMethod. Needs to take into
|
||||
* account (ignore) any JoinPoint based arguments as these are not pointcut context but
|
||||
* rather part of the advice execution context (thisJoinPoint, thisJoinPointStaticPart)
|
||||
*/
|
||||
private Class<?>[] extractPointcutParameterTypes(String[] argNames, Method adviceMethod) {
|
||||
Class<?>[] ret = new Class<?>[argNames.length];
|
||||
Class<?>[] paramTypes = adviceMethod.getParameterTypes();
|
||||
if (argNames.length > paramTypes.length) {
|
||||
throw new IllegalStateException("Expecting at least " + argNames.length +
|
||||
" arguments in the advice declaration, but only found " + paramTypes.length);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
// Make the simplifying assumption for now that all of the JoinPoint based arguments
|
||||
// come first in the advice declaration.
|
||||
int typeOffset = paramTypes.length - argNames.length;
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = paramTypes[i + typeOffset];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
protected enum AspectJAnnotationType {
|
||||
|
||||
AtPointcut,
|
||||
AtBefore,
|
||||
AtAfter,
|
||||
|
||||
+2
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,7 +50,7 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
|
||||
private List<Pattern> includePatterns;
|
||||
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory;
|
||||
private AspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
|
||||
|
||||
@@ -74,9 +74,6 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
@Override
|
||||
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
super.initBeanFactory(beanFactory);
|
||||
if (this.aspectJAdvisorFactory == null) {
|
||||
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
|
||||
}
|
||||
this.aspectJAdvisorsBuilder =
|
||||
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
|
||||
}
|
||||
@@ -133,7 +130,6 @@ public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorA
|
||||
|
||||
public BeanFactoryAspectJAdvisorsBuilderAdapter(
|
||||
ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
|
||||
|
||||
super(beanFactory, advisorFactory);
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,31 +63,31 @@ public interface AspectJAdvisorFactory {
|
||||
/**
|
||||
* Build Spring AOP Advisors for all annotated At-AspectJ methods
|
||||
* on the specified aspect instance.
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* (not the aspect instance itself in order to avoid eager instantiation)
|
||||
* @param aif the aspect instance factory (not the aspect instance itself
|
||||
* in order to avoid eager instantiation)
|
||||
* @return a list of advisors for this class
|
||||
*/
|
||||
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);
|
||||
List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aif);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advisor for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* @param declarationOrder the declaration order within the aspect
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return {@code null} if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
* create a Spring advice in its own right
|
||||
*/
|
||||
Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
int declarationOrder, String aspectName);
|
||||
Advisor getAdvisor(Method candidateAdviceMethod,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
/**
|
||||
* Build a Spring AOP Advice for the given AspectJ advice method.
|
||||
* @param candidateAdviceMethod the candidate advice method
|
||||
* @param expressionPointcut the AspectJ expression pointcut
|
||||
* @param aspectInstanceFactory the aspect instance factory
|
||||
* @param declarationOrder the declaration order within the aspect
|
||||
* @param pointcut the corresponding AspectJ expression pointcut
|
||||
* @param aif the aspect instance factory
|
||||
* @param declarationOrderInAspect the declaration order within the aspect
|
||||
* @param aspectName the name of the aspect
|
||||
* @return {@code null} if the method is not an AspectJ advice method
|
||||
* or if it is a pointcut that will be used by other advice but will not
|
||||
@@ -98,7 +98,7 @@ public interface AspectJAdvisorFactory {
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice
|
||||
* @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
|
||||
*/
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
|
||||
Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut pointcut,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName);
|
||||
|
||||
}
|
||||
|
||||
+19
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.springframework.util.ClassUtils;
|
||||
public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
|
||||
/** Cache for singleton aspect instances */
|
||||
private static final Map<Class<?>, Object> aspectCache = new ConcurrentHashMap<Class<?>, Object>();
|
||||
private static final Map<Class<?>, Object> aspectCache = new HashMap<Class<?>, Object>();
|
||||
|
||||
private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();
|
||||
|
||||
@@ -144,7 +144,7 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
private MetadataAwareAspectInstanceFactory createAspectInstanceFactory(
|
||||
AspectMetadata am, Class<?> aspectClass, String aspectName) {
|
||||
|
||||
MetadataAwareAspectInstanceFactory instanceFactory;
|
||||
MetadataAwareAspectInstanceFactory instanceFactory = null;
|
||||
if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
// Create a shared aspect instance.
|
||||
Object instance = getSingletonAspectInstance(aspectClass);
|
||||
@@ -162,29 +162,23 @@ public class AspectJProxyFactory extends ProxyCreatorSupport {
|
||||
* is created if one cannot be found in the instance cache.
|
||||
*/
|
||||
private Object getSingletonAspectInstance(Class<?> aspectClass) {
|
||||
// Quick check without a lock...
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance == null) {
|
||||
synchronized (aspectCache) {
|
||||
// To be safe, check within full lock now...
|
||||
instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
synchronized (aspectCache) {
|
||||
Object instance = aspectCache.get(aspectClass);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
try {
|
||||
instance = aspectClass.newInstance();
|
||||
aspectCache.put(aspectClass, instance);
|
||||
return instance;
|
||||
}
|
||||
catch (InstantiationException ex) {
|
||||
throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
-41
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.AjType;
|
||||
import org.aspectj.lang.reflect.AjTypeSystem;
|
||||
@@ -35,35 +31,21 @@ import org.springframework.aop.support.ComposablePointcut;
|
||||
* Metadata for an AspectJ aspect class, with an additional Spring AOP pointcut
|
||||
* for the per clause.
|
||||
*
|
||||
* <p>Uses AspectJ 5 AJType reflection API, enabling us to work with different
|
||||
* AspectJ instantiation models such as "singleton", "pertarget" and "perthis".
|
||||
* <p>Uses AspectJ 5 AJType reflection API, so is only supported on Java 5.
|
||||
* Enables us to work with different AspectJ instantiation models such as
|
||||
* "singleton", "pertarget" and "perthis".
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.aop.aspectj.AspectJExpressionPointcut
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AspectMetadata implements Serializable {
|
||||
|
||||
/**
|
||||
* The name of this aspect as defined to Spring (the bean name) -
|
||||
* allows us to determine if two pieces of advice come from the
|
||||
* same aspect and hence their relative precedence.
|
||||
*/
|
||||
private final String aspectName;
|
||||
|
||||
/**
|
||||
* The aspect class, stored separately for re-resolution of the
|
||||
* corresponding AjType on deserialization.
|
||||
*/
|
||||
private final Class<?> aspectClass;
|
||||
public class AspectMetadata {
|
||||
|
||||
/**
|
||||
* AspectJ reflection information (AspectJ 5 / Java 5 specific).
|
||||
* Re-resolved on deserialization since it isn't serializable itself.
|
||||
*/
|
||||
private transient AjType<?> ajType;
|
||||
private final AjType<?> ajType;
|
||||
|
||||
/**
|
||||
* Spring AOP pointcut corresponding to the per clause of the
|
||||
@@ -72,6 +54,13 @@ public class AspectMetadata implements Serializable {
|
||||
*/
|
||||
private final Pointcut perClausePointcut;
|
||||
|
||||
/**
|
||||
* The name of this aspect as defined to Spring (the bean name) -
|
||||
* allows us to determine if two pieces of advice come from the
|
||||
* same aspect and hence their relative precedence.
|
||||
*/
|
||||
private String aspectName;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new AspectMetadata instance for the given aspect class.
|
||||
@@ -94,29 +83,26 @@ public class AspectMetadata implements Serializable {
|
||||
if (ajType == null) {
|
||||
throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
|
||||
}
|
||||
if (ajType.getDeclarePrecedence().length > 0) {
|
||||
this.ajType = ajType;
|
||||
if (this.ajType.getDeclarePrecedence().length > 0) {
|
||||
throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP");
|
||||
}
|
||||
this.aspectClass = ajType.getJavaClass();
|
||||
this.ajType = ajType;
|
||||
|
||||
switch (this.ajType.getPerClause().getKind()) {
|
||||
case SINGLETON:
|
||||
case SINGLETON :
|
||||
this.perClausePointcut = Pointcut.TRUE;
|
||||
return;
|
||||
case PERTARGET:
|
||||
case PERTHIS:
|
||||
case PERTARGET : case PERTHIS :
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setLocation(aspectClass.getName());
|
||||
ajexp.setLocation("@Aspect annotation on " + aspectClass.getName());
|
||||
ajexp.setExpression(findPerClause(aspectClass));
|
||||
ajexp.setPointcutDeclarationScope(aspectClass);
|
||||
this.perClausePointcut = ajexp;
|
||||
return;
|
||||
case PERTYPEWITHIN:
|
||||
case PERTYPEWITHIN :
|
||||
// Works with a type pattern
|
||||
this.perClausePointcut = new ComposablePointcut(new TypePatternClassFilter(findPerClause(aspectClass)));
|
||||
return;
|
||||
default:
|
||||
default :
|
||||
throw new AopConfigException(
|
||||
"PerClause " + ajType.getPerClause().getKind() + " not supported by Spring AOP for " + aspectClass);
|
||||
}
|
||||
@@ -126,6 +112,8 @@ public class AspectMetadata implements Serializable {
|
||||
* Extract contents from String of form {@code pertarget(contents)}.
|
||||
*/
|
||||
private String findPerClause(Class<?> aspectClass) {
|
||||
// TODO when AspectJ provides this, we can remove this hack. Hence we don't
|
||||
// bother to make it elegant. Or efficient. Or robust :-)
|
||||
String str = aspectClass.getAnnotation(Aspect.class).value();
|
||||
str = str.substring(str.indexOf("(") + 1);
|
||||
str = str.substring(0, str.length() - 1);
|
||||
@@ -144,7 +132,7 @@ public class AspectMetadata implements Serializable {
|
||||
* Return the aspect class.
|
||||
*/
|
||||
public Class<?> getAspectClass() {
|
||||
return this.aspectClass;
|
||||
return this.ajType.getJavaClass();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,10 +173,4 @@ public class AspectMetadata implements Serializable {
|
||||
return (isPerThisOrPerTarget() || isPerTypeWithin());
|
||||
}
|
||||
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
this.ajType = AjTypeSystem.getAjType(this.aspectClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,13 +16,10 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -40,8 +37,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
@@ -70,8 +66,6 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
* @param type the type that should be introspected by AspectJ
|
||||
*/
|
||||
public BeanFactoryAspectInstanceFactory(BeanFactory beanFactory, String name, Class<?> type) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
Assert.notNull(name, "Bean name must not be null");
|
||||
this.beanFactory = beanFactory;
|
||||
this.name = name;
|
||||
this.aspectMetadata = new AspectMetadata(type, name);
|
||||
@@ -85,9 +79,12 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
|
||||
@Override
|
||||
public ClassLoader getAspectClassLoader() {
|
||||
return (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
|
||||
ClassUtils.getDefaultClassLoader());
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader();
|
||||
}
|
||||
else {
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,23 +92,6 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst
|
||||
return this.aspectMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
if (this.beanFactory != null) {
|
||||
if (this.beanFactory.isSingleton(name)) {
|
||||
// Rely on singleton semantics provided by the factory -> no local lock.
|
||||
return null;
|
||||
}
|
||||
else if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
return ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the order for this factory's target aspect, either
|
||||
* an instance-specific order expressed through implementing the
|
||||
|
||||
+48
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,10 +17,10 @@
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
@@ -43,12 +43,12 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private final AspectJAdvisorFactory advisorFactory;
|
||||
|
||||
private volatile List<String> aspectBeanNames;
|
||||
private List<String> aspectBeanNames;
|
||||
|
||||
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<String, List<Advisor>>();
|
||||
private final Map<String, List<Advisor>> advisorsCache = new HashMap<String, List<Advisor>>();
|
||||
|
||||
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
|
||||
new ConcurrentHashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
new HashMap<String, MetadataAwareAspectInstanceFactory>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -56,7 +56,7 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
* @param beanFactory the ListableBeanFactory to scan
|
||||
*/
|
||||
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
|
||||
this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
|
||||
this(beanFactory, new ReflectiveAspectJAdvisorFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,57 +80,56 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
* @see #isEligibleBean
|
||||
*/
|
||||
public List<Advisor> buildAspectJAdvisors() {
|
||||
List<String> aspectNames = this.aspectBeanNames;
|
||||
List<String> aspectNames = null;
|
||||
|
||||
if (aspectNames == null) {
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
if (!isEligibleBean(beanName)) {
|
||||
continue;
|
||||
}
|
||||
// We must be careful not to instantiate beans eagerly as in this case they
|
||||
// would be cached by the Spring container but would not have been weaved.
|
||||
Class<?> beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
synchronized (this) {
|
||||
aspectNames = this.aspectBeanNames;
|
||||
if (aspectNames == null) {
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
aspectNames = new LinkedList<String>();
|
||||
String[] beanNames =
|
||||
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
|
||||
for (String beanName : beanNames) {
|
||||
if (!isEligibleBean(beanName)) {
|
||||
continue;
|
||||
}
|
||||
// We must be careful not to instantiate beans eagerly as in this
|
||||
// case they would be cached by the Spring container but would not
|
||||
// have been weaved
|
||||
Class<?> beanType = this.beanFactory.getType(beanName);
|
||||
if (beanType == null) {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
}
|
||||
this.aspectBeanNames = aspectNames;
|
||||
return advisors;
|
||||
}
|
||||
this.aspectBeanNames = aspectNames;
|
||||
return advisors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-53
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
@@ -40,70 +37,58 @@ import org.springframework.aop.support.Pointcuts;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
class InstantiationModelAwarePointcutAdvisorImpl
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
|
||||
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation {
|
||||
|
||||
private final AspectJExpressionPointcut declaredPointcut;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
||||
private transient Method aspectJAdviceMethod;
|
||||
|
||||
private final AspectJAdvisorFactory aspectJAdvisorFactory;
|
||||
private Pointcut pointcut;
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
|
||||
|
||||
private final int declarationOrder;
|
||||
|
||||
private final String aspectName;
|
||||
|
||||
private final Pointcut pointcut;
|
||||
private final Method method;
|
||||
|
||||
private final boolean lazy;
|
||||
|
||||
private final AspectJAdvisorFactory atAspectJAdvisorFactory;
|
||||
|
||||
private Advice instantiatedAdvice;
|
||||
|
||||
private int declarationOrder;
|
||||
|
||||
private String aspectName;
|
||||
|
||||
private Boolean isBeforeAdvice;
|
||||
|
||||
private Boolean isAfterAdvice;
|
||||
|
||||
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
|
||||
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
|
||||
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
this.declaredPointcut = declaredPointcut;
|
||||
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
|
||||
this.methodName = aspectJAdviceMethod.getName();
|
||||
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
|
||||
this.aspectJAdviceMethod = aspectJAdviceMethod;
|
||||
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
|
||||
this.aspectInstanceFactory = aspectInstanceFactory;
|
||||
this.declarationOrder = declarationOrder;
|
||||
this.declaredPointcut = ajexp;
|
||||
this.method = method;
|
||||
this.atAspectJAdvisorFactory = af;
|
||||
this.aspectInstanceFactory = aif;
|
||||
this.declarationOrder = declarationOrderInAspect;
|
||||
this.aspectName = aspectName;
|
||||
|
||||
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
|
||||
if (aif.getAspectMetadata().isLazilyInstantiated()) {
|
||||
// Static part of the pointcut is a lazy type.
|
||||
Pointcut preInstantiationPointcut = Pointcuts.union(
|
||||
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
|
||||
Pointcut preInstantiationPointcut =
|
||||
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
|
||||
|
||||
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
|
||||
// If it's not a dynamic pointcut, it may be optimized out
|
||||
// by the Spring AOP infrastructure after the first evaluation.
|
||||
this.pointcut = new PerTargetInstantiationModelPointcut(
|
||||
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
|
||||
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
|
||||
this.lazy = true;
|
||||
}
|
||||
else {
|
||||
// A singleton aspect.
|
||||
this.pointcut = this.declaredPointcut;
|
||||
this.lazy = false;
|
||||
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
|
||||
this.pointcut = declaredPointcut;
|
||||
this.lazy = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,8 +142,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
|
||||
|
||||
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
|
||||
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
|
||||
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
return this.atAspectJAdvisorFactory.getAdvice(
|
||||
this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
|
||||
}
|
||||
|
||||
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
|
||||
@@ -206,7 +191,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
*/
|
||||
private void determineAdviceType() {
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod);
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method);
|
||||
if (aspectJAnnotation == null) {
|
||||
this.isBeforeAdvice = false;
|
||||
this.isAfterAdvice = false;
|
||||
@@ -235,21 +220,11 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
|
||||
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
|
||||
"]; advice method [" + this.method + "]; perClauseKind=" +
|
||||
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
|
||||
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
|
||||
inputStream.defaultReadObject();
|
||||
try {
|
||||
this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
throw new IllegalStateException("Failed to find advice method on deserialization", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pointcut implementation that changes its behaviour when the advice is instantiated.
|
||||
@@ -281,7 +256,7 @@ class InstantiationModelAwarePointcutAdvisorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// This can match only on declared pointcut.
|
||||
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass));
|
||||
}
|
||||
|
||||
+6
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -27,8 +25,7 @@ import org.springframework.util.Assert;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final MetadataAwareAspectInstanceFactory maaif;
|
||||
|
||||
@@ -46,17 +43,11 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAspectInstance() {
|
||||
public synchronized Object getAspectInstance() {
|
||||
if (this.materialized == null) {
|
||||
Object mutex = this.maaif.getAspectCreationMutex();
|
||||
if (mutex == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
else {
|
||||
synchronized (mutex) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (this.materialized == null) {
|
||||
this.materialized = this.maaif.getAspectInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,11 +68,6 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar
|
||||
return this.maaif.getAspectMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this.maaif.getAspectCreationMutex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.maaif.getOrder();
|
||||
|
||||
+1
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,11 +39,4 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor
|
||||
*/
|
||||
AspectMetadata getAspectMetadata();
|
||||
|
||||
/**
|
||||
* Return the best possible creation mutex for this factory.
|
||||
* @return the mutex object (may be {@code null} for no mutex to use)
|
||||
* @since 4.3
|
||||
*/
|
||||
Object getAspectCreationMutex();
|
||||
|
||||
}
|
||||
|
||||
+4
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a
|
||||
* {@link BeanFactory}-provided prototype, enforcing prototype semantics.
|
||||
* AspectInstanceFactory backed by a BeanFactory-provided prototype,
|
||||
* enforcing prototype semantics.
|
||||
*
|
||||
* <p>Note that this may instantiate multiple times, which probably won't give the
|
||||
* semantics you expect. Use a {@link LazySingletonAspectInstanceFactoryDecorator}
|
||||
@@ -34,8 +32,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
* @see LazySingletonAspectInstanceFactoryDecorator
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable {
|
||||
public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory {
|
||||
|
||||
/**
|
||||
* Create a PrototypeAspectInstanceFactory. AspectJ will be called to
|
||||
|
||||
+30
-65
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -46,7 +45,6 @@ import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice;
|
||||
import org.springframework.aop.aspectj.DeclareParentsAdvisor;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.support.DefaultPointcutAdvisor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConvertingComparator;
|
||||
@@ -67,8 +65,7 @@ import org.springframework.util.comparator.InstanceComparator;
|
||||
* @author Phillip Webb
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
|
||||
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory {
|
||||
|
||||
private static final Comparator<Method> METHOD_COMPARATOR;
|
||||
|
||||
@@ -80,9 +77,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
new Converter<Method, Annotation>() {
|
||||
@Override
|
||||
public Annotation convert(Method method) {
|
||||
AspectJAnnotation<?> annotation =
|
||||
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return (annotation != null ? annotation.getAnnotation() : null);
|
||||
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
|
||||
return annotation == null ? null : annotation.getAnnotation();
|
||||
}
|
||||
}));
|
||||
comparator.addComparator(new ConvertingComparator<Method, String>(
|
||||
@@ -96,42 +92,18 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code ReflectiveAspectJAdvisorFactory}.
|
||||
*/
|
||||
public ReflectiveAspectJAdvisorFactory() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code ReflectiveAspectJAdvisorFactory}, propagating the given
|
||||
* {@link BeanFactory} to the created {@link AspectJExpressionPointcut} instances,
|
||||
* for bean pointcut handling as well as consistent {@link ClassLoader} resolution.
|
||||
* @param beanFactory the BeanFactory to propagate (may be {@code null}}
|
||||
* @since 4.3.6
|
||||
* @see AspectJExpressionPointcut#setBeanFactory
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader()
|
||||
*/
|
||||
public ReflectiveAspectJAdvisorFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
|
||||
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
|
||||
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
|
||||
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
|
||||
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
|
||||
final String aspectName = maaif.getAspectMetadata().getAspectName();
|
||||
validate(aspectClass);
|
||||
|
||||
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
|
||||
// so that it will only instantiate once.
|
||||
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
|
||||
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
|
||||
new LazySingletonAspectInstanceFactoryDecorator(maaif);
|
||||
|
||||
List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
final List<Advisor> advisors = new LinkedList<Advisor>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
|
||||
if (advisor != null) {
|
||||
@@ -186,7 +158,9 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
}
|
||||
|
||||
if (DeclareParents.class == declareParents.defaultImpl()) {
|
||||
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
|
||||
// This is what comes back if it wasn't set. This seems bizarre...
|
||||
// TODO this restriction possibly should be relaxed
|
||||
throw new IllegalStateException("defaultImpl must be set on DeclareParents");
|
||||
}
|
||||
|
||||
return new DeclareParentsAdvisor(
|
||||
@@ -195,19 +169,18 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
|
||||
@Override
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
|
||||
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
|
||||
int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
|
||||
validate(aif.getAspectMetadata().getAspectClass());
|
||||
|
||||
AspectJExpressionPointcut expressionPointcut = getPointcut(
|
||||
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
|
||||
if (expressionPointcut == null) {
|
||||
AspectJExpressionPointcut ajexp =
|
||||
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
|
||||
if (ajexp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
|
||||
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(
|
||||
this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
|
||||
@@ -216,20 +189,18 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
if (aspectJAnnotation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AspectJExpressionPointcut ajexp =
|
||||
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
|
||||
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
|
||||
ajexp.setBeanFactory(this.beanFactory);
|
||||
return ajexp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
|
||||
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
|
||||
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) {
|
||||
|
||||
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
|
||||
Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass();
|
||||
validate(candidateAspectClass);
|
||||
|
||||
AspectJAnnotation<?> aspectJAnnotation =
|
||||
@@ -254,32 +225,27 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
switch (aspectJAnnotation.getAnnotationType()) {
|
||||
case AtBefore:
|
||||
springAdvice = new AspectJMethodBeforeAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfter:
|
||||
springAdvice = new AspectJAfterAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtAfterReturning:
|
||||
springAdvice = new AspectJAfterReturningAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
|
||||
springAdvice.setReturningName(afterReturningAnnotation.returning());
|
||||
}
|
||||
break;
|
||||
case AtAfterThrowing:
|
||||
springAdvice = new AspectJAfterThrowingAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
|
||||
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
|
||||
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
|
||||
}
|
||||
break;
|
||||
case AtAround:
|
||||
springAdvice = new AspectJAroundAdvice(
|
||||
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
|
||||
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
|
||||
break;
|
||||
case AtPointcut:
|
||||
if (logger.isDebugEnabled()) {
|
||||
@@ -288,12 +254,12 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported advice type on method: " + candidateAdviceMethod);
|
||||
"Unsupported advice type on method " + candidateAdviceMethod);
|
||||
}
|
||||
|
||||
// Now to configure the advice...
|
||||
springAdvice.setAspectName(aspectName);
|
||||
springAdvice.setDeclarationOrder(declarationOrder);
|
||||
springAdvice.setDeclarationOrder(declarationOrderInAspect);
|
||||
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
|
||||
if (argNames != null) {
|
||||
springAdvice.setArgumentNamesFromStringArray(argNames);
|
||||
@@ -302,7 +268,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return springAdvice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Synthetic advisor that instantiates the aspect.
|
||||
* Triggered by per-clause pointcut on non-singleton aspect.
|
||||
|
||||
+1
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -50,11 +50,6 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
|
||||
+2
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.aspectj.annotation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.aop.aspectj.SingletonAspectInstanceFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
@@ -32,9 +30,8 @@ import org.springframework.core.annotation.OrderUtils;
|
||||
* @since 2.0
|
||||
* @see SimpleMetadataAwareAspectInstanceFactory
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspectInstanceFactory
|
||||
implements MetadataAwareAspectInstanceFactory, Serializable {
|
||||
implements MetadataAwareAspectInstanceFactory {
|
||||
|
||||
private final AspectMetadata metadata;
|
||||
|
||||
@@ -55,11 +52,6 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAspectCreationMutex() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOrderForAspectClass(Class<?> aspectClass) {
|
||||
return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE);
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,7 +71,7 @@ public abstract class AbstractInterceptorDrivenBeanDefinitionDecorator implement
|
||||
BeanDefinition interceptorDefinition = createInterceptorDefinition(node);
|
||||
|
||||
// generate name and register the interceptor
|
||||
String interceptorName = existingBeanName + '.' + getInterceptorNameSuffix(interceptorDefinition);
|
||||
String interceptorName = existingBeanName + "." + getInterceptorNameSuffix(interceptorDefinition);
|
||||
BeanDefinitionReaderUtils.registerBeanDefinition(
|
||||
new BeanDefinitionHolder(interceptorDefinition, interceptorName), registry);
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ import org.springframework.util.Assert;
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.parsing.ComponentDefinition}
|
||||
* that bridges the gap between the advisor bean definition configured
|
||||
* by the {@code <aop:advisor>} tag and the component definition
|
||||
* by the {@code <aop:advisor>} tag and the component definition
|
||||
* infrastructure.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -97,7 +97,7 @@ public abstract class AopConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
|
||||
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
|
||||
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
|
||||
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
* {@code NamespaceHandler} for the {@code aop} namespace.
|
||||
*
|
||||
* <p>Provides a {@link org.springframework.beans.factory.xml.BeanDefinitionParser} for the
|
||||
* {@code <aop:config>} tag. A {@code config} tag can include nested
|
||||
* {@code <aop:config>} tag. A {@code config} tag can include nested
|
||||
* {@code pointcut}, {@code advisor} and {@code aspect} tags.
|
||||
*
|
||||
* <p>The {@code pointcut} tag allows for creation of named
|
||||
|
||||
+4
-4
@@ -49,7 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionParser} for the {@code <aop:config>} tag.
|
||||
* {@link BeanDefinitionParser} for the {@code <aop:config>} tag.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
@@ -123,7 +123,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Configures the auto proxy creator needed to support the {@link BeanDefinition BeanDefinitions}
|
||||
* created by the '{@code <aop:config/>}' tag. Will force class proxying if the
|
||||
* created by the '{@code <aop:config/>}' tag. Will force class proxying if the
|
||||
* '{@code proxy-target-class}' attribute is set to '{@code true}'.
|
||||
* @see AopNamespaceUtils
|
||||
*/
|
||||
@@ -132,7 +132,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the supplied {@code <advisor>} element and registers the resulting
|
||||
* Parses the supplied {@code <advisor>} element and registers the resulting
|
||||
* {@link org.springframework.aop.Advisor} and any resulting {@link org.springframework.aop.Pointcut}
|
||||
* with the supplied {@link BeanDefinitionRegistry}.
|
||||
*/
|
||||
@@ -428,7 +428,7 @@ class ConfigBeanDefinitionParser implements BeanDefinitionParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the supplied {@code <pointcut>} and registers the resulting
|
||||
* Parses the supplied {@code <pointcut>} and registers the resulting
|
||||
* Pointcut with the BeanDefinitionRegistry.
|
||||
*/
|
||||
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinitionDecorator} responsible for parsing the
|
||||
* {@code <aop:scoped-proxy/>} tag.
|
||||
* {@code <aop:scoped-proxy/>} tag.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,8 +21,8 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AspectInstanceFactory} that locates the aspect from the
|
||||
@@ -50,7 +50,9 @@ public class SimpleBeanFactoryAwareAspectInstanceFactory implements AspectInstan
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
Assert.notNull(this.aspectBeanName, "'aspectBeanName' is required");
|
||||
if (!StringUtils.hasText(this.aspectBeanName)) {
|
||||
throw new IllegalArgumentException("'aspectBeanName' is required");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-38
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
@@ -37,7 +37,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
|
||||
protected boolean beforeExistingAdvisors = false;
|
||||
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(256);
|
||||
private final Map<Class<?>, Boolean> eligibleBeans = new ConcurrentHashMap<Class<?>, Boolean>(64);
|
||||
|
||||
|
||||
/**
|
||||
@@ -81,12 +81,13 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
}
|
||||
|
||||
if (isEligible(bean, beanName)) {
|
||||
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.setTarget(bean);
|
||||
if (!proxyFactory.isProxyTargetClass()) {
|
||||
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
|
||||
}
|
||||
proxyFactory.addAdvisor(this.advisor);
|
||||
customizeProxyFactory(proxyFactory);
|
||||
return proxyFactory.getProxy(getProxyClassLoader());
|
||||
}
|
||||
|
||||
@@ -130,38 +131,4 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSu
|
||||
return eligible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a {@link ProxyFactory} for the given bean.
|
||||
* <p>Subclasses may customize the handling of the target instance and in
|
||||
* particular the exposure of the target class. The default introspection
|
||||
* of interfaces for non-target-class proxies and the configured advisor
|
||||
* will be applied afterwards; {@link #customizeProxyFactory} allows for
|
||||
* late customizations of those parts right before proxy creation.
|
||||
* @param bean the bean instance to create a proxy for
|
||||
* @param beanName the corresponding bean name
|
||||
* @return the ProxyFactory, initialized with this processor's
|
||||
* {@link ProxyConfig} settings and the specified bean
|
||||
* @since 4.2.3
|
||||
* @see #customizeProxyFactory
|
||||
*/
|
||||
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.copyFrom(this);
|
||||
proxyFactory.setTarget(bean);
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may choose to implement this: for example,
|
||||
* to change the interfaces exposed.
|
||||
* <p>The default implementation is empty.
|
||||
* @param proxyFactory ProxyFactory that is already configured with
|
||||
* target, advisor and interfaces and will be used to create the proxy
|
||||
* immediately after this method returns
|
||||
* @since 4.2.3
|
||||
* @see #prepareProxyFactory
|
||||
*/
|
||||
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -113,7 +113,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Create a AdvisedSupport instance with the given parameters.
|
||||
* @param interfaces the proxied interfaces
|
||||
*/
|
||||
public AdvisedSupport(Class<?>... interfaces) {
|
||||
public AdvisedSupport(Class<?>[] interfaces) {
|
||||
this();
|
||||
setInterfaces(interfaces);
|
||||
}
|
||||
@@ -586,7 +586,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
* Simple wrapper class around a Method. Used as the key when
|
||||
* caching methods, for efficient equals and hashCode comparisons.
|
||||
*/
|
||||
private static final class MethodCacheKey implements Comparable<MethodCacheKey> {
|
||||
private static class MethodCacheKey {
|
||||
|
||||
private final Method method;
|
||||
|
||||
@@ -599,28 +599,17 @@ public class AdvisedSupport extends ProxyConfig implements Advised {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (this == other || (other instanceof MethodCacheKey &&
|
||||
this.method == ((MethodCacheKey) other).method));
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
MethodCacheKey otherKey = (MethodCacheKey) other;
|
||||
return (this.method == otherKey.method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.method.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MethodCacheKey other) {
|
||||
int result = this.method.getName().compareTo(other.method.getName());
|
||||
if (result == 0) {
|
||||
result = this.method.toString().compareTo(other.method.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -26,9 +24,7 @@ import org.springframework.aop.TargetClassAware;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.SingletonTargetSource;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Utility methods for AOP proxy factories.
|
||||
@@ -43,25 +39,6 @@ import org.springframework.util.ObjectUtils;
|
||||
*/
|
||||
public abstract class AopProxyUtils {
|
||||
|
||||
/**
|
||||
* Obtain the singleton target object behind the given proxy, if any.
|
||||
* @param candidate the (potential) proxy to check
|
||||
* @return the singleton target object managed in a {@link SingletonTargetSource},
|
||||
* or {@code null} in any other case (not a proxy, not an existing singleton target)
|
||||
* @since 4.3.8
|
||||
* @see Advised#getTargetSource()
|
||||
* @see SingletonTargetSource#getTarget()
|
||||
*/
|
||||
public static Object getSingletonTarget(Object candidate) {
|
||||
if (candidate instanceof Advised) {
|
||||
TargetSource targetSource = ((Advised) candidate).getTargetSource();
|
||||
if (targetSource instanceof SingletonTargetSource) {
|
||||
return ((SingletonTargetSource) targetSource).getTarget();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the ultimate target class of the given bean instance, traversing
|
||||
* not only a top-level proxy but any number of nested proxies as well —
|
||||
@@ -78,7 +55,14 @@ public abstract class AopProxyUtils {
|
||||
Class<?> result = null;
|
||||
while (current instanceof TargetClassAware) {
|
||||
result = ((TargetClassAware) current).getTargetClass();
|
||||
current = getSingletonTarget(current);
|
||||
Object nested = null;
|
||||
if (current instanceof Advised) {
|
||||
TargetSource targetSource = ((Advised) current).getTargetSource();
|
||||
if (targetSource instanceof SingletonTargetSource) {
|
||||
nested = ((SingletonTargetSource) targetSource).getTarget();
|
||||
}
|
||||
}
|
||||
current = nested;
|
||||
}
|
||||
if (result == null) {
|
||||
result = (AopUtils.isCglibProxy(candidate) ? candidate.getClass().getSuperclass() : candidate.getClass());
|
||||
@@ -91,29 +75,11 @@ public abstract class AopProxyUtils {
|
||||
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
|
||||
* {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
|
||||
* {@link org.springframework.aop.SpringProxy} marker interface.
|
||||
* @param advised the proxy config
|
||||
* @return the complete set of interfaces to proxy
|
||||
* @see SpringProxy
|
||||
* @see Advised
|
||||
* @see org.springframework.aop.SpringProxy
|
||||
*/
|
||||
public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
|
||||
return completeProxiedInterfaces(advised, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the complete set of interfaces to proxy for the given AOP configuration.
|
||||
* <p>This will always add the {@link Advised} interface unless the AdvisedSupport's
|
||||
* {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the
|
||||
* {@link org.springframework.aop.SpringProxy} marker interface.
|
||||
* @param advised the proxy config
|
||||
* @param decoratingProxy whether to expose the {@link DecoratingProxy} interface
|
||||
* @return the complete set of interfaces to proxy
|
||||
* @since 4.3
|
||||
* @see SpringProxy
|
||||
* @see Advised
|
||||
* @see DecoratingProxy
|
||||
*/
|
||||
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
|
||||
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
|
||||
if (specifiedInterfaces.length == 0) {
|
||||
// No user-specified interfaces: check whether target class is an interface.
|
||||
@@ -130,7 +96,6 @@ public abstract class AopProxyUtils {
|
||||
}
|
||||
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
|
||||
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
|
||||
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
|
||||
int nonUserIfcCount = 0;
|
||||
if (addSpringProxy) {
|
||||
nonUserIfcCount++;
|
||||
@@ -138,22 +103,13 @@ public abstract class AopProxyUtils {
|
||||
if (addAdvised) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
if (addDecoratingProxy) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount];
|
||||
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
|
||||
int index = specifiedInterfaces.length;
|
||||
if (addSpringProxy) {
|
||||
proxiedInterfaces[index] = SpringProxy.class;
|
||||
index++;
|
||||
proxiedInterfaces[specifiedInterfaces.length] = SpringProxy.class;
|
||||
}
|
||||
if (addAdvised) {
|
||||
proxiedInterfaces[index] = Advised.class;
|
||||
index++;
|
||||
}
|
||||
if (addDecoratingProxy) {
|
||||
proxiedInterfaces[index] = DecoratingProxy.class;
|
||||
proxiedInterfaces[proxiedInterfaces.length - 1] = Advised.class;
|
||||
}
|
||||
return proxiedInterfaces;
|
||||
}
|
||||
@@ -175,9 +131,6 @@ public abstract class AopProxyUtils {
|
||||
if (proxy instanceof Advised) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
if (proxy instanceof DecoratingProxy) {
|
||||
nonUserIfcCount++;
|
||||
}
|
||||
Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - nonUserIfcCount];
|
||||
System.arraycopy(proxyInterfaces, 0, userInterfaces, 0, userInterfaces.length);
|
||||
Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces");
|
||||
@@ -208,38 +161,4 @@ public abstract class AopProxyUtils {
|
||||
return Arrays.equals(a.getAdvisors(), b.getAdvisors());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the given arguments to the target signature in the given method,
|
||||
* if necessary: in particular, if a given vararg argument array does not
|
||||
* match the array type of the declared vararg parameter in the method.
|
||||
* @param method the target method
|
||||
* @param arguments the given arguments
|
||||
* @return a cloned argument array, or the original if no adaptation is needed
|
||||
* @since 4.2.3
|
||||
*/
|
||||
static Object[] adaptArgumentsIfNecessary(Method method, Object... arguments) {
|
||||
if (method.isVarArgs() && !ObjectUtils.isEmpty(arguments)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length == arguments.length) {
|
||||
int varargIndex = paramTypes.length - 1;
|
||||
Class<?> varargType = paramTypes[varargIndex];
|
||||
if (varargType.isArray()) {
|
||||
Object varargArray = arguments[varargIndex];
|
||||
if (varargArray instanceof Object[] && !varargType.isInstance(varargArray)) {
|
||||
Object[] newArguments = new Object[arguments.length];
|
||||
System.arraycopy(arguments, 0, newArguments, 0, varargIndex);
|
||||
Class<?> targetElementType = varargType.getComponentType();
|
||||
int varargLength = Array.getLength(varargArray);
|
||||
Object newVarargArray = Array.newInstance(targetElementType, varargLength);
|
||||
System.arraycopy(varargArray, 0, newVarargArray, 0, varargLength);
|
||||
newArguments[varargIndex] = newVarargArray;
|
||||
return newArguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,6 @@ import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
@@ -37,7 +36,6 @@ import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.cglib.core.ClassGenerator;
|
||||
import org.springframework.cglib.core.CodeGenerationException;
|
||||
import org.springframework.cglib.core.SpringNamingPolicy;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
@@ -57,6 +55,9 @@ import org.springframework.util.ObjectUtils;
|
||||
/**
|
||||
* CGLIB-based {@link AopProxy} implementation for the Spring AOP framework.
|
||||
*
|
||||
* <p>Formerly named {@code Cglib2AopProxy}, as of Spring 3.2, this class depends on
|
||||
* Spring's own internally repackaged version of CGLIB 3.</i>.
|
||||
*
|
||||
* <p>Objects of this type should be obtained through proxy factories,
|
||||
* configured by an {@link AdvisedSupport} object. This class is internal
|
||||
* to Spring's AOP framework and need not be used directly by client code.
|
||||
@@ -92,7 +93,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
|
||||
/** Logger available to subclasses; static to optimize serialization */
|
||||
protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);
|
||||
protected final static Log logger = LogFactory.getLog(CglibAopProxy.class);
|
||||
|
||||
/** Keeps track of the Classes that we have validated for final methods */
|
||||
private static final Map<Class<?>, Boolean> validatedClasses = new WeakHashMap<Class<?>, Boolean>();
|
||||
@@ -185,7 +186,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
enhancer.setSuperclass(proxySuperClass);
|
||||
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
|
||||
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
|
||||
|
||||
Callback[] callbacks = getCallbacks(rootClass);
|
||||
Class<?>[] types = new Class<?>[callbacks.length];
|
||||
@@ -212,7 +213,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
"Common causes of this problem include using a final class or a non-visible class",
|
||||
ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
catch (Exception ex) {
|
||||
// TargetSource.getTarget() failed
|
||||
throw new AopConfigException("Unexpected AOP exception", ex);
|
||||
}
|
||||
@@ -239,11 +240,10 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* validates it if not.
|
||||
*/
|
||||
private void validateClassIfNecessary(Class<?> proxySuperClass, ClassLoader proxyClassLoader) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
synchronized (validatedClasses) {
|
||||
if (!validatedClasses.containsKey(proxySuperClass)) {
|
||||
doValidateClass(proxySuperClass, proxyClassLoader,
|
||||
ClassUtils.getAllInterfacesForClassAsSet(proxySuperClass));
|
||||
doValidateClass(proxySuperClass, proxyClassLoader);
|
||||
validatedClasses.put(proxySuperClass, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
@@ -254,35 +254,30 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
* Checks for final methods on the given {@code Class}, as well as package-visible
|
||||
* methods across ClassLoaders, and writes warnings to the log for each one found.
|
||||
*/
|
||||
private void doValidateClass(Class<?> proxySuperClass, ClassLoader proxyClassLoader, Set<Class<?>> ifcs) {
|
||||
if (proxySuperClass != Object.class) {
|
||||
private void doValidateClass(Class<?> proxySuperClass, ClassLoader proxyClassLoader) {
|
||||
if (Object.class != proxySuperClass) {
|
||||
Method[] methods = proxySuperClass.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
int mod = method.getModifiers();
|
||||
if (!Modifier.isStatic(mod)) {
|
||||
if (Modifier.isFinal(mod)) {
|
||||
if (implementsInterface(method, ifcs)) {
|
||||
logger.warn("Unable to proxy interface-implementing method [" + method + "] because " +
|
||||
"it is marked as final: Consider using interface-based JDK proxies instead!");
|
||||
}
|
||||
logger.info("Final method [" + method + "] cannot get proxied via CGLIB: " +
|
||||
"Calls to this method will NOT be routed to the target instance and " +
|
||||
"might lead to NPEs against uninitialized fields in the proxy instance.");
|
||||
logger.info("Unable to proxy method [" + method + "] because it is final: " +
|
||||
"All calls to this method via a proxy will NOT be routed to the target instance.");
|
||||
}
|
||||
else if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod) && !Modifier.isPrivate(mod) &&
|
||||
proxyClassLoader != null && proxySuperClass.getClassLoader() != proxyClassLoader) {
|
||||
logger.info("Method [" + method + "] is package-visible across different ClassLoaders " +
|
||||
"and cannot get proxied via CGLIB: Declare this method as public or protected " +
|
||||
"if you need to support invocations through the proxy.");
|
||||
logger.info("Unable to proxy method [" + method + "] because it is package-visible " +
|
||||
"across different ClassLoaders: All calls to this method via a proxy will " +
|
||||
"NOT be routed to the target instance.");
|
||||
}
|
||||
}
|
||||
}
|
||||
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader, ifcs);
|
||||
doValidateClass(proxySuperClass.getSuperclass(), proxyClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
|
||||
// Parameters used for optimization choices...
|
||||
// Parameters used for optimisation choices...
|
||||
boolean exposeProxy = this.advised.isExposeProxy();
|
||||
boolean isFrozen = this.advised.isFrozen();
|
||||
boolean isStatic = this.advised.getTargetSource().isStatic();
|
||||
@@ -309,26 +304,26 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
Callback targetDispatcher = isStatic ?
|
||||
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
|
||||
|
||||
Callback[] mainCallbacks = new Callback[] {
|
||||
aopInterceptor, // for normal advice
|
||||
targetInterceptor, // invoke target without considering advice, if optimized
|
||||
new SerializableNoOp(), // no override for methods mapped to this
|
||||
targetDispatcher, this.advisedDispatcher,
|
||||
new EqualsInterceptor(this.advised),
|
||||
new HashCodeInterceptor(this.advised)
|
||||
Callback[] mainCallbacks = new Callback[]{
|
||||
aopInterceptor, // for normal advice
|
||||
targetInterceptor, // invoke target without considering advice, if optimized
|
||||
new SerializableNoOp(), // no override for methods mapped to this
|
||||
targetDispatcher, this.advisedDispatcher,
|
||||
new EqualsInterceptor(this.advised),
|
||||
new HashCodeInterceptor(this.advised)
|
||||
};
|
||||
|
||||
Callback[] callbacks;
|
||||
|
||||
// If the target is a static one and the advice chain is frozen,
|
||||
// then we can make some optimizations by sending the AOP calls
|
||||
// then we can make some optimisations by sending the AOP calls
|
||||
// direct to the target using the fixed chain for that method.
|
||||
if (isStatic && isFrozen) {
|
||||
Method[] methods = rootClass.getMethods();
|
||||
Callback[] fixedCallbacks = new Callback[methods.length];
|
||||
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
|
||||
|
||||
// TODO: small memory optimization here (can skip creation for methods with no advice)
|
||||
// TODO: small memory optimisation here (can skip creation for methods with no advice)
|
||||
for (int x = 0; x < methods.length; x++) {
|
||||
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
|
||||
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
|
||||
@@ -349,39 +344,13 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (this == other || (other instanceof CglibAopProxy &&
|
||||
AopProxyUtils.equalsInProxy(this.advised, ((CglibAopProxy) other).advised)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check whether the given method is declared on any of the given interfaces.
|
||||
*/
|
||||
private static boolean implementsInterface(Method method, Set<Class<?>> ifcs) {
|
||||
for (Class<?> ifc : ifcs) {
|
||||
if (ClassUtils.hasMethod(ifc, method.getName(), method.getParameterTypes())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a return value. Wraps a return of {@code this} if necessary to be the
|
||||
* {@code proxy} and also verifies that {@code null} is not returned as a primitive.
|
||||
*/
|
||||
private static Object processReturnType(Object proxy, Object target, Method method, Object retVal) {
|
||||
// Massage return value if necessary
|
||||
if (retVal != null && retVal == target &&
|
||||
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
if (retVal != null && retVal == target && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this". Note that we can't help
|
||||
// if the target sets a reference to itself in another returned object.
|
||||
retVal = proxy;
|
||||
@@ -395,6 +364,18 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (this == other || (other instanceof CglibAopProxy &&
|
||||
AopProxyUtils.equalsInProxy(this.advised, ((CglibAopProxy) other).advised)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return CglibAopProxy.class.hashCode() * 13 + this.advised.getTargetSource().hashCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serializable replacement for CGLIB's NoOp interface.
|
||||
* Public to allow use elsewhere in the framework.
|
||||
@@ -665,8 +646,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// Note that the final invoker must be an InvokerInterceptor, so we know
|
||||
// it does nothing but a reflective operation on the target, and no hot
|
||||
// swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
retVal = methodProxy.invoke(target, argsToUse);
|
||||
retVal = methodProxy.invoke(target, args);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
@@ -722,7 +702,6 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
|
||||
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());
|
||||
@@ -840,43 +819,53 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
// Else use the AOP_PROXY.
|
||||
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method has advice and optimizations are enabled: " + method);
|
||||
logger.debug("Method has advice and optimisations are enabled: " + method);
|
||||
}
|
||||
// We know that we are optimizing so we can use the FixedStaticChainInterceptors.
|
||||
// We know that we are optimising so we can use the
|
||||
// FixedStaticChainInterceptors.
|
||||
int index = this.fixedInterceptorMap.get(key);
|
||||
return (index + this.fixedInterceptorOffset);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Unable to apply any optimizations to advised method: " + method);
|
||||
logger.debug("Unable to apply any optimisations to advised method: " + method);
|
||||
}
|
||||
return AOP_PROXY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// See if the return type of the method is outside the class hierarchy 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 we cannot use a dispatcher because the
|
||||
// target needs to be explicitly released after the invocation.
|
||||
// See if the return type of the method is outside the class hierarchy
|
||||
// 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.
|
||||
if (exposeProxy || !isStatic) {
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (returnType.isAssignableFrom(targetClass)) {
|
||||
if (targetClass == returnType) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method return type is assignable from target type and " +
|
||||
"may therefore return 'this' - using INVOKE_TARGET: " + method);
|
||||
logger.debug("Method " + method +
|
||||
"has return type same as target type (may return this) - using INVOKE_TARGET");
|
||||
}
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
else {
|
||||
else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method return type ensures 'this' cannot be returned - " +
|
||||
"using DISPATCH_TARGET: " + method);
|
||||
logger.debug("Method " + method +
|
||||
" has return type that ensures this cannot be returned- using DISPATCH_TARGET");
|
||||
}
|
||||
return DISPATCH_TARGET;
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method " + method +
|
||||
"has return type that is assignable from the target type (may return this) - " +
|
||||
"using INVOKE_TARGET");
|
||||
}
|
||||
return INVOKE_TARGET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,7 +920,7 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
if (aa == null || ba == null) {
|
||||
return (aa == ba);
|
||||
}
|
||||
return (aa.getClass() == ba.getClass());
|
||||
return aa.getClass().equals(ba.getClass());
|
||||
}
|
||||
|
||||
private boolean equalsPointcuts(Advisor a, Advisor b) {
|
||||
@@ -960,51 +949,4 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CGLIB GeneratorStrategy variant which exposes the application ClassLoader
|
||||
* as thread context ClassLoader for the time of class generation
|
||||
* (in order for ASM to pick it up when doing common superclass resolution).
|
||||
*/
|
||||
private static class ClassLoaderAwareUndeclaredThrowableStrategy extends UndeclaredThrowableStrategy {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public ClassLoaderAwareUndeclaredThrowableStrategy(ClassLoader classLoader) {
|
||||
super(UndeclaredThrowableException.class);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] generate(ClassGenerator cg) throws Exception {
|
||||
if (this.classLoader == null) {
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader threadContextClassLoader;
|
||||
try {
|
||||
threadContextClassLoader = currentThread.getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access thread context ClassLoader - falling back...
|
||||
return super.generate(cg);
|
||||
}
|
||||
|
||||
boolean overrideClassLoader = !this.classLoader.equals(threadContextClassLoader);
|
||||
if (overrideClassLoader) {
|
||||
currentThread.setContextClassLoader(this.classLoader);
|
||||
}
|
||||
try {
|
||||
return super.generate(cg);
|
||||
}
|
||||
finally {
|
||||
if (overrideClassLoader) {
|
||||
// Reset original thread context ClassLoader.
|
||||
currentThread.setContextClassLoader(threadContextClassLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -30,7 +30,6 @@ import org.springframework.aop.AopInvocationException;
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -117,7 +116,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
|
||||
}
|
||||
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
|
||||
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
|
||||
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
|
||||
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
|
||||
}
|
||||
@@ -165,15 +164,11 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// The target does not implement the equals(Object) method itself.
|
||||
return equals(args[0]);
|
||||
}
|
||||
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
|
||||
// The target does not implement the hashCode() method itself.
|
||||
return hashCode();
|
||||
}
|
||||
else if (method.getDeclaringClass() == DecoratingProxy.class) {
|
||||
// There is only getDecoratedClass() declared -> dispatch to proxy config.
|
||||
return AopProxyUtils.ultimateTargetClass(this.advised);
|
||||
}
|
||||
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
|
||||
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
|
||||
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
|
||||
// Service invocations on ProxyConfig with the proxy config...
|
||||
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
|
||||
@@ -203,8 +198,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
// We can skip creating a MethodInvocation: just invoke the target directly
|
||||
// Note that the final invoker must be an InvokerInterceptor so we know it does
|
||||
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
|
||||
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
|
||||
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
|
||||
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
|
||||
}
|
||||
else {
|
||||
// We need to create a method invocation...
|
||||
@@ -215,8 +209,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa
|
||||
|
||||
// Massage return value if necessary.
|
||||
Class<?> returnType = method.getReturnType();
|
||||
if (retVal != null && retVal == target &&
|
||||
returnType != Object.class && returnType.isInstance(proxy) &&
|
||||
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
|
||||
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
|
||||
// Special case: it returned "this" and the return type of the method
|
||||
// is type-compatible. Note that we can't help if the target sets
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* 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.
|
||||
@@ -22,9 +22,9 @@ import org.springframework.aop.TargetSource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Factory for AOP proxies for programmatic use, rather than via declarative
|
||||
* setup in a bean factory. This class provides a simple way of obtaining
|
||||
* and configuring AOP proxy instances in custom user code.
|
||||
* Factory for AOP proxies for programmatic use, rather than via a bean
|
||||
* factory. This class provides a simple way of obtaining and configuring
|
||||
* AOP proxies in code.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+2
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -129,7 +127,6 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
*/
|
||||
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
|
||||
return (InitializingBean.class == ifc || DisposableBean.class == ifc ||
|
||||
Closeable.class == ifc || "java.lang.AutoCloseable".equals(ifc.getName()) ||
|
||||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
|
||||
}
|
||||
|
||||
@@ -142,9 +139,7 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC
|
||||
* @return whether the given interface is an internal language interface
|
||||
*/
|
||||
protected boolean isInternalLanguageInterface(Class<?> ifc) {
|
||||
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
|
||||
ifc.getName().endsWith(".cglib.proxy.Factory") ||
|
||||
ifc.getName().endsWith(".bytebuddy.MockAccess"));
|
||||
return ifc.getName().equals("groovy.lang.GroovyObject");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -109,7 +109,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
this.target = target;
|
||||
this.targetClass = targetClass;
|
||||
this.method = BridgeMethodResolver.findBridgedMethod(method);
|
||||
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
|
||||
this.arguments = arguments;
|
||||
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArguments(Object... arguments) {
|
||||
public void setArguments(Object[] arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Clonea
|
||||
* @see java.lang.Object#clone()
|
||||
*/
|
||||
@Override
|
||||
public MethodInvocation invocableClone(Object... arguments) {
|
||||
public MethodInvocation invocableClone(Object[] arguments) {
|
||||
// Force initialization of the user attributes Map,
|
||||
// for having a shared Map reference in the clone.
|
||||
if (this.userAttributes == null) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -26,7 +26,7 @@ import org.springframework.aop.AfterReturningAdvice;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Interceptor to wrap an {@link org.springframework.aop.AfterReturningAdvice}.
|
||||
* Interceptor to wrap am {@link org.springframework.aop.AfterReturningAdvice}.
|
||||
* Used internally by the AOP framework; application developers should not need
|
||||
* to use this class directly.
|
||||
*
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,8 +54,7 @@ public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyC
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
super.setBeanFactory(beanFactory);
|
||||
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
|
||||
throw new IllegalArgumentException(
|
||||
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
|
||||
throw new IllegalStateException("Cannot use AdvisorAutoProxyCreator without a ConfigurableListableBeanFactory");
|
||||
}
|
||||
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
|
||||
}
|
||||
|
||||
+39
-58
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -31,7 +31,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.AopInfrastructureBean;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
@@ -43,11 +42,9 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
|
||||
@@ -55,25 +52,26 @@ import org.springframework.util.StringUtils;
|
||||
* before invoking the bean itself.
|
||||
*
|
||||
* <p>This class distinguishes between "common" interceptors: shared for all proxies it
|
||||
* creates, and "specific" interceptors: unique per bean instance. There need not be any
|
||||
* common interceptors. If there are, they are set using the interceptorNames property.
|
||||
* As with {@link org.springframework.aop.framework.ProxyFactoryBean}, interceptors names
|
||||
* in the current factory are used rather than bean references to allow correct handling
|
||||
* of prototype advisors and interceptors: for example, to support stateful mixins.
|
||||
* Any advice type is supported for {@link #setInterceptorNames "interceptorNames"} entries.
|
||||
* creates, and "specific" interceptors: unique per bean instance. There need not
|
||||
* be any common interceptors. If there are, they are set using the interceptorNames
|
||||
* property. As with ProxyFactoryBean, interceptors names in the current factory
|
||||
* are used rather than bean references to allow correct handling of prototype
|
||||
* advisors and interceptors: for example, to support stateful mixins.
|
||||
* Any advice type is supported for "interceptorNames" entries.
|
||||
*
|
||||
* <p>Such auto-proxying is particularly useful if there's a large number of beans that
|
||||
* need to be wrapped with similar proxies, i.e. delegating to the same interceptors.
|
||||
* Instead of x repetitive proxy definitions for x target beans, you can register
|
||||
* one single such post processor with the bean factory to achieve the same effect.
|
||||
*
|
||||
* <p>Subclasses can apply any strategy to decide if a bean is to be proxied, e.g. by type,
|
||||
* by name, by definition details, etc. They can also return additional interceptors that
|
||||
* should just be applied to the specific bean instance. A simple concrete implementation is
|
||||
* {@link BeanNameAutoProxyCreator}, identifying the beans to be proxied via given names.
|
||||
* <p>Subclasses can apply any strategy to decide if a bean is to be proxied,
|
||||
* e.g. by type, by name, by definition details, etc. They can also return
|
||||
* additional interceptors that should just be applied to the specific bean
|
||||
* instance. The default concrete implementation is BeanNameAutoProxyCreator,
|
||||
* identifying the beans to be proxied via a list of bean names.
|
||||
*
|
||||
* <p>Any number of {@link TargetSourceCreator} implementations can be used to create
|
||||
* a custom target source: for example, to pool prototype objects. Auto-proxying will
|
||||
* a custom target source - for example, to pool prototype objects. Auto-proxying will
|
||||
* occur even if there is no advice, as long as a TargetSourceCreator specifies a custom
|
||||
* {@link org.springframework.aop.TargetSource}. If there are no TargetSourceCreators set,
|
||||
* or if none matches, a {@link org.springframework.aop.target.SingletonTargetSource}
|
||||
@@ -127,6 +125,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(64);
|
||||
|
||||
private final Set<String> targetSourcedBeans =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
|
||||
|
||||
@@ -135,8 +135,6 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<Object, Class<?>>(16);
|
||||
|
||||
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<Object, Boolean>(256);
|
||||
|
||||
|
||||
/**
|
||||
* Set whether or not the proxy should be frozen, preventing advice
|
||||
@@ -155,8 +153,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@link AdvisorAdapterRegistry} to use.
|
||||
* <p>Default is the global {@link AdvisorAdapterRegistry}.
|
||||
* Specify the AdvisorAdapterRegistry to use.
|
||||
* Default is the global AdvisorAdapterRegistry.
|
||||
* @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
|
||||
*/
|
||||
public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
|
||||
@@ -164,18 +162,18 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom {@code TargetSourceCreators} to be applied in this order.
|
||||
* If the list is empty, or they all return null, a {@link SingletonTargetSource}
|
||||
* Set custom TargetSourceCreators to be applied in this order.
|
||||
* If the list is empty, or they all return null, a SingletonTargetSource
|
||||
* will be created for each bean.
|
||||
* <p>Note that TargetSourceCreators will kick in even for target beans
|
||||
* where no advices or advisors have been found. If a {@code TargetSourceCreator}
|
||||
* returns a {@link TargetSource} for a specific bean, that bean will be proxied
|
||||
* where no advices or advisors have been found. If a TargetSourceCreator
|
||||
* returns a TargetSource for a specific bean, that bean will be proxied
|
||||
* in any case.
|
||||
* <p>{@code TargetSourceCreators} can only be invoked if this post processor is used
|
||||
* in a {@link BeanFactory} and its {@link BeanFactoryAware} callback is triggered.
|
||||
* @param targetSourceCreators the list of {@code TargetSourceCreators}.
|
||||
* Ordering is significant: The {@code TargetSource} returned from the first matching
|
||||
* {@code TargetSourceCreator} (that is, the first that returns non-null) will be used.
|
||||
* <p>TargetSourceCreators can only be invoked if this post processor is used
|
||||
* in a BeanFactory, and its BeanFactoryAware callback is used.
|
||||
* @param targetSourceCreators list of TargetSourceCreator.
|
||||
* 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) {
|
||||
this.customTargetSourceCreators = targetSourceCreators;
|
||||
@@ -206,8 +204,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the owning {@link BeanFactory}.
|
||||
* May be {@code null}, as this post-processor doesn't need to belong to a bean factory.
|
||||
* Return the owning BeanFactory.
|
||||
* May be {@code null}, as this object doesn't need to belong to a bean factory.
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
@@ -216,9 +214,6 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
@Override
|
||||
public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
|
||||
if (this.proxyTypes.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Object cacheKey = getCacheKey(beanClass, beanName);
|
||||
return this.proxyTypes.get(cacheKey);
|
||||
}
|
||||
@@ -304,23 +299,12 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
|
||||
/**
|
||||
* Build a cache key for the given bean class and bean name.
|
||||
* <p>Note: As of 4.2.3, this implementation does not return a concatenated
|
||||
* class/name String anymore but rather the most efficient cache key possible:
|
||||
* a plain bean name, prepended with {@link BeanFactory#FACTORY_BEAN_PREFIX}
|
||||
* in case of a {@code FactoryBean}; or if no bean name specified, then the
|
||||
* given bean {@code Class} as-is.
|
||||
* @param beanClass the bean class
|
||||
* @param beanName the bean name
|
||||
* @return the cache key for the given class and name
|
||||
*/
|
||||
protected Object getCacheKey(Class<?> beanClass, String beanName) {
|
||||
if (StringUtils.hasLength(beanName)) {
|
||||
return (FactoryBean.class.isAssignableFrom(beanClass) ?
|
||||
BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
|
||||
}
|
||||
else {
|
||||
return beanClass;
|
||||
}
|
||||
return beanClass.getName() + "_" + beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,8 +330,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
|
||||
if (specificInterceptors != DO_NOT_PROXY) {
|
||||
this.advisedBeans.put(cacheKey, Boolean.TRUE);
|
||||
Object proxy = createProxy(
|
||||
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
|
||||
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
|
||||
this.proxyTypes.put(cacheKey, proxy.getClass());
|
||||
return proxy;
|
||||
}
|
||||
@@ -370,7 +353,6 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
*/
|
||||
protected boolean isInfrastructureClass(Class<?> beanClass) {
|
||||
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
|
||||
Pointcut.class.isAssignableFrom(beanClass) ||
|
||||
Advisor.class.isAssignableFrom(beanClass) ||
|
||||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
|
||||
if (retVal && logger.isTraceEnabled()) {
|
||||
@@ -437,10 +419,6 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
protected Object createProxy(
|
||||
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
|
||||
|
||||
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
|
||||
}
|
||||
|
||||
ProxyFactory proxyFactory = new ProxyFactory();
|
||||
proxyFactory.copyFrom(this);
|
||||
|
||||
@@ -454,7 +432,10 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
|
||||
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
|
||||
proxyFactory.addAdvisors(advisors);
|
||||
for (Advisor advisor : advisors) {
|
||||
proxyFactory.addAdvisor(advisor);
|
||||
}
|
||||
|
||||
proxyFactory.setTargetSource(targetSource);
|
||||
customizeProxyFactory(proxyFactory);
|
||||
|
||||
@@ -509,7 +490,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
List<Object> allInterceptors = new ArrayList<Object>();
|
||||
if (specificInterceptors != null) {
|
||||
allInterceptors.addAll(Arrays.asList(specificInterceptors));
|
||||
if (commonInterceptors.length > 0) {
|
||||
if (commonInterceptors != null) {
|
||||
if (this.applyCommonInterceptorsFirst) {
|
||||
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
|
||||
}
|
||||
@@ -519,7 +500,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
int nrOfCommonInterceptors = commonInterceptors.length;
|
||||
int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0);
|
||||
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
|
||||
logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
|
||||
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
|
||||
@@ -537,8 +518,8 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
* @see #setInterceptorNames
|
||||
*/
|
||||
private Advisor[] resolveInterceptorNames() {
|
||||
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory ?
|
||||
(ConfigurableBeanFactory) this.beanFactory : null);
|
||||
ConfigurableBeanFactory cbf = (this.beanFactory instanceof ConfigurableBeanFactory) ?
|
||||
(ConfigurableBeanFactory) this.beanFactory : null;
|
||||
List<Advisor> advisors = new ArrayList<Advisor>();
|
||||
for (String beanName : this.interceptorNames) {
|
||||
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
|
||||
@@ -555,7 +536,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
|
||||
* <p>The default implementation is empty.
|
||||
* @param proxyFactory ProxyFactory that is already configured with
|
||||
* TargetSource and interfaces and will be used to create the proxy
|
||||
* immediately after this method returns
|
||||
* immediably after this method returns
|
||||
*/
|
||||
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
|
||||
}
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.framework.autoproxy;
|
||||
|
||||
import org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
|
||||
/**
|
||||
* Extension of {@link AbstractAutoProxyCreator} which implements {@link BeanFactoryAware},
|
||||
* adds exposure of the original target class for each proxied bean
|
||||
* ({@link AutoProxyUtils#ORIGINAL_TARGET_CLASS_ATTRIBUTE}),
|
||||
* and participates in an externally enforced target-class mode for any given bean
|
||||
* ({@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE}).
|
||||
* This post-processor is therefore aligned with {@link AbstractAutoProxyCreator}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.2.3
|
||||
* @see AutoProxyUtils#shouldProxyTargetClass
|
||||
* @see AutoProxyUtils#determineTargetClass
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public abstract class AbstractBeanFactoryAwareAdvisingPostProcessor extends AbstractAdvisingBeanPostProcessor
|
||||
implements BeanFactoryAware {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = (beanFactory instanceof ConfigurableListableBeanFactory ?
|
||||
(ConfigurableListableBeanFactory) beanFactory : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
|
||||
if (this.beanFactory != null) {
|
||||
AutoProxyUtils.exposeTargetClass(this.beanFactory, beanName, bean.getClass());
|
||||
}
|
||||
|
||||
ProxyFactory proxyFactory = super.prepareProxyFactory(bean, beanName);
|
||||
if (!proxyFactory.isProxyTargetClass() && this.beanFactory != null &&
|
||||
AutoProxyUtils.shouldProxyTargetClass(this.beanFactory, beanName)) {
|
||||
proxyFactory.setProxyTargetClass(true);
|
||||
}
|
||||
return proxyFactory;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,23 +35,12 @@ public abstract class AutoProxyUtils {
|
||||
* to be proxied with its target class (in case of it getting proxied in the first
|
||||
* place). The value is {@code Boolean.TRUE} or {@code Boolean.FALSE}.
|
||||
* <p>Proxy factories can set this attribute if they built a target class proxy
|
||||
* for a specific bean, and want to enforce that bean can always be cast
|
||||
* for a specific bean, and want to enforce that that bean can always be cast
|
||||
* to its target class (even if AOP advices get applied through auto-proxying).
|
||||
* @see #shouldProxyTargetClass
|
||||
*/
|
||||
public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
|
||||
|
||||
/**
|
||||
* Bean definition attribute that indicates the original target class of an
|
||||
* auto-proxied bean, e.g. to be used for the introspection of annotations
|
||||
* on the target class behind an interface-based proxy.
|
||||
* @since 4.2.3
|
||||
* @see #determineTargetClass
|
||||
*/
|
||||
public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
|
||||
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the given bean should be proxied with its target
|
||||
@@ -70,40 +59,4 @@ public abstract class AutoProxyUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the original target class for the specified bean, if possible,
|
||||
* otherwise falling back to a regular {@code getType} lookup.
|
||||
* @param beanFactory the containing ConfigurableListableBeanFactory
|
||||
* @param beanName the name of the bean
|
||||
* @return the original target class as stored in the bean definition, if any
|
||||
* @since 4.2.3
|
||||
* @see org.springframework.beans.factory.BeanFactory#getType(String)
|
||||
*/
|
||||
public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanName == null) {
|
||||
return null;
|
||||
}
|
||||
if (beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
|
||||
Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
|
||||
if (targetClass != null) {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
return beanFactory.getType(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the given target class for the specified bean, if possible.
|
||||
* @param beanFactory the containing ConfigurableListableBeanFactory
|
||||
* @param beanName the name of the bean
|
||||
* @param targetClass the corresponding target class
|
||||
* @since 4.2.3
|
||||
*/
|
||||
static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, String beanName, Class<?> targetClass) {
|
||||
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
|
||||
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,16 +19,15 @@ package org.springframework.aop.framework.autoproxy;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
|
||||
/**
|
||||
* {@code BeanPostProcessor} implementation that creates AOP proxies based on all
|
||||
* candidate {@code Advisor}s in the current {@code BeanFactory}. This class is
|
||||
* completely generic; it contains no special code to handle any particular aspects,
|
||||
* such as pooling aspects.
|
||||
* BeanPostProcessor implementation that creates AOP proxies based on all candidate
|
||||
* Advisors in the current BeanFactory. This class is completely generic; it contains
|
||||
* no special code to handle any particular aspects, such as pooling aspects.
|
||||
*
|
||||
* <p>It's possible to filter out advisors - for example, to use multiple post processors
|
||||
* of this type in the same factory - by setting the {@code usePrefix} property to true,
|
||||
* in which case only advisors beginning with the DefaultAdvisorAutoProxyCreator's bean
|
||||
* name followed by a dot (like "aapc.") will be used. This default prefix can be changed
|
||||
* from the bean name by setting the {@code advisorBeanNamePrefix} property.
|
||||
* of this type in the same factory - by setting the {@code usePrefix} property
|
||||
* to true, in which case only advisors beginning with the DefaultAdvisorAutoProxyCreator's
|
||||
* bean name followed by a dot (like "aapc.") will be used. This default prefix can be
|
||||
* changed from the bean name by setting the {@code advisorBeanNamePrefix} property.
|
||||
* The separator (.) will also be used in this case.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
@@ -41,22 +40,22 @@ public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCrea
|
||||
public final static String SEPARATOR = ".";
|
||||
|
||||
|
||||
private boolean usePrefix = false;
|
||||
private boolean usePrefix;
|
||||
|
||||
private String advisorBeanNamePrefix;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to only include advisors with a certain prefix in the bean name.
|
||||
* <p>Default is {@code false}, including all beans of type {@code Advisor}.
|
||||
* @see #setAdvisorBeanNamePrefix
|
||||
* Set whether to exclude advisors with a certain prefix
|
||||
* in the bean name.
|
||||
*/
|
||||
public void setUsePrefix(boolean usePrefix) {
|
||||
this.usePrefix = usePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether to only include advisors with a certain prefix in the bean name.
|
||||
* Return whether to exclude advisors with a certain prefix
|
||||
* in the bean name.
|
||||
*/
|
||||
public boolean isUsePrefix() {
|
||||
return this.usePrefix;
|
||||
@@ -90,7 +89,7 @@ public class DefaultAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCrea
|
||||
|
||||
|
||||
/**
|
||||
* Consider {@code Advisor} beans with the specified prefix as eligible, if activated.
|
||||
* Consider Advisor beans with the specified prefix as eligible, if activated.
|
||||
* @see #setUsePrefix
|
||||
* @see #setAdvisorBeanNamePrefix
|
||||
*/
|
||||
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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,12 +22,12 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
/**
|
||||
* Base class for monitoring interceptors, such as performance monitors.
|
||||
* Provides configurable "prefix and "suffix" properties that help to
|
||||
* classify/group performance monitoring results.
|
||||
* Provides {@code prefix} and {@code suffix} properties
|
||||
* that help to classify/group performance monitoring results.
|
||||
*
|
||||
* <p>In their {@link #invokeUnderTrace} implementation, subclasses should call the
|
||||
* {@link #createInvocationTraceName} method to create a name for the given trace,
|
||||
* including information about the method invocation along with a prefix/suffix.
|
||||
* <p>Subclasses should call the {@code createInvocationTraceName(MethodInvocation)}
|
||||
* method to create a name for the given trace that includes information about the
|
||||
* method invocation under trace along with the prefix and suffix added as appropriate.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+3
-56
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,12 +58,6 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
|
||||
*/
|
||||
private boolean hideProxyClassNames = false;
|
||||
|
||||
/**
|
||||
* Indicates whether to pass an exception to the logger.
|
||||
* @see #writeToLog(Log, String, Throwable)
|
||||
*/
|
||||
private boolean logExceptionStackTrace = true;
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to use a dynamic logger or a static logger.
|
||||
@@ -104,17 +98,6 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
|
||||
this.hideProxyClassNames = hideProxyClassNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to pass an exception to the logger, suggesting inclusion
|
||||
* of its stack trace into the log. Default is "true"; set this to "false"
|
||||
* in order to reduce the log output to just the trace message (which may
|
||||
* include the exception class name and exception message, if applicable).
|
||||
* @since 4.3.10
|
||||
*/
|
||||
public void setLogExceptionStackTrace(boolean logExceptionStackTrace) {
|
||||
this.logExceptionStackTrace = logExceptionStackTrace;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether or not logging is enabled for the particular {@code MethodInvocation}.
|
||||
@@ -188,40 +171,6 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
|
||||
return logger.isTraceEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the supplied trace message to the supplied {@code Log} instance.
|
||||
* <p>To be called by {@link #invokeUnderTrace} for enter/exit messages.
|
||||
* <p>Delegates to {@link #writeToLog(Log, String, Throwable)} as the
|
||||
* ultimate delegate that controls the underlying logger invocation.
|
||||
* @since 4.3.10
|
||||
* @see #writeToLog(Log, String, Throwable)
|
||||
*/
|
||||
protected void writeToLog(Log logger, String message) {
|
||||
writeToLog(logger, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the supplied trace message and {@link Throwable} to the
|
||||
* supplied {@code Log} instance.
|
||||
* <p>To be called by {@link #invokeUnderTrace} for enter/exit outcomes,
|
||||
* potentially including an exception. Note that an exception's stack trace
|
||||
* won't get logged when {@link #setLogExceptionStackTrace} is "false".
|
||||
* <p>By default messages are written at {@code TRACE} level. Subclasses
|
||||
* can override this method to control which level the message is written
|
||||
* at, typically also overriding {@link #isLogEnabled} accordingly.
|
||||
* @since 4.3.10
|
||||
* @see #setLogExceptionStackTrace
|
||||
* @see #isLogEnabled
|
||||
*/
|
||||
protected void writeToLog(Log logger, String message, Throwable ex) {
|
||||
if (ex != null && this.logExceptionStackTrace) {
|
||||
logger.trace(message, ex);
|
||||
}
|
||||
else {
|
||||
logger.trace(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must override this method to perform any tracing around the
|
||||
@@ -231,15 +180,13 @@ public abstract class AbstractTraceInterceptor implements MethodInterceptor, Ser
|
||||
* <p>By default, the passed-in {@code Log} instance will have log level
|
||||
* "trace" enabled. Subclasses do not have to check for this again, unless
|
||||
* they overwrite the {@code isInterceptorEnabled} method to modify
|
||||
* the default behavior, and may delegate to {@code writeToLog} for actual
|
||||
* messages to be written.
|
||||
* the default behavior.
|
||||
* @param logger the {@code Log} to write trace messages to
|
||||
* @return the result of the call to {@code MethodInvocation.proceed()}
|
||||
* @throws Throwable if the call to {@code MethodInvocation.proceed()}
|
||||
* encountered any errors
|
||||
* @see #isInterceptorEnabled
|
||||
* @see #isLogEnabled
|
||||
* @see #writeToLog(Log, String)
|
||||
* @see #writeToLog(Log, String, Throwable)
|
||||
*/
|
||||
protected abstract Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable;
|
||||
|
||||
|
||||
+31
-122
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,12 +31,9 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.core.task.support.TaskExecutorAdapter;
|
||||
import org.springframework.lang.UsesJava8;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -61,15 +58,6 @@ import org.springframework.util.concurrent.ListenableFuture;
|
||||
*/
|
||||
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* The default name of the {@link TaskExecutor} bean to pick up: "taskExecutor".
|
||||
* <p>Note that the initial lookup happens by type; this is just the fallback
|
||||
* in case of multiple executor beans found in the context.
|
||||
* @since 4.2.6
|
||||
*/
|
||||
public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor";
|
||||
|
||||
|
||||
// Java 8's CompletableFuture type present?
|
||||
private static final boolean completableFuturePresent = ClassUtils.isPresent(
|
||||
"java.util.concurrent.CompletableFuture", AsyncExecutionInterceptor.class.getClassLoader());
|
||||
@@ -79,7 +67,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<Method, AsyncTaskExecutor>(16);
|
||||
|
||||
private volatile Executor defaultExecutor;
|
||||
private Executor defaultExecutor;
|
||||
|
||||
private AsyncUncaughtExceptionHandler exceptionHandler;
|
||||
|
||||
@@ -87,22 +75,10 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
|
||||
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link AsyncExecutionAspectSupport} with the given exception handler.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
* Create a new {@link AsyncExecutionAspectSupport}, using the provided default
|
||||
* executor unless individual async methods indicate via qualifier that a more
|
||||
* specific executor should be used.
|
||||
* @param defaultExecutor the executor to use when executing asynchronous methods
|
||||
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
@@ -110,16 +86,23 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
|
||||
this(defaultExecutor, new SimpleAsyncUncaughtExceptionHandler());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Supply the executor to be used when executing async methods.
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to, unless a more specific
|
||||
* executor has been requested via a qualifier on the async method, in which case the
|
||||
* executor will be looked up at invocation time against the enclosing bean factory
|
||||
* @see #getExecutorQualifier(Method)
|
||||
* @param defaultExecutor the {@code Executor} (typically a Spring {@code
|
||||
* AsyncTaskExecutor} or {@link java.util.concurrent.ExecutorService}) to delegate to
|
||||
* unless a more specific executor has been requested via a qualifier on the async
|
||||
* method, in which case the executor will be looked up at invocation time against the
|
||||
* enclosing bean factory.
|
||||
* @see #getExecutorQualifier
|
||||
* @see #setBeanFactory(BeanFactory)
|
||||
* @see #getDefaultExecutor(BeanFactory)
|
||||
*/
|
||||
public void setExecutor(Executor defaultExecutor) {
|
||||
this.defaultExecutor = defaultExecutor;
|
||||
@@ -134,10 +117,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link BeanFactory} to be used when looking up executors by qualifier
|
||||
* or when relying on the default executor lookup algorithm.
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
* @see #getDefaultExecutor(BeanFactory)
|
||||
* Set the {@link BeanFactory} to be used when looking up executors by qualifier.
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
@@ -148,32 +128,26 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
/**
|
||||
* Determine the specific executor to use when executing the given method.
|
||||
* Should preferably return an {@link AsyncListenableTaskExecutor} implementation.
|
||||
* @return the executor to use (or {@code null}, but just if no default executor is available)
|
||||
* @return the executor to use (or {@code null}, but just if no default executor has been set)
|
||||
*/
|
||||
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
|
||||
AsyncTaskExecutor executor = this.executors.get(method);
|
||||
if (executor == null) {
|
||||
Executor targetExecutor;
|
||||
Executor executorToUse = this.defaultExecutor;
|
||||
String qualifier = getExecutorQualifier(method);
|
||||
if (StringUtils.hasLength(qualifier)) {
|
||||
targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
|
||||
}
|
||||
else {
|
||||
targetExecutor = this.defaultExecutor;
|
||||
if (targetExecutor == null) {
|
||||
synchronized (this.executors) {
|
||||
if (this.defaultExecutor == null) {
|
||||
this.defaultExecutor = getDefaultExecutor(this.beanFactory);
|
||||
}
|
||||
targetExecutor = this.defaultExecutor;
|
||||
}
|
||||
if (this.beanFactory == null) {
|
||||
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
}
|
||||
executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
this.beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
if (targetExecutor == null) {
|
||||
else if (executorToUse == null) {
|
||||
return null;
|
||||
}
|
||||
executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
|
||||
(AsyncListenableTaskExecutor) targetExecutor : new TaskExecutorAdapter(targetExecutor));
|
||||
executor = (executorToUse instanceof AsyncListenableTaskExecutor ?
|
||||
(AsyncListenableTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
|
||||
this.executors.put(method, executor);
|
||||
}
|
||||
return executor;
|
||||
@@ -186,76 +160,11 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* been specified and that the {@linkplain #setExecutor(Executor) default executor}
|
||||
* should be used.
|
||||
* @param method the method to inspect for executor qualifier metadata
|
||||
* @return the qualifier if specified, otherwise empty String or {@code null}
|
||||
* @return the qualifier if specified, otherwise empty string or {@code null}
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
*/
|
||||
protected abstract String getExecutorQualifier(Method method);
|
||||
|
||||
/**
|
||||
* Retrieve a target executor for the given qualifier.
|
||||
* @param qualifier the qualifier to resolve
|
||||
* @return the target executor, or {@code null} if none available
|
||||
* @since 4.2.6
|
||||
* @see #getExecutorQualifier(Method)
|
||||
*/
|
||||
protected Executor findQualifiedExecutor(BeanFactory beanFactory, String qualifier) {
|
||||
if (beanFactory == null) {
|
||||
throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
}
|
||||
return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve or build a default executor for this advice instance.
|
||||
* An executor returned from here will be cached for further use.
|
||||
* <p>The default implementation searches for a unique {@link TaskExecutor} bean
|
||||
* in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
|
||||
* If neither of the two is resolvable, this implementation will return {@code null}.
|
||||
* @param beanFactory the BeanFactory to use for a default executor lookup
|
||||
* @return the default executor, or {@code null} if none available
|
||||
* @since 4.2.6
|
||||
* @see #findQualifiedExecutor(BeanFactory, String)
|
||||
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
|
||||
*/
|
||||
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
|
||||
if (beanFactory != null) {
|
||||
try {
|
||||
// Search for TaskExecutor bean... not plain Executor since that would
|
||||
// match with ScheduledExecutorService as well, which is unusable for
|
||||
// our purposes here. TaskExecutor is more clearly designed for it.
|
||||
return beanFactory.getBean(TaskExecutor.class);
|
||||
}
|
||||
catch (NoUniqueBeanDefinitionException ex) {
|
||||
logger.debug("Could not find unique TaskExecutor bean", ex);
|
||||
try {
|
||||
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex2) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("More than one TaskExecutor bean found within the context, and none is named " +
|
||||
"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
|
||||
"as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
logger.debug("Could not find default TaskExecutor bean", ex);
|
||||
try {
|
||||
return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex2) {
|
||||
logger.info("No task executor bean found for async processing: " +
|
||||
"no bean of type TaskExecutor and no bean named 'taskExecutor' either");
|
||||
}
|
||||
// Giving up -> either using local default executor or none at all...
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegate for actually executing the given task with the chosen executor.
|
||||
* @param task the task to execute
|
||||
|
||||
+8
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,11 +26,9 @@ import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -67,27 +65,22 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code AsyncExecutionInterceptor}.
|
||||
* @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to;
|
||||
* as of 4.2.6, a local executor for this interceptor will be built otherwise
|
||||
* or {@link java.util.concurrent.ExecutorService}) to delegate to
|
||||
* @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
|
||||
super(defaultExecutor, exceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
|
||||
*/
|
||||
public AsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the given method invocation, submit the actual calling of the method to
|
||||
@@ -143,20 +136,6 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport imple
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation searches for a unique {@link org.springframework.core.task.TaskExecutor}
|
||||
* bean in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
|
||||
* If neither of the two is resolvable (e.g. if no {@code BeanFactory} was configured at all),
|
||||
* this implementation falls back to a newly created {@link SimpleAsyncTaskExecutor} instance
|
||||
* for local use if no default could be found.
|
||||
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
|
||||
*/
|
||||
@Override
|
||||
protected Executor getDefaultExecutor(BeanFactory beanFactory) {
|
||||
Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
|
||||
return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
+45
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -128,20 +128,20 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
/**
|
||||
* The default message used for writing method entry messages.
|
||||
*/
|
||||
private static final String DEFAULT_ENTER_MESSAGE = "Entering method '" +
|
||||
PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
private static final String DEFAULT_ENTER_MESSAGE =
|
||||
"Entering method '" + PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
|
||||
/**
|
||||
* The default message used for writing method exit messages.
|
||||
*/
|
||||
private static final String DEFAULT_EXIT_MESSAGE = "Exiting method '" +
|
||||
PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
private static final String DEFAULT_EXIT_MESSAGE =
|
||||
"Exiting method '" + PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
|
||||
/**
|
||||
* The default message used for writing exception messages.
|
||||
*/
|
||||
private static final String DEFAULT_EXCEPTION_MESSAGE = "Exception thrown in method '" +
|
||||
PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
private static final String DEFAULT_EXCEPTION_MESSAGE =
|
||||
"Exception thrown in method '" + PLACEHOLDER_METHOD_NAME + "' of class [" + PLACEHOLDER_TARGET_CLASS_NAME + "]";
|
||||
|
||||
/**
|
||||
* The {@code Pattern} used to match placeholders.
|
||||
@@ -182,14 +182,14 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
* </ul>
|
||||
*/
|
||||
public void setEnterMessage(String enterMessage) throws IllegalArgumentException {
|
||||
Assert.hasText(enterMessage, "enterMessage must not be empty");
|
||||
Assert.hasText(enterMessage, "'enterMessage' must not be empty");
|
||||
checkForInvalidPlaceholders(enterMessage);
|
||||
Assert.doesNotContain(enterMessage, PLACEHOLDER_RETURN_VALUE,
|
||||
"enterMessage cannot contain placeholder " + PLACEHOLDER_RETURN_VALUE);
|
||||
"enterMessage cannot contain placeholder [" + PLACEHOLDER_RETURN_VALUE + "]");
|
||||
Assert.doesNotContain(enterMessage, PLACEHOLDER_EXCEPTION,
|
||||
"enterMessage cannot contain placeholder " + PLACEHOLDER_EXCEPTION);
|
||||
"enterMessage cannot contain placeholder [" + PLACEHOLDER_EXCEPTION + "]");
|
||||
Assert.doesNotContain(enterMessage, PLACEHOLDER_INVOCATION_TIME,
|
||||
"enterMessage cannot contain placeholder " + PLACEHOLDER_INVOCATION_TIME);
|
||||
"enterMessage cannot contain placeholder [" + PLACEHOLDER_INVOCATION_TIME + "]");
|
||||
this.enterMessage = enterMessage;
|
||||
}
|
||||
|
||||
@@ -206,10 +206,10 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
* </ul>
|
||||
*/
|
||||
public void setExitMessage(String exitMessage) {
|
||||
Assert.hasText(exitMessage, "exitMessage must not be empty");
|
||||
Assert.hasText(exitMessage, "'exitMessage' must not be empty");
|
||||
checkForInvalidPlaceholders(exitMessage);
|
||||
Assert.doesNotContain(exitMessage, PLACEHOLDER_EXCEPTION,
|
||||
"exitMessage cannot contain placeholder" + PLACEHOLDER_EXCEPTION);
|
||||
"exitMessage cannot contain placeholder [" + PLACEHOLDER_EXCEPTION + "]");
|
||||
this.exitMessage = exitMessage;
|
||||
}
|
||||
|
||||
@@ -225,10 +225,12 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
* </ul>
|
||||
*/
|
||||
public void setExceptionMessage(String exceptionMessage) {
|
||||
Assert.hasText(exceptionMessage, "exceptionMessage must not be empty");
|
||||
Assert.hasText(exceptionMessage, "'exceptionMessage' must not be empty");
|
||||
checkForInvalidPlaceholders(exceptionMessage);
|
||||
Assert.doesNotContain(exceptionMessage, PLACEHOLDER_RETURN_VALUE,
|
||||
"exceptionMessage cannot contain placeholder " + PLACEHOLDER_RETURN_VALUE);
|
||||
"exceptionMessage cannot contain placeholder [" + PLACEHOLDER_RETURN_VALUE + "]");
|
||||
Assert.doesNotContain(exceptionMessage, PLACEHOLDER_INVOCATION_TIME,
|
||||
"exceptionMessage cannot contain placeholder [" + PLACEHOLDER_INVOCATION_TIME + "]");
|
||||
this.exceptionMessage = exceptionMessage;
|
||||
}
|
||||
|
||||
@@ -244,7 +246,7 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
*/
|
||||
@Override
|
||||
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
|
||||
String name = ClassUtils.getQualifiedMethodName(invocation.getMethod());
|
||||
String name = invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName();
|
||||
StopWatch stopWatch = new StopWatch(name);
|
||||
Object returnValue = null;
|
||||
boolean exitThroughException = false;
|
||||
@@ -260,8 +262,8 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
stopWatch.stop();
|
||||
}
|
||||
exitThroughException = true;
|
||||
writeToLog(logger, replacePlaceholders(
|
||||
this.exceptionMessage, invocation, null, ex, stopWatch.getTotalTimeMillis()), ex);
|
||||
writeToLog(logger,
|
||||
replacePlaceholders(this.exceptionMessage, invocation, null, ex, stopWatch.getTotalTimeMillis()), ex);
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
@@ -269,12 +271,35 @@ public class CustomizableTraceInterceptor extends AbstractTraceInterceptor {
|
||||
if (stopWatch.isRunning()) {
|
||||
stopWatch.stop();
|
||||
}
|
||||
writeToLog(logger, replacePlaceholders(
|
||||
this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
|
||||
writeToLog(logger,
|
||||
replacePlaceholders(this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the supplied message to the supplied {@code Log} instance.
|
||||
* @see #writeToLog(org.apache.commons.logging.Log, String, Throwable)
|
||||
*/
|
||||
protected void writeToLog(Log logger, String message) {
|
||||
writeToLog(logger, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the supplied message and {@link Throwable} to the
|
||||
* supplied {@code Log} instance. By default messages are written
|
||||
* at {@code TRACE} level. Sub-classes can override this method
|
||||
* to control which level the message is written at.
|
||||
*/
|
||||
protected void writeToLog(Log logger, String message, Throwable ex) {
|
||||
if (ex != null) {
|
||||
logger.trace(message, ex);
|
||||
}
|
||||
else {
|
||||
logger.trace(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the placeholders in the given message with the supplied values,
|
||||
* or values derived from those supplied.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -121,7 +121,7 @@ public class JamonPerformanceMonitorInterceptor extends AbstractMonitoringInterc
|
||||
finally {
|
||||
monitor.stop();
|
||||
if (!this.trackAllInvocations || isLogEnabled(logger)) {
|
||||
writeToLog(logger, "JAMon performance statistics for method [" + name + "]:\n" + monitor);
|
||||
logger.trace("JAMon performance statistics for method [" + name + "]:\n" + monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,7 +63,7 @@ public class PerformanceMonitorInterceptor extends AbstractMonitoringInterceptor
|
||||
}
|
||||
finally {
|
||||
stopWatch.stop();
|
||||
writeToLog(logger, stopWatch.shortSummary());
|
||||
logger.trace(stopWatch.shortSummary());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -55,14 +55,14 @@ public class SimpleTraceInterceptor extends AbstractTraceInterceptor {
|
||||
@Override
|
||||
protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
|
||||
String invocationDescription = getInvocationDescription(invocation);
|
||||
writeToLog(logger, "Entering " + invocationDescription);
|
||||
logger.trace("Entering " + invocationDescription);
|
||||
try {
|
||||
Object rval = invocation.proceed();
|
||||
writeToLog(logger, "Exiting " + invocationDescription);
|
||||
logger.trace("Exiting " + invocationDescription);
|
||||
return rval;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
writeToLog(logger, "Exception thrown in " + invocationDescription, ex);
|
||||
logger.trace("Exception thrown in " + invocationDescription, ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -89,7 +89,7 @@ public abstract class ScopedProxyUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the bean name that is used within the scoped proxy to reference the target bean.
|
||||
* Generates the bean name that is used within the scoped proxy to reference the target bean.
|
||||
* @param originalBeanName the original name of bean
|
||||
* @return the generated bean to be used to reference the target bean
|
||||
*/
|
||||
|
||||
+9
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,7 +23,6 @@ import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -46,7 +45,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private transient volatile Advice advice;
|
||||
private transient Advice advice;
|
||||
|
||||
private transient volatile Object adviceMonitor = new Object();
|
||||
|
||||
@@ -73,23 +72,8 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
resetAdviceMonitor();
|
||||
}
|
||||
|
||||
private void resetAdviceMonitor() {
|
||||
if (this.beanFactory instanceof ConfigurableBeanFactory) {
|
||||
this.adviceMonitor = ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex();
|
||||
}
|
||||
else {
|
||||
this.adviceMonitor = new Object();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a particular instance of the target advice directly,
|
||||
* avoiding lazy resolution in {@link #getAdvice()}.
|
||||
* @since 3.1
|
||||
*/
|
||||
public void setAdvice(Advice advice) {
|
||||
synchronized (this.adviceMonitor) {
|
||||
this.advice = advice;
|
||||
@@ -98,42 +82,18 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
|
||||
@Override
|
||||
public Advice getAdvice() {
|
||||
Advice advice = this.advice;
|
||||
if (advice != null || this.adviceBeanName == null) {
|
||||
return advice;
|
||||
}
|
||||
|
||||
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
if (this.beanFactory.isSingleton(this.adviceBeanName)) {
|
||||
// Rely on singleton semantics provided by the factory.
|
||||
advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
this.advice = advice;
|
||||
return advice;
|
||||
}
|
||||
else {
|
||||
// No singleton guarantees from the factory -> let's lock locally but
|
||||
// reuse the factory's singleton lock, just in case a lazy dependency
|
||||
// of our advice bean happens to trigger the singleton lock implicitly...
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (this.advice == null) {
|
||||
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
}
|
||||
return this.advice;
|
||||
synchronized (this.adviceMonitor) {
|
||||
if (this.advice == null && this.adviceBeanName != null) {
|
||||
Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
|
||||
this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
|
||||
}
|
||||
return this.advice;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(getClass().getName());
|
||||
sb.append(": advice ");
|
||||
if (this.adviceBeanName != null) {
|
||||
sb.append("bean '").append(this.adviceBeanName).append("'");
|
||||
}
|
||||
else {
|
||||
sb.append(this.advice);
|
||||
}
|
||||
return sb.toString();
|
||||
return getClass().getName() + ": advice bean '" + getAdviceBeanName() + "'";
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +106,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu
|
||||
ois.defaultReadObject();
|
||||
|
||||
// Initialize transient fields.
|
||||
resetAdviceMonitor();
|
||||
this.adviceMonitor = new Object();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -130,8 +129,8 @@ public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPo
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return ((targetClass != null && matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass))) ||
|
||||
matchesPattern(ClassUtils.getQualifiedMethodName(method)));
|
||||
return ((targetClass != null && matchesPattern(targetClass.getName() + "." + method.getName())) ||
|
||||
matchesPattern(method.getDeclaringClass().getName() + "." + method.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.springframework.aop.support;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -35,7 +34,6 @@ import org.springframework.aop.PointcutAdvisor;
|
||||
import org.springframework.aop.SpringProxy;
|
||||
import org.springframework.aop.TargetClassAware;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -114,30 +112,6 @@ public abstract class AopUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an invocable method on the target type: either the given method itself
|
||||
* if actually exposed on the target type, or otherwise a corresponding method
|
||||
* on one of the target type's interfaces or on the target type itself.
|
||||
* @param method the method to check
|
||||
* @param targetType the target type to search methods on (typically an AOP proxy)
|
||||
* @return a corresponding invocable method on the target type
|
||||
* @throws IllegalStateException if the given method is not invocable on the given
|
||||
* target type (typically due to a proxy mismatch)
|
||||
* @since 4.3
|
||||
* @see MethodIntrospector#selectInvocableMethod(Method, Class)
|
||||
*/
|
||||
public static Method selectInvocableMethod(Method method, Class<?> targetType) {
|
||||
Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType);
|
||||
if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) &&
|
||||
SpringProxy.class.isAssignableFrom(targetType)) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Need to invoke method '%s' found on proxy for target class '%s' but cannot " +
|
||||
"be delegated to target bean. Switch its visibility to package or protected.",
|
||||
method.getName(), method.getDeclaringClass().getSimpleName()));
|
||||
}
|
||||
return methodToUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method is an "equals" method.
|
||||
* @see java.lang.Object#equals
|
||||
@@ -222,11 +196,6 @@ public abstract class AopUtils {
|
||||
}
|
||||
|
||||
MethodMatcher methodMatcher = pc.getMethodMatcher();
|
||||
if (methodMatcher == MethodMatcher.TRUE) {
|
||||
// No need to iterate the methods if we're matching any method anyway...
|
||||
return true;
|
||||
}
|
||||
|
||||
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
|
||||
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
|
||||
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
|
||||
@@ -235,7 +204,7 @@ public abstract class AopUtils {
|
||||
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
|
||||
classes.add(targetClass);
|
||||
for (Class<?> clazz : classes) {
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Method method : methods) {
|
||||
if ((introductionAwareMethodMatcher != null &&
|
||||
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -22,6 +22,7 @@ import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Convenient class for building up pointcuts. All methods return
|
||||
@@ -187,14 +188,21 @@ public class ComposablePointcut implements Pointcut, Serializable {
|
||||
if (!(other instanceof ComposablePointcut)) {
|
||||
return false;
|
||||
}
|
||||
ComposablePointcut otherPointcut = (ComposablePointcut) other;
|
||||
return (this.classFilter.equals(otherPointcut.classFilter) &&
|
||||
this.methodMatcher.equals(otherPointcut.methodMatcher));
|
||||
ComposablePointcut that = (ComposablePointcut) other;
|
||||
return ObjectUtils.nullSafeEquals(that.classFilter, this.classFilter) &&
|
||||
ObjectUtils.nullSafeEquals(that.methodMatcher, this.methodMatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.classFilter.hashCode() * 37 + this.methodMatcher.hashCode();
|
||||
int code = 17;
|
||||
if (this.classFilter != null) {
|
||||
code = 37 * code + this.classFilter.hashCode();
|
||||
}
|
||||
if (this.methodMatcher != null) {
|
||||
code = 37 * code + this.methodMatcher.hashCode();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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,6 +22,8 @@ import java.lang.reflect.Method;
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.core.ControlFlow;
|
||||
import org.springframework.core.ControlFlowFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -32,7 +34,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @see org.springframework.core.ControlFlow
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher, Serializable {
|
||||
@@ -41,7 +43,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
|
||||
private String methodName;
|
||||
|
||||
private volatile int evaluations;
|
||||
private int evaluations;
|
||||
|
||||
|
||||
/**
|
||||
@@ -53,11 +55,11 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new pointcut that matches all calls below the given method
|
||||
* in the given class. If no method name is given, matches all control flows
|
||||
* below the given class.
|
||||
* Construct a new pointcut that matches all calls below the
|
||||
* given method in the given class. If the method name is null,
|
||||
* matches all control flows below that class.
|
||||
* @param clazz the clazz
|
||||
* @param methodName the name of the method (may be {@code null})
|
||||
* @param methodName the name of the method
|
||||
*/
|
||||
public ControlFlowPointcut(Class<?> clazz, String methodName) {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
@@ -89,23 +91,17 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
this.evaluations++;
|
||||
|
||||
for (StackTraceElement element : new Throwable().getStackTrace()) {
|
||||
if (element.getClassName().equals(this.clazz.getName()) &&
|
||||
(this.methodName == null || element.getMethodName().equals(this.methodName))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
++this.evaluations;
|
||||
ControlFlow cflow = ControlFlowFactory.createControlFlow();
|
||||
return (this.methodName != null) ? cflow.under(this.clazz, this.methodName) : cflow.under(this.clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* It's useful to know how many times we've fired, for optimization.
|
||||
*/
|
||||
public int getEvaluations() {
|
||||
return this.evaluations;
|
||||
return evaluations;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +115,6 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
@@ -134,7 +129,8 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int code = this.clazz.hashCode();
|
||||
int code = 17;
|
||||
code = 37 * code + this.clazz.hashCode();
|
||||
if (this.methodName != null) {
|
||||
code = 37 * code + this.methodName.hashCode();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -138,7 +138,7 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
return this.mm1.matches(method, targetClass, args) || this.mm2.matches(method, targetClass, args);
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public abstract class MethodMatchers {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// Because a dynamic intersection may be composed of a static and dynamic part,
|
||||
// we must avoid calling the 3-arg matches method on a dynamic matcher, as
|
||||
// it will probably be an unsupported operation.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* 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.
|
||||
@@ -27,7 +27,7 @@ import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
/**
|
||||
* Pointcut bean for simple method name matches, as alternative to regexp patterns.
|
||||
* Does not handle overloaded methods: all methods with a given name will be eligible.
|
||||
* Does not handle overloaded methods: all methods *with a given name will be eligible.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,7 +71,7 @@ public abstract class Pointcuts {
|
||||
* @param args arguments to the method
|
||||
* @return whether there's a runtime match
|
||||
*/
|
||||
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object... args) {
|
||||
public static boolean matches(Pointcut pointcut, Method method, Class<?> targetClass, Object[] args) {
|
||||
Assert.notNull(pointcut, "Pointcut must not be null");
|
||||
if (pointcut == Pointcut.TRUE) {
|
||||
return true;
|
||||
@@ -98,9 +98,9 @@ public abstract class Pointcuts {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return (method.getName().startsWith("set") &&
|
||||
method.getParameterTypes().length == 1 &&
|
||||
method.getReturnType() == Void.TYPE);
|
||||
return method.getName().startsWith("set") &&
|
||||
method.getParameterTypes().length == 1 &&
|
||||
method.getReturnType() == Void.TYPE;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
@@ -119,8 +119,8 @@ public abstract class Pointcuts {
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, Class<?> targetClass) {
|
||||
return (method.getName().startsWith("get") &&
|
||||
method.getParameterTypes().length == 0);
|
||||
return method.getName().startsWith("get") &&
|
||||
method.getParameterTypes().length == 0;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,7 +32,7 @@ public abstract class StaticMethodMatcher implements MethodMatcher {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
|
||||
public final boolean matches(Method method, Class<?> targetClass, Object[] args) {
|
||||
// should never be invoked because isRuntime() returns false
|
||||
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
|
||||
}
|
||||
|
||||
+18
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 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.
|
||||
@@ -22,6 +22,7 @@ import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.MethodMatcher;
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Simple Pointcut that looks for a specific Java 5 annotation
|
||||
@@ -45,15 +46,16 @@ public class AnnotationMatchingPointcut implements Pointcut {
|
||||
* @param classAnnotationType the annotation type to look for at the class level
|
||||
*/
|
||||
public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType) {
|
||||
this(classAnnotationType, false);
|
||||
this.classFilter = new AnnotationClassFilter(classAnnotationType);
|
||||
this.methodMatcher = MethodMatcher.TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AnnotationMatchingPointcut for the given annotation type.
|
||||
* @param classAnnotationType the annotation type to look for at the class level
|
||||
* @param checkInherited whether to also check the superclasses and interfaces
|
||||
* as well as meta-annotations for the annotation type
|
||||
* @see AnnotationClassFilter#AnnotationClassFilter(Class, boolean)
|
||||
* @param checkInherited whether to explicitly check the superclasses and
|
||||
* interfaces for the annotation type as well (even if the annotation type
|
||||
* is not marked as inherited itself)
|
||||
*/
|
||||
public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType, boolean checkInherited) {
|
||||
this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited);
|
||||
@@ -107,14 +109,21 @@ public class AnnotationMatchingPointcut implements Pointcut {
|
||||
if (!(other instanceof AnnotationMatchingPointcut)) {
|
||||
return false;
|
||||
}
|
||||
AnnotationMatchingPointcut otherPointcut = (AnnotationMatchingPointcut) other;
|
||||
return (this.classFilter.equals(otherPointcut.classFilter) &&
|
||||
this.methodMatcher.equals(otherPointcut.methodMatcher));
|
||||
AnnotationMatchingPointcut that = (AnnotationMatchingPointcut) other;
|
||||
return ObjectUtils.nullSafeEquals(that.classFilter, this.classFilter) &&
|
||||
ObjectUtils.nullSafeEquals(that.methodMatcher, this.methodMatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.classFilter.hashCode() * 37 + this.methodMatcher.hashCode();
|
||||
int code = 17;
|
||||
if (this.classFilter != null) {
|
||||
code = 37 * code + this.classFilter.hashCode();
|
||||
}
|
||||
if (this.methodMatcher != null) {
|
||||
code = 37 * code + this.methodMatcher.hashCode();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ public abstract class AbstractBeanFactoryBasedTargetSource implements TargetSour
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
if (other == null || !getClass().equals(other.getClass())) {
|
||||
return false;
|
||||
}
|
||||
AbstractBeanFactoryBasedTargetSource otherTargetSource = (AbstractBeanFactoryBasedTargetSource) other;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,7 @@ import org.springframework.aop.TargetSource;
|
||||
public abstract class AbstractRefreshableTargetSource implements TargetSource, Refreshable {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected Object targetObject;
|
||||
|
||||
|
||||
@@ -6,5 +6,4 @@ http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframewor
|
||||
http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd
|
||||
http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd
|
||||
http\://www.springframework.org/schema/aop/spring-aop-4.2.xsd=org/springframework/aop/config/spring-aop-4.2.xsd
|
||||
http\://www.springframework.org/schema/aop/spring-aop-4.3.xsd=org/springframework/aop/config/spring-aop-4.3.xsd
|
||||
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.3.xsd
|
||||
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.2.xsd
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/aop"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/aop"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.3.xsd"/>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements for the Spring Framework's AOP support.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="config">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A section (compartmentalization) of AOP-specific configuration (including
|
||||
aspects, pointcuts, etc).
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="pointcut" type="pointcutType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A named pointcut definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.aop.Advisor"><![CDATA[
|
||||
A named advisor definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="aspect" type="aspectType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A named aspect definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Are class-based (CGLIB) proxies to be created? By default, standard
|
||||
Java interface-based proxies are created.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Indicate that the proxy should be exposed by the AOP framework as a
|
||||
ThreadLocal for retrieval via the AopContext class. Off by default,
|
||||
i.e. no guarantees that AopContext access will work.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="aspectj-autoproxy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><![CDATA[
|
||||
Enables the use of the @AspectJ style of Spring AOP.
|
||||
|
||||
See org.springframework.context.annotation.EnableAspectJAutoProxy Javadoc
|
||||
for information on code-based alternatives to this XML element.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="include" type="includeType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Indicates that only @AspectJ beans with names matched by the (regex)
|
||||
pattern will be considered as defining aspects to use for Spring autoproxying.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Are class-based (CGLIB) proxies to be created? By default, standard
|
||||
Java interface-based proxies are created.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Indicate that the proxy should be exposed by the AOP framework as a
|
||||
ThreadLocal for retrieval via the AopContext class. Off by default,
|
||||
i.e. no guarantees that AopContext access will work.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="scoped-proxy">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.aop.scope.ScopedProxyFactoryBean"><![CDATA[
|
||||
Marks a bean definition as being a scoped proxy.
|
||||
|
||||
A bean marked as such will be exposed via a proxy, with the 'real'
|
||||
bean instance being retrieved from some other source (such as a
|
||||
HttpSession) as and when required.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="true">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Are class-based (CGLIB) proxies to be created? This is the default; in order to
|
||||
switch to standard Java interface-based proxies, turn this flag to "false".
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="aspectType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:element name="pointcut" type="pointcutType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A named pointcut definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="declare-parents" type="declareParentsType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Allows this aspect to introduce additional interfaces that the advised
|
||||
object will transparently implement.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="before" type="basicAdviceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A before advice definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="after" type="basicAdviceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
An after advice definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="after-returning" type="afterReturningAdviceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
An after-returning advice definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="after-throwing" type="afterThrowingAdviceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
An after-throwing advice definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element name="around" type="basicAdviceType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
An around advice definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The unique identifier for an aspect.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the (backing) bean that encapsulates the aspect.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order" type="xsd:token">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
|
||||
Controls the ordering of the execution of this aspect when multiple
|
||||
advice executes at a specific joinpoint.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="includeType">
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:java.util.regex.Pattern"><![CDATA[
|
||||
The regular expression defining which beans are to be included in the
|
||||
list of @AspectJ beans; beans with names matched by the pattern will
|
||||
be included.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="pointcutType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.aop.Pointcut"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The unique identifier for a pointcut.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="expression" use="required" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The pointcut expression.
|
||||
|
||||
For example : 'execution(* com.xyz.myapp.service.*.*(..))'
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="declareParentsType">
|
||||
<xsd:attribute name="types-matching" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.aop.aspectj.TypePatternClassFilter"><![CDATA[
|
||||
The AspectJ type expression that defines what types (classes) the
|
||||
introduction is restricted to.
|
||||
|
||||
An example would be 'org.springframework.beans.ITestBean+'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="implement-interface" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:java.lang.Class"><![CDATA[
|
||||
The fully qualified name of the interface that will be introduced.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="default-impl" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:java.lang.Class"><![CDATA[
|
||||
The fully qualified name of the class that will be instantiated to serve
|
||||
as the default implementation of the introduced interface.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="delegate-ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A reference to the bean that will serve
|
||||
as the default implementation of the introduced interface.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref"/>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="basicAdviceType">
|
||||
<xsd:attribute name="pointcut" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The associated pointcut expression.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of an associated pointcut definition.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.aop.Pointcut"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="method" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the method that defines the logic of the advice.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="arg-names" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The comma-delimited list of advice method argument (parameter) names
|
||||
that will be matched from pointcut parameters.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="afterReturningAdviceType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="basicAdviceType">
|
||||
<xsd:attribute name="returning" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the method parameter to which the return value must
|
||||
be passed.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="afterThrowingAdviceType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="basicAdviceType">
|
||||
<xsd:attribute name="throwing" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the method parameter to which the thrown exception must
|
||||
be passed.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="advisorType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation>
|
||||
<tool:exports type="org.springframework.aop.Advisor"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="advice-ref" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A reference to an advice bean.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.aopalliance.aop.Advice"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="pointcut" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A pointcut expression.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
A reference to a pointcut definition.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order" type="xsd:token">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
|
||||
Controls the ordering of the execution of this advice when multiple
|
||||
advice executes at a specific joinpoint.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="pointcutRefType">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.aop.Pointcut"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
</xsd:schema>
|
||||
+1
-2
@@ -307,8 +307,7 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
try {
|
||||
discoverer.getParameterNames(m);
|
||||
fail("Expecting " + exceptionType.getName() + " with message '" + message + "'");
|
||||
}
|
||||
catch (RuntimeException expected) {
|
||||
} catch (RuntimeException expected) {
|
||||
assertEquals("Expecting exception of type " + exceptionType.getName(),
|
||||
exceptionType, expected.getClass());
|
||||
assertEquals("Exception message does not match expected", message, expected.getMessage());
|
||||
|
||||
+37
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -53,15 +53,17 @@ public final class AspectJExpressionPointcutTests {
|
||||
|
||||
private Method setSomeNumber;
|
||||
|
||||
private Method isPostProcessed;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
setAge = TestBean.class.getMethod("setAge", int.class);
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", Number.class);
|
||||
getAge = TestBean.class.getMethod("getAge", (Class<?>[])null);
|
||||
setAge = TestBean.class.getMethod("setAge", new Class[]{int.class});
|
||||
setSomeNumber = TestBean.class.getMethod("setSomeNumber", new Class[]{Number.class});
|
||||
isPostProcessed = TestBean.class.getMethod("isPostProcessed", (Class[]) null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMatchExplicit() {
|
||||
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
|
||||
@@ -109,9 +111,21 @@ public final class AspectJExpressionPointcutTests {
|
||||
testThisOrTarget("target");
|
||||
}
|
||||
|
||||
public static class OtherIOther implements IOther {
|
||||
|
||||
@Override
|
||||
public void absquatulate() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This and target are equivalent. Really instanceof pointcuts.
|
||||
* @param which this or target
|
||||
* @throws Exception
|
||||
* @throws NoSuchMethodException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
private void testThisOrTarget(String which) throws SecurityException, NoSuchMethodException {
|
||||
String matchesTestBean = which + "(org.springframework.tests.sample.beans.TestBean)";
|
||||
@@ -124,8 +138,11 @@ public final class AspectJExpressionPointcutTests {
|
||||
|
||||
assertTrue(testBeanPc.matches(TestBean.class));
|
||||
assertTrue(testBeanPc.matches(getAge, TestBean.class));
|
||||
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
|
||||
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
|
||||
assertTrue(iOtherPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
|
||||
assertFalse(testBeanPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,7 +171,8 @@ public final class AspectJExpressionPointcutTests {
|
||||
assertEquals(matchSubpackages, withinBeansPc.matches(
|
||||
DeepBean.class.getMethod("aMethod", String.class), DeepBean.class));
|
||||
assertFalse(withinBeansPc.matches(String.class));
|
||||
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate"), OtherIOther.class));
|
||||
assertFalse(withinBeansPc.matches(OtherIOther.class.getMethod("absquatulate", (Class<?>[])null),
|
||||
OtherIOther.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,7 +183,7 @@ public final class AspectJExpressionPointcutTests {
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().contains("expression"));
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +195,7 @@ public final class AspectJExpressionPointcutTests {
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().contains("expression"));
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +207,7 @@ public final class AspectJExpressionPointcutTests {
|
||||
fail();
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertTrue(ex.getMessage().contains("expression"));
|
||||
assertTrue(ex.getMessage().indexOf("expression") != -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,10 +226,10 @@ public final class AspectJExpressionPointcutTests {
|
||||
//assertDoesNotMatchStringClass(classFilter);
|
||||
|
||||
assertTrue("Should match with setSomeNumber with Double input",
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Double(12)));
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Double(12)}));
|
||||
assertFalse("Should not match setSomeNumber with Integer input",
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Integer(11)));
|
||||
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class));
|
||||
methodMatcher.matches(setSomeNumber, TestBean.class, new Object[]{new Integer(11)}));
|
||||
assertFalse("Should not match getAge", methodMatcher.matches(getAge, TestBean.class, null));
|
||||
assertTrue("Should be a runtime match", methodMatcher.isRuntime());
|
||||
}
|
||||
|
||||
@@ -263,6 +281,7 @@ public final class AspectJExpressionPointcutTests {
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertTrue(true);
|
||||
System.out.println(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,14 +326,16 @@ public final class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testAndSubstitution() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String)");
|
||||
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
PointcutExpression expr =
|
||||
((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertEquals("execution(* *(..)) && args(String)",expr.getPointcutExpression());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleAndSubstitutions() {
|
||||
Pointcut pc = getPointcut("execution(* *(..)) and args(String) and this(Object)");
|
||||
PointcutExpression expr = ((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
PointcutExpression expr =
|
||||
((AspectJExpressionPointcut) pc).getPointcutExpression();
|
||||
assertEquals("execution(* *(..)) && args(String) && this(Object)",expr.getPointcutExpression());
|
||||
}
|
||||
|
||||
@@ -323,15 +344,6 @@ public final class AspectJExpressionPointcutTests {
|
||||
pointcut.setExpression(expression);
|
||||
return pointcut;
|
||||
}
|
||||
|
||||
|
||||
public static class OtherIOther implements IOther {
|
||||
|
||||
@Override
|
||||
public void absquatulate() {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user