mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
159 Commits
main
...
v5.0.7.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| 8bfd47a8d4 | |||
| 4ec9f5df5c | |||
| 224fcc1712 | |||
| 96eba8b997 | |||
| be5229949c | |||
| 516937cfc5 | |||
| dac97f1b7d | |||
| f2694a8ed9 | |||
| 82f421bff8 | |||
| a2765c009e | |||
| 78d3164543 | |||
| afcc430481 | |||
| 062a15fbd7 | |||
| c04c8a2472 | |||
| f39adcf865 | |||
| da049f480b | |||
| 455d8ac7b9 | |||
| b80c13b722 | |||
| 7bfd683816 | |||
| fe01e5114d | |||
| b5595c3904 | |||
| 76678e9c6a | |||
| b3a34f8397 | |||
| 79adffd214 | |||
| af0a82931e | |||
| bbe5124556 | |||
| 5935b7aefe | |||
| a2d7cc7a69 | |||
| 8a56db6e4e | |||
| 50d6d90ed8 | |||
| a7ffe092ab | |||
| 6407cb9baf | |||
| 0bc0762577 | |||
| 051ab05d32 | |||
| 9d36fd0b68 | |||
| f078e057ce | |||
| 941186a359 | |||
| 27fc4d6053 | |||
| 1943a1f5bd | |||
| a158ff4c3d | |||
| a71bd7c03f | |||
| 1fefe2ab0c | |||
| 0b36c9437e | |||
| 72e7687b80 | |||
| e87355b29c | |||
| 1dc8201df1 | |||
| e3e975d7f9 | |||
| b385ff1d9f | |||
| 3c88029dd3 | |||
| c7adf28f61 | |||
| c555fef6f2 | |||
| ab0b0b31fd | |||
| d24546ad18 | |||
| 2818051aff | |||
| a3bcdbe371 | |||
| 3978d5500d | |||
| 416dee7226 | |||
| 4d69ec48b1 | |||
| 14a9d291e1 | |||
| 5183f71a78 | |||
| fd36af6fcf | |||
| 9179a4fa30 | |||
| 98335b41f7 | |||
| e9f4dec08c | |||
| 4ec695b4d9 | |||
| 2da02ccbd0 | |||
| f2cc70ecf9 | |||
| e2115594c0 | |||
| 2008e04354 | |||
| b4f83dbdc3 | |||
| 0795ae5c6a | |||
| 41ab177b6c | |||
| 8848ec73ab | |||
| 9f9481ec7b | |||
| f6275e009b | |||
| ed44262a71 | |||
| a0d37ac29e | |||
| a39938d251 | |||
| edb33331ed | |||
| a63f04df09 | |||
| 5a98516f6c | |||
| 30363c84bd | |||
| fa27130b82 | |||
| be4c07fc32 | |||
| 22f421cc51 | |||
| 9dc538a7c6 | |||
| d74a2730ec | |||
| 3e47f4564d | |||
| a9548f93e4 | |||
| f2e77c292d | |||
| 8b051ab06e | |||
| 5a1d7f9c4b | |||
| b55f69deb1 | |||
| de1eb343e7 | |||
| 417bb302c3 | |||
| b0aa08a671 | |||
| 9dc79982e2 | |||
| 43f2334e82 | |||
| 6c6e44b58e | |||
| c6b60f0c00 | |||
| 7aba6ca9d6 | |||
| dca77c0666 | |||
| df6e690e33 | |||
| a702ef8074 | |||
| f7376bdde3 | |||
| f9e31b503c | |||
| 3551dd92fb | |||
| c23297fe76 | |||
| a5622d0dd2 | |||
| 72cfe41f30 | |||
| 4ff595e2bc | |||
| 2c766b9501 | |||
| 2960a558d7 | |||
| d69a281e5c | |||
| d3ed7b624d | |||
| 66bd277671 | |||
| 881343e928 | |||
| 922fd1e785 | |||
| ea8317a1f9 | |||
| 053ffe808f | |||
| daa2d37ad4 | |||
| f800df12e3 | |||
| 26652a6b83 | |||
| 4cd43dc793 | |||
| 91c8b62817 | |||
| 9d37c099a8 | |||
| eb573d8b9e | |||
| b312a62f64 | |||
| 567733d2a1 | |||
| 0f91f4b960 | |||
| c1385f52c2 | |||
| c3bc125093 | |||
| b5922f75bb | |||
| bbe850d33a | |||
| 295929cc16 | |||
| 4763154193 | |||
| 8f7e5e7c1a | |||
| cd79966c52 | |||
| 7631aa6062 | |||
| 02e09098e4 | |||
| 230c8f93e8 | |||
| c4296fa785 | |||
| ab78854f1b | |||
| 96a465a749 | |||
| 861b9dc938 | |||
| eda2720471 | |||
| 7fe28ce8b7 | |||
| de8c4179fb | |||
| 433877e5cb | |||
| ffa4f03fd4 | |||
| 7068282e1f | |||
| 3879179927 | |||
| 007da2a58d | |||
| 1be585562f | |||
| 7a896d7d80 | |||
| be1aaa06e7 | |||
| 2fa060f0e9 | |||
| 4d2d889142 | |||
| 4b9bc50fd0 |
+2
-2
@@ -38,7 +38,7 @@ it helps us to make a decision.
|
||||
Reporting an issue or making a feature request is a great way to contribute. Your feedback
|
||||
and the conversations that result from it provide a continuous flow of ideas.
|
||||
|
||||
Before you create a ticket, please take the time to [research first](#Discuss).
|
||||
Before you create a ticket, please take the time to [research first](#discuss).
|
||||
|
||||
If creating a ticket after a discussion on StackOverflow, please provide a self-sufficient description in the ticket, independent of the details on StackOverview. We understand this is extra work but the issue tracker is an important place of record for design discussions and decisions that can often be referenced long after the fix version, for example to revisit decisions, to understand the origin of a feature, and so on.
|
||||
|
||||
@@ -64,7 +64,7 @@ You can contribute a source code change by submitting a pull request.
|
||||
[Contributor License Agreement](https://cla.pivotal.io/sign/spring). You will also be reminded
|
||||
automatically when you submit a pull request.
|
||||
|
||||
1. For all but the most trivial of contributions, please [create a ticket](#Create-a-Ticket).
|
||||
1. For all but the most trivial of contributions, please [create a ticket](#create-a-ticket).
|
||||
The purpose of the ticket is to understand and discuss the underlying issue or feature.
|
||||
We use the JIRA issue tracker as the preferred place of record for conversations and
|
||||
conclusions. In that sense discussions directly under a PR are more implementation detail
|
||||
|
||||
+40
-33
@@ -14,8 +14,8 @@ buildscript {
|
||||
plugins {
|
||||
id "com.gradle.build-scan" version "1.8"
|
||||
id "io.spring.dependency-management" version "1.0.3.RELEASE" apply false
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.31" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.16"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.2.41" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.17"
|
||||
id "org.asciidoctor.convert" version "1.5.6"
|
||||
}
|
||||
|
||||
@@ -35,40 +35,54 @@ ext {
|
||||
moduleProjects = subprojects.findAll {
|
||||
!it.name.equals('spring-build-src') && !it.name.equals('spring-framework-bom')
|
||||
}
|
||||
|
||||
aspectjVersion = "1.8.13"
|
||||
freemarkerVersion = "2.3.27-incubating"
|
||||
groovyVersion = "2.4.15"
|
||||
hsqldbVersion = "2.4.1"
|
||||
jackson2Version = "2.9.5"
|
||||
jettyVersion = "9.4.11.v20180605"
|
||||
junitJupiterVersion = "5.0.3"
|
||||
junitPlatformVersion = "1.0.3"
|
||||
junitVintageVersion = "4.12.3"
|
||||
kotlinVersion = "1.2.41"
|
||||
log4jVersion = "2.11.0"
|
||||
nettyVersion = "4.1.25.Final"
|
||||
reactorVersion = "Bismuth-SR10"
|
||||
rxjavaVersion = "1.3.8"
|
||||
rxjavaAdapterVersion = "1.2.1"
|
||||
rxjava2Version = "2.1.14"
|
||||
slf4jVersion = "1.7.25" // spring-jcl + consistent 3rd party deps
|
||||
tiles3Version = "3.0.8"
|
||||
tomcatVersion = "8.5.31"
|
||||
undertowVersion = "1.4.25.Final"
|
||||
|
||||
gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
withoutJclOverSlf4J = {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
}
|
||||
|
||||
configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.8.13"
|
||||
ext.freemarkerVersion = "2.3.27-incubating"
|
||||
ext.groovyVersion = "2.4.15"
|
||||
ext.hsqldbVersion = "2.4.0"
|
||||
ext.jackson2Version = "2.9.5"
|
||||
ext.jettyVersion = "9.4.9.v20180320"
|
||||
ext.junitJupiterVersion = "5.0.3"
|
||||
ext.junitPlatformVersion = "1.0.3"
|
||||
ext.junitVintageVersion = "4.12.3"
|
||||
ext.kotlinVersion = "1.2.31"
|
||||
ext.log4jVersion = "2.11.0"
|
||||
ext.nettyVersion = "4.1.22.Final"
|
||||
ext.reactorVersion = "Bismuth-SR8"
|
||||
ext.rxjavaVersion = "1.3.8"
|
||||
ext.rxjavaAdapterVersion = "1.2.1"
|
||||
ext.rxjava2Version = "2.1.12"
|
||||
ext.slf4jVersion = "1.7.25" // spring-jcl + consistent 3rd party deps
|
||||
ext.tiles3Version = "3.0.8"
|
||||
ext.tomcatVersion = "8.5.29"
|
||||
ext.undertowVersion = "1.4.23.Final"
|
||||
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
|
||||
apply plugin: "propdeps"
|
||||
apply plugin: "java"
|
||||
apply plugin: "test-source-set-dependencies"
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply from: "${gradleScriptDir}/ide.gradle"
|
||||
|
||||
dependencyManagement {
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
generatedPomCustomization {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "kotlin"
|
||||
compileKotlin {
|
||||
kotlinOptions {
|
||||
@@ -96,7 +110,6 @@ configure(allprojects) { project ->
|
||||
}
|
||||
}
|
||||
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
|
||||
def commonCompilerArgs =
|
||||
@@ -154,7 +167,6 @@ configure(allprojects) { project ->
|
||||
exclude module:'mockito-core'
|
||||
}
|
||||
testCompile("org.hamcrest:hamcrest-all:1.3")
|
||||
testCompile("org.xmlunit:xmlunit-matchers:2.3.0")
|
||||
testRuntime("org.apache.logging.log4j:log4j-core:${log4jVersion}")
|
||||
testRuntime("org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}")
|
||||
testRuntime("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
|
||||
@@ -239,7 +251,6 @@ configure(rootProject) {
|
||||
description = "Spring Framework"
|
||||
|
||||
apply plugin: "groovy"
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||
apply from: "${gradleScriptDir}/docs.gradle"
|
||||
|
||||
@@ -247,10 +258,6 @@ configure(rootProject) {
|
||||
imports {
|
||||
mavenBom "io.projectreactor:reactor-bom:${reactorVersion}"
|
||||
}
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
}
|
||||
|
||||
// don't publish the default jar for the root project
|
||||
@@ -272,7 +279,7 @@ configure(rootProject) {
|
||||
testCompile("javax.servlet:javax.servlet-api:3.1.0")
|
||||
testCompile("org.aspectj:aspectjweaver:${aspectjVersion}")
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.13.Final")
|
||||
testCompile("org.hibernate:hibernate-core:5.1.14.Final")
|
||||
}
|
||||
|
||||
artifacts {
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.0.5.BUILD-SNAPSHOT
|
||||
version=5.0.7.RELEASE
|
||||
|
||||
+10
-5
@@ -49,12 +49,9 @@ task api(type: Javadoc) {
|
||||
}
|
||||
}
|
||||
|
||||
// Need https://github.com/Kotlin/dokka/issues/184 to be fixed to avoid "Can't find node by signature" log spam
|
||||
dokka {
|
||||
dependsOn {
|
||||
subprojects.collect {
|
||||
it.tasks.getByName("jar")
|
||||
}
|
||||
tasks.getByName("api")
|
||||
}
|
||||
doFirst {
|
||||
classpath = subprojects.collect { project -> project.jar.outputs.files.getFiles() }.flatten()
|
||||
@@ -69,6 +66,10 @@ dokka {
|
||||
def kotlinDirs = project.sourceSets.main.kotlin.srcDirs.collect()
|
||||
kotlinDirs -= project.sourceSets.main.java.srcDirs
|
||||
})
|
||||
externalDocumentationLink {
|
||||
url = new URL("https://docs.spring.io/spring-framework/docs/$version/javadoc-api/")
|
||||
packageListUrl = new File(buildDir, "api/package-list").toURI().toURL()
|
||||
}
|
||||
externalDocumentationLink {
|
||||
url = new URL("http://projectreactor.io/docs/core/release/api/")
|
||||
}
|
||||
@@ -122,10 +123,14 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
|
||||
from (asciidoctor) {
|
||||
from ("$asciidoctor.outputDir/html5") {
|
||||
into "spring-framework-reference"
|
||||
}
|
||||
|
||||
from ("$asciidoctor.outputDir/pdf") {
|
||||
into "spring-framework-reference/pdf"
|
||||
}
|
||||
|
||||
from (dokka) {
|
||||
into "kdoc-api"
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ def customizePom(pom, gradleProject) {
|
||||
"$dep.scope:$dep.groupId:$dep.artifactId"
|
||||
}
|
||||
|
||||
def managedVersions = dependencyManagement.managedVersions
|
||||
generatedPom.dependencies.findAll{dep -> !dep.version }.each { dep ->
|
||||
dep.version = managedVersions["${dep.groupId}:${dep.artifactId}"]
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/*
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
url "https://dl.bintray.com/kotlin/kotlin-eap-1.1"
|
||||
}
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Workaround for https://github.com/Kotlin/dokka/issues/146
|
||||
pluginManagement {
|
||||
repositories {
|
||||
jcenter()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
include "spring-aop"
|
||||
include "spring-aspects"
|
||||
include "spring-beans"
|
||||
|
||||
+31
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.aop.aspectj;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -289,10 +290,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean beanHasIntroductions) {
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
|
||||
obtainPointcutExpression();
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
ShadowMatch shadowMatch = getShadowMatch(targetMethod, method);
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
|
||||
// Special handling for this, target, @this, @target, @annotation
|
||||
// in Spring - we can optimize since we know we have exactly this class,
|
||||
@@ -305,7 +305,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
else {
|
||||
// the maybe case
|
||||
if (beanHasIntroductions) {
|
||||
if (hasIntroductions) {
|
||||
return true;
|
||||
}
|
||||
// A match test returned maybe - if there are any subtype sensitive variables
|
||||
@@ -331,8 +331,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
@Override
|
||||
public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
|
||||
obtainPointcutExpression();
|
||||
ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
|
||||
ShadowMatch originalShadowMatch = getShadowMatch(method, method);
|
||||
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
|
||||
|
||||
// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
|
||||
// consistent with return of MethodInvocationProceedingJoinPoint
|
||||
@@ -367,7 +366,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* <p>See SPR-2979 for the original bug.
|
||||
*/
|
||||
if (pmi != null && thisObject != null) { // there is a current invocation
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
|
||||
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
|
||||
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
|
||||
return false;
|
||||
}
|
||||
@@ -427,6 +426,22 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
invocation.setUserAttribute(resolveExpression(), jpm);
|
||||
}
|
||||
|
||||
private ShadowMatch getTargetShadowMatch(Method method, @Nullable Class<?> targetClass) {
|
||||
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
if (targetClass != null && targetMethod.getDeclaringClass().isInterface()) {
|
||||
// Try to build the most specific interface possible for inherited methods to be
|
||||
// considered for sub-interface matches as well, in particular for proxy classes.
|
||||
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
|
||||
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
|
||||
if (ifcs.size() > 1) {
|
||||
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
|
||||
ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
|
||||
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
|
||||
}
|
||||
}
|
||||
return getShadowMatch(targetMethod, method);
|
||||
}
|
||||
|
||||
private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
|
||||
// Avoid lock contention for known Methods through concurrent access...
|
||||
ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
@@ -434,9 +449,9 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
synchronized (this.shadowMatchCache) {
|
||||
// Not found - now check again with full lock...
|
||||
PointcutExpression fallbackExpression = null;
|
||||
Method methodToMatch = targetMethod;
|
||||
shadowMatch = this.shadowMatchCache.get(targetMethod);
|
||||
if (shadowMatch == null) {
|
||||
Method methodToMatch = targetMethod;
|
||||
try {
|
||||
try {
|
||||
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
|
||||
@@ -454,12 +469,16 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
if (shadowMatch == null && targetMethod != originalMethod) {
|
||||
if (targetMethod != originalMethod && (shadowMatch == null ||
|
||||
(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {
|
||||
// Fall back to the plain original method in case of no resolvable match or a
|
||||
// negative match on a proxy class (which doesn't carry any annotations on its
|
||||
// redeclared methods).
|
||||
methodToMatch = originalMethod;
|
||||
try {
|
||||
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
catch (ReflectionWorldException ex3) {
|
||||
catch (ReflectionWorldException ex) {
|
||||
// Could neither introspect the target class nor the proxy class ->
|
||||
// let's try the original method's declaring class before we give up...
|
||||
try {
|
||||
@@ -468,7 +487,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
|
||||
}
|
||||
}
|
||||
catch (ReflectionWorldException ex4) {
|
||||
catch (ReflectionWorldException ex2) {
|
||||
fallbackExpression = null;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,17 +33,15 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of AspectJ ProceedingJoinPoint interface
|
||||
* wrapping an AOP Alliance MethodInvocation.
|
||||
* An implementation of the AspectJ {@link ProceedingJoinPoint} interface
|
||||
* wrapping an AOP Alliance {@link org.aopalliance.intercept.MethodInvocation}.
|
||||
*
|
||||
* <p><b>Note</b>: the {@code getThis()} method returns the current Spring AOP proxy.
|
||||
* <p><b>Note</b>: The {@code getThis()} method returns the current Spring AOP proxy.
|
||||
* The {@code getTarget()} method returns the current Spring AOP target (which may be
|
||||
* {@code null} if there is no target), and is a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use
|
||||
* {@code getThis()}.</b> A common example is casting the object to an
|
||||
* introduced interface in the implementation of an introduction.
|
||||
*
|
||||
* <p>Of course there is no such distinction between target and proxy in AspectJ.
|
||||
* {@code null} if there is no target instance) as a plain POJO without any advice.
|
||||
* <b>If you want to call the object and have the advice take effect, use {@code getThis()}.</b>
|
||||
* A common example is casting the object to an introduced interface in the implementation of
|
||||
* an introduction. There is no such distinction between target and proxy in AspectJ itself.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -58,7 +56,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
private final ProxyMethodInvocation methodInvocation;
|
||||
|
||||
@Nullable
|
||||
private Object[] defensiveCopyOfArgs;
|
||||
private Object[] args;
|
||||
|
||||
/** Lazily initialized signature object */
|
||||
@Nullable
|
||||
@@ -79,6 +77,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
this.methodInvocation = methodInvocation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void set$AroundClosure(AroundClosure aroundClosure) {
|
||||
throw new UnsupportedOperationException();
|
||||
@@ -120,12 +119,10 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
|
||||
@Override
|
||||
public Object[] getArgs() {
|
||||
if (this.defensiveCopyOfArgs == null) {
|
||||
Object[] argsSource = this.methodInvocation.getArguments();
|
||||
this.defensiveCopyOfArgs = new Object[argsSource.length];
|
||||
System.arraycopy(argsSource, 0, this.defensiveCopyOfArgs, 0, argsSource.length);
|
||||
if (this.args == null) {
|
||||
this.args = this.methodInvocation.getArguments().clone();
|
||||
}
|
||||
return this.defensiveCopyOfArgs;
|
||||
return this.args;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,7 +130,7 @@ public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint,
|
||||
if (this.signature == null) {
|
||||
this.signature = new MethodSignatureImpl();
|
||||
}
|
||||
return signature;
|
||||
return this.signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -205,9 +205,8 @@ class CglibAopProxy implements AopProxy, Serializable {
|
||||
return createProxyClassAndInstance(enhancer, callbacks);
|
||||
}
|
||||
catch (CodeGenerationException | IllegalArgumentException ex) {
|
||||
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
|
||||
this.advised.getTargetClass() + "]: " +
|
||||
"Common causes of this problem include using a final class or a non-visible class",
|
||||
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
|
||||
": Common causes of this problem include using a final class or a non-visible class",
|
||||
ex);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Seriali
|
||||
|
||||
@Override
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
|
||||
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
|
||||
return mi.proceed();
|
||||
}
|
||||
|
||||
|
||||
@@ -192,8 +192,7 @@ public abstract class AopUtils {
|
||||
* @see org.springframework.util.ClassUtils#getMostSpecificMethod
|
||||
*/
|
||||
public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) {
|
||||
Class<?> specificTargetClass = (targetClass != null && !Proxy.isProxyClass(targetClass) ?
|
||||
ClassUtils.getUserClass(targetClass) : null);
|
||||
Class<?> specificTargetClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
|
||||
Method resolvedMethod = ClassUtils.getMostSpecificMethod(method, specificTargetClass);
|
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
return BridgeMethodResolver.findBridgedMethod(resolvedMethod);
|
||||
@@ -247,8 +246,8 @@ public abstract class AopUtils {
|
||||
for (Class<?> clazz : classes) {
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
|
||||
for (Method method : methods) {
|
||||
if ((introductionAwareMethodMatcher != null &&
|
||||
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
|
||||
if (introductionAwareMethodMatcher != null ?
|
||||
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
|
||||
methodMatcher.matches(method, targetClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -90,8 +90,8 @@ public abstract class MethodMatchers {
|
||||
*/
|
||||
public static boolean matches(MethodMatcher mm, Method method, @Nullable Class<?> targetClass, boolean hasIntroductions) {
|
||||
Assert.notNull(mm, "MethodMatcher must not be null");
|
||||
return ((mm instanceof IntroductionAwareMethodMatcher &&
|
||||
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions)) ||
|
||||
return (mm instanceof IntroductionAwareMethodMatcher ?
|
||||
((IntroductionAwareMethodMatcher) mm).matches(method, targetClass, hasIntroductions) :
|
||||
mm.matches(method, targetClass));
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.aop.support.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.support.StaticMethodMatcher;
|
||||
@@ -71,6 +72,10 @@ public class AnnotationMethodMatcher extends StaticMethodMatcher {
|
||||
if (matchesMethod(method)) {
|
||||
return true;
|
||||
}
|
||||
// Proxy classes never have annotations on their redeclared methods.
|
||||
if (targetClass != null && Proxy.isProxyClass(targetClass)) {
|
||||
return false;
|
||||
}
|
||||
// The method may be on an interface, so let's check on the target class as well.
|
||||
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
return (specificMethod != method && matchesMethod(specificMethod));
|
||||
|
||||
+7
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -30,13 +27,7 @@ import org.junit.Test;
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscoverAnnotationTests
|
||||
extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface MyAnnotation {}
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
public class AspectJAdviceParameterNameDiscoverAnnotationTests extends AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testAnnotationBinding() {
|
||||
@@ -45,4 +36,9 @@ public class AspectJAdviceParameterNameDiscoverAnnotationTests
|
||||
new String[] {"thisJoinPoint","ann"});
|
||||
}
|
||||
|
||||
|
||||
public void pjpAndAnAnnotation(ProceedingJoinPoint pjp, MyAnnotation ann) {}
|
||||
|
||||
@interface MyAnnotation {}
|
||||
|
||||
}
|
||||
|
||||
+58
-52
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -34,47 +35,6 @@ import static org.junit.Assert.*;
|
||||
*/
|
||||
public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
// methods to discover parameter names for
|
||||
public void noArgs() {
|
||||
}
|
||||
|
||||
public void tjp(JoinPoint jp) {
|
||||
}
|
||||
|
||||
public void tjpsp(JoinPoint.StaticPart tjpsp) {
|
||||
}
|
||||
|
||||
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
|
||||
}
|
||||
|
||||
public void oneThrowable(Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
|
||||
}
|
||||
|
||||
public void oneObject(Object x) {
|
||||
}
|
||||
|
||||
public void twoObjects(Object x, Object y) {
|
||||
}
|
||||
|
||||
public void onePrimitive(int x) {
|
||||
}
|
||||
|
||||
public void oneObjectOnePrimitive(Object x, int y) {
|
||||
}
|
||||
|
||||
public void oneThrowableOnePrimitive(Throwable x, int y) {
|
||||
}
|
||||
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoArgs() {
|
||||
assertParameterNames(getMethod("noArgs"), "execution(* *(..))", new String[0]);
|
||||
@@ -221,22 +181,26 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
@Test
|
||||
public void testThisAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)", new String[] {"obj", "count"});
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && this(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTargetAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)", new String[] {"obj", "count"});
|
||||
assertParameterNames(getMethod("oneObjectOnePrimitive"), "args(count) && target(obj)",
|
||||
new String[] {"obj", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrowingAndPrimitive() {
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex", new String[] {"ex", "count"});
|
||||
assertParameterNames(getMethod("oneThrowableOnePrimitive"), "args(count)", null, "ex",
|
||||
new String[] {"ex", "count"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllTogetherNow() {
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex", new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
assertParameterNames(getMethod("theBigOne"), "this(foo) && args(x)", null, "ex",
|
||||
new String[] {"thisJoinPoint", "ex", "x", "foo"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -253,8 +217,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
|
||||
|
||||
protected Method getMethod(String name) {
|
||||
// assumes no overloading of test methods...
|
||||
Method[] candidates = this.getClass().getMethods();
|
||||
// Assumes no overloading of test methods...
|
||||
Method[] candidates = getClass().getMethods();
|
||||
for (Method candidate : candidates) {
|
||||
if (candidate.getName().equals(name)) {
|
||||
return candidate;
|
||||
@@ -268,8 +232,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
assertParameterNames(method, pointcut, null, null, parameterNames);
|
||||
}
|
||||
|
||||
protected void assertParameterNames(Method method, String pointcut, String returning, String throwing,
|
||||
String[] parameterNames) {
|
||||
protected void assertParameterNames(
|
||||
Method method, String pointcut, String returning, String throwing, String[] parameterNames) {
|
||||
|
||||
assertEquals("bad test specification, must have same number of parameter names as method arguments",
|
||||
method.getParameterCount(), parameterNames.length);
|
||||
@@ -300,8 +264,8 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
assertException(method, pointcut, null, null, exceptionType, message);
|
||||
}
|
||||
|
||||
protected void assertException(Method method, String pointcut, String returning, String throwing,
|
||||
Class<?> exceptionType, String message) {
|
||||
protected void assertException(
|
||||
Method method, String pointcut, String returning, String throwing, Class<?> exceptionType, String message) {
|
||||
|
||||
AspectJAdviceParameterNameDiscoverer discoverer = new AspectJAdviceParameterNameDiscoverer(pointcut);
|
||||
discoverer.setRaiseExceptions(true);
|
||||
@@ -333,4 +297,46 @@ public class AspectJAdviceParameterNameDiscovererTests {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
// Methods to discover parameter names for
|
||||
|
||||
public void noArgs() {
|
||||
}
|
||||
|
||||
public void tjp(JoinPoint jp) {
|
||||
}
|
||||
|
||||
public void tjpsp(JoinPoint.StaticPart tjpsp) {
|
||||
}
|
||||
|
||||
public void twoJoinPoints(JoinPoint jp1, JoinPoint jp2) {
|
||||
}
|
||||
|
||||
public void oneThrowable(Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndOneThrowable(JoinPoint jp, Exception ex) {
|
||||
}
|
||||
|
||||
public void jpAndTwoThrowables(JoinPoint jp, Exception ex, Error err) {
|
||||
}
|
||||
|
||||
public void oneObject(Object x) {
|
||||
}
|
||||
|
||||
public void twoObjects(Object x, Object y) {
|
||||
}
|
||||
|
||||
public void onePrimitive(int x) {
|
||||
}
|
||||
|
||||
public void oneObjectOnePrimitive(Object x, int y) {
|
||||
}
|
||||
|
||||
public void oneThrowableOnePrimitive(Throwable x, int y) {
|
||||
}
|
||||
|
||||
public void theBigOne(JoinPoint jp, Throwable x, int y, Object foo) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -218,38 +218,27 @@ public class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testSimpleAdvice() {
|
||||
String expression = "execution(int org.springframework.tests.sample.beans.TestBean.getAge())";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.getAge();
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setAge(90);
|
||||
|
||||
assertEquals("Calls should still be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDynamicMatchingProxy() {
|
||||
String expression = "execution(void org.springframework.tests.sample.beans.TestBean.setSomeNumber(Number)) && args(Double)";
|
||||
|
||||
CallCountingInterceptor interceptor = new CallCountingInterceptor();
|
||||
|
||||
TestBean testBean = getAdvisedProxy(expression, interceptor);
|
||||
|
||||
assertEquals("Calls should be 0", 0, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Double(30));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
|
||||
testBean.setSomeNumber(new Integer(90));
|
||||
|
||||
assertEquals("Calls should be 1", 1, interceptor.getCount());
|
||||
}
|
||||
|
||||
@@ -291,7 +280,7 @@ public class AspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUnsupportedPointcutPrimitive() throws Exception {
|
||||
public void testWithUnsupportedPointcutPrimitive() {
|
||||
String expression = "call(int org.springframework.tests.sample.beans.TestBean.getAge())";
|
||||
|
||||
try {
|
||||
@@ -301,7 +290,6 @@ public class AspectJExpressionPointcutTests {
|
||||
catch (UnsupportedPointcutPrimitiveException ex) {
|
||||
assertEquals("Should not support call pointcut", PointcutPrimitive.CALL, ex.getUnsupportedPrimitive());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -332,6 +320,7 @@ public class AspectJExpressionPointcutTests {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -77,6 +77,7 @@ public class BeanNamePointcutMatchingTests {
|
||||
assertMisMatch("someName", "!bean(someName) || bean(someOtherName)");
|
||||
}
|
||||
|
||||
|
||||
private void assertMatch(String beanName, String pcExpression) {
|
||||
assertTrue("Unexpected mismatch for bean \"" + beanName + "\" for pcExpression \"" + pcExpression + "\"",
|
||||
matches(beanName, pcExpression));
|
||||
@@ -98,4 +99,5 @@ public class BeanNamePointcutMatchingTests {
|
||||
pointcut.setExpression(pcExpression);
|
||||
return pointcut.matches(TestBean.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+65
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,30 +26,30 @@ import org.junit.Test;
|
||||
import test.annotation.EmptySpringAnnotation;
|
||||
import test.annotation.transaction.Tx;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Java5-specific {@link AspectJExpressionPointcutTests}.
|
||||
* Java 5 specific {@link AspectJExpressionPointcutTests}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
// TODO factor into static in AspectJExpressionPointcut
|
||||
private Method getAge;
|
||||
|
||||
private Map<String,Method> methodsOnHasGeneric = new HashMap<>();
|
||||
private final Map<String, Method> methodsOnHasGeneric = new HashMap<>();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws NoSuchMethodException {
|
||||
public void setup() throws NoSuchMethodException {
|
||||
getAge = TestBean.class.getMethod("getAge");
|
||||
// Assumes no overloading
|
||||
for (Method m : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(m.getName(), m);
|
||||
for (Method method : HasGeneric.class.getMethods()) {
|
||||
methodsOnHasGeneric.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchVarargs() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchVarargs() throws Exception {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
class MyTemplate {
|
||||
@@ -87,11 +87,6 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
AspectJExpressionPointcut jdbcVarArgs = new AspectJExpressionPointcut();
|
||||
jdbcVarArgs.setExpression(expression);
|
||||
|
||||
// TODO: the expression above no longer matches Object[]
|
||||
// assertFalse(jdbcVarArgs.matches(
|
||||
// JdbcTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
// JdbcTemplate.class));
|
||||
|
||||
assertTrue(jdbcVarArgs.matches(
|
||||
MyTemplate.class.getMethod("queryForInt", String.class, Object[].class),
|
||||
MyTemplate.class));
|
||||
@@ -105,19 +100,19 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithAtWithin() throws Exception {
|
||||
String expression = "@within(test.annotation.transaction.Tx)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithoutBinding() throws Exception {
|
||||
String expression = "within(@test.annotation.transaction.Tx *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithSubpackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation..*) *)";
|
||||
AspectJExpressionPointcut springAnnotatedPc = testMatchAnnotationOnClass(expression);
|
||||
assertFalse(springAnnotatedPc.matches(TestBean.class.getMethod("setName", String.class), TestBean.class));
|
||||
@@ -129,12 +124,12 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testMatchAnnotationOnClassWithExactPackageWildcard() throws Exception {
|
||||
String expression = "within(@(test.annotation.transaction.*) *)";
|
||||
testMatchAnnotationOnClass(expression);
|
||||
}
|
||||
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws SecurityException, NoSuchMethodException {
|
||||
private AspectJExpressionPointcut testMatchAnnotationOnClass(String expression) throws Exception {
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
@@ -147,7 +142,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodWithFQN() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
@@ -161,28 +156,56 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnCglibProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(true);
|
||||
BeanA proxy = (BeanA) factory.getProxy();
|
||||
assertTrue(ajexp.matches(BeanA.class.getMethod("getAge"), proxy.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnDynamicProxyMethod() throws Exception {
|
||||
String expression = "@annotation(test.annotation.transaction.Tx)";
|
||||
AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
|
||||
ajexp.setExpression(expression);
|
||||
|
||||
ProxyFactory factory = new ProxyFactory(new BeanA());
|
||||
factory.setProxyTargetClass(false);
|
||||
IBeanA proxy = (IBeanA) factory.getProxy();
|
||||
assertTrue(ajexp.matches(IBeanA.class.getMethod("getAge"), proxy.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodWithWildcard() throws Exception {
|
||||
String expression = "execution(@(test.annotation..*) * *(..))";
|
||||
AspectJExpressionPointcut anySpringMethodAnnotation = new AspectJExpressionPointcut();
|
||||
anySpringMethodAnnotation.setExpression(expression);
|
||||
|
||||
assertFalse(anySpringMethodAnnotation.matches(getAge, TestBean.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertTrue(anySpringMethodAnnotation.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(anySpringMethodAnnotation.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodArgumentsWithFQN() throws Exception {
|
||||
String expression = "@args(*, test.annotation.EmptySpringAnnotation))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
@@ -203,14 +226,16 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws SecurityException, NoSuchMethodException {
|
||||
public void testAnnotationOnMethodArgumentsWithWildcards() throws Exception {
|
||||
String expression = "execution(* *(*, @(test..*) *))";
|
||||
AspectJExpressionPointcut takesSpringAnnotatedArgument2 = new AspectJExpressionPointcut();
|
||||
takesSpringAnnotatedArgument2.setExpression(expression);
|
||||
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(getAge, TestBean.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("foo"), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(
|
||||
HasTransactionalAnnotation.class.getMethod("bar", String.class), HasTransactionalAnnotation.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("getAge"), BeanA.class));
|
||||
assertFalse(takesSpringAnnotatedArgument2.matches(BeanA.class.getMethod("setName", String.class), BeanA.class));
|
||||
@@ -260,12 +285,21 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class BeanA {
|
||||
interface IBeanA {
|
||||
|
||||
@Tx
|
||||
int getAge();
|
||||
}
|
||||
|
||||
|
||||
static class BeanA implements IBeanA {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
@@ -275,6 +309,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
}
|
||||
|
||||
@Tx
|
||||
@Override
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
@@ -283,6 +318,7 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
@Tx
|
||||
static class BeanB {
|
||||
|
||||
private String name;
|
||||
|
||||
public void setName(String name) {
|
||||
|
||||
+77
-96
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,7 +46,6 @@ import test.aop.PerTargetAspect;
|
||||
import test.aop.TwoAdviceAspect;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
@@ -82,22 +81,24 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testRejectsPerCflowAspect() {
|
||||
try {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(),"someBean"));
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean"));
|
||||
fail("Cannot accept cflow");
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("PERCFLOW") != -1);
|
||||
assertTrue(ex.getMessage().contains("PERCFLOW"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRejectsPerCflowBelowAspect() {
|
||||
try {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(),"someBean"));
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean"));
|
||||
fail("Cannot accept cflowbelow");
|
||||
}
|
||||
catch (AopConfigException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("PERCFLOWBELOW") != -1);
|
||||
assertTrue(ex.getMessage().contains("PERCFLOWBELOW"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +113,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertEquals("Around advice must NOT apply", realAge, itb.getAge());
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[3];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -199,7 +201,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
Advised advised = (Advised) itb;
|
||||
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
|
||||
assertEquals(4, advised.getAdvisors().length);
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -227,16 +230,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
PerTypeWithinAspectInstanceFactory aif = new PerTypeWithinAspectInstanceFactory();
|
||||
TestBean itb = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aif),
|
||||
TestBean.class);
|
||||
TestBean itb = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
assertEquals("No method calls", 0, aif.getInstantiationCount());
|
||||
assertEquals("Around advice must now apply", 0, itb.getAge());
|
||||
|
||||
Advised advised = (Advised) itb;
|
||||
// Will be ExposeInvocationInterceptor, synthetic instantiation advisor, 2 method advisors
|
||||
assertEquals(4, advised.getAdvisors().length);
|
||||
SyntheticInstantiationAdvisor sia = (SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor sia =
|
||||
(ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor) advised.getAdvisors()[1];
|
||||
assertTrue(sia.getPointcut().getMethodMatcher().matches(TestBean.class.getMethod("getSpouse"), null));
|
||||
InstantiationModelAwarePointcutAdvisorImpl imapa = (InstantiationModelAwarePointcutAdvisorImpl) advised.getAdvisors()[2];
|
||||
LazySingletonAspectInstanceFactoryDecorator maaif =
|
||||
@@ -257,9 +259,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertEquals("Around advice must still apply", 1, itb.getAge());
|
||||
assertEquals("Around advice must still apply", 2, itb.getAge());
|
||||
|
||||
TestBean itb2 = (TestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aif),
|
||||
TestBean.class);
|
||||
TestBean itb2 = (TestBean) createProxy(target, getFixture().getAdvisors(aif), TestBean.class);
|
||||
assertEquals(1, aif.getInstantiationCount());
|
||||
assertEquals("Around advice be independent for second instance", 0, itb2.getAge());
|
||||
assertEquals(2, aif.getInstantiationCount());
|
||||
@@ -284,7 +284,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testNamedPointcutFromAspectLibraryWithBinding() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new NamedPointcutAspectFromLibraryWithBinding(),"someBean")),
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NamedPointcutAspectFromLibraryWithBinding(), "someBean")),
|
||||
ITestBean.class);
|
||||
itb.setAge(10);
|
||||
assertEquals("Around advice must apply", 20, itb.getAge());
|
||||
@@ -296,7 +297,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
int realAge = 65;
|
||||
target.setAge(realAge);
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance,"someBean")),
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, "someBean")),
|
||||
ITestBean.class);
|
||||
assertEquals("Around advice must apply", -1, itb.getAge());
|
||||
assertEquals(realAge, target.getAge());
|
||||
@@ -306,7 +307,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testBindingWithSingleArg() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(),"someBean")),
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new BindingAspectWithSingleArg(), "someBean")),
|
||||
ITestBean.class);
|
||||
itb.setAge(10);
|
||||
assertEquals("Around advice must apply", 20, itb.getAge());
|
||||
@@ -317,7 +319,8 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testBindingWithMultipleArgsDifferentlyOrdered() {
|
||||
ManyValuedArgs target = new ManyValuedArgs();
|
||||
ManyValuedArgs mva = (ManyValuedArgs) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(),"someBean")),
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ManyValuedArgs(), "someBean")),
|
||||
ManyValuedArgs.class);
|
||||
|
||||
String a = "a";
|
||||
@@ -338,7 +341,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertFalse(notLockableTarget instanceof Lockable);
|
||||
NotLockable notLockable1 = (NotLockable) createProxy(notLockableTarget,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
assertTrue(notLockable1 instanceof Lockable);
|
||||
Lockable lockable = (Lockable) notLockable1;
|
||||
@@ -349,7 +352,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
NotLockable notLockable2Target = new NotLockable();
|
||||
NotLockable notLockable2 = (NotLockable) createProxy(notLockable2Target,
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")),
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
NotLockable.class);
|
||||
assertTrue(notLockable2 instanceof Lockable);
|
||||
Lockable lockable2 = (Lockable) notLockable2;
|
||||
@@ -368,11 +371,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testIntroductionAdvisorExcludedFromTargetImplementingInterface() {
|
||||
assertTrue(AopUtils.findAdvisorsThatCanApply(
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new MakeLockable(),"someBean")),
|
||||
CannotBeUnlocked.class).isEmpty());
|
||||
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
CannotBeUnlocked.class).isEmpty());
|
||||
assertEquals(2, AopUtils.findAdvisorsThatCanApply(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")), NotLockable.class).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -408,42 +411,34 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")),
|
||||
List.class
|
||||
),
|
||||
CannotBeUnlocked.class);
|
||||
List.class);
|
||||
assertFalse("Type pattern must have excluded mixin", proxy instanceof Lockable);
|
||||
}
|
||||
|
||||
/* prereq AspectJ 1.6.7
|
||||
@Test
|
||||
public void testIntroductionBasedOnAnnotationMatch_Spr5307() {
|
||||
public void testIntroductionBasedOnAnnotationMatch_SPR5307() {
|
||||
AnnotatedTarget target = new AnnotatedTargetImpl();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(),"someBean"));
|
||||
Object proxy = createProxy(target,
|
||||
advisors,
|
||||
AnnotatedTarget.class);
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeAnnotatedTypeModifiable(), "someBean"));
|
||||
Object proxy = createProxy(target, advisors, AnnotatedTarget.class);
|
||||
System.out.println(advisors.get(1));
|
||||
assertTrue(proxy instanceof Lockable);
|
||||
Lockable lockable = (Lockable)proxy;
|
||||
lockable.locked();
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testIntroductionWithArgumentBinding() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(),"someBean"));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeITestBeanModifiable(), "someBean"));
|
||||
advisors.addAll(getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(),"someBean")));
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new MakeLockable(), "someBean")));
|
||||
|
||||
Modifiable modifiable = (Modifiable) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
Modifiable modifiable = (Modifiable) createProxy(target, advisors, ITestBean.class);
|
||||
assertThat(modifiable, instanceOf(Modifiable.class));
|
||||
Lockable lockable = (Lockable) modifiable;
|
||||
assertFalse(lockable.locked());
|
||||
@@ -477,11 +472,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testAspectMethodThrowsExceptionLegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
UnsupportedOperationException expectedException = new UnsupportedOperationException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertEquals("One advice method was found", 1, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
|
||||
try {
|
||||
itb.getAge();
|
||||
fail();
|
||||
@@ -497,11 +492,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testAspectMethodThrowsExceptionIllegalOnSignature() {
|
||||
TestBean target = new TestBean();
|
||||
RemoteException expectedException = new RemoteException();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException),"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new ExceptionAspect(expectedException), "someBean"));
|
||||
assertEquals("One advice method was found", 1, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
|
||||
try {
|
||||
itb.getAge();
|
||||
fail();
|
||||
@@ -522,10 +517,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
// Required everywhere we use AspectJ proxies
|
||||
pf.addAdvice(ExposeInvocationInterceptor.INSTANCE);
|
||||
|
||||
for (Object a : advisors) {
|
||||
pf.addAdvisor((Advisor) a);
|
||||
}
|
||||
pf.addAdvisors(advisors);
|
||||
|
||||
pf.setExposeProxy(true);
|
||||
return pf.getProxy();
|
||||
@@ -534,13 +526,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testTwoAdvicesOnOneAspect() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
TwoAdviceAspect twoAdviceAspect = new TwoAdviceAspect();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect,"someBean"));
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(twoAdviceAspect, "someBean"));
|
||||
assertEquals("Two advice methods found", 2, advisors.size());
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
advisors,
|
||||
ITestBean.class);
|
||||
ITestBean itb = (ITestBean) createProxy(target, advisors, ITestBean.class);
|
||||
itb.setName("");
|
||||
assertEquals(0, itb.getAge());
|
||||
int newAge = 32;
|
||||
@@ -551,16 +541,15 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
@Test
|
||||
public void testAfterAdviceTypes() throws Exception {
|
||||
Echo target = new Echo();
|
||||
|
||||
ExceptionHandling afterReturningAspect = new ExceptionHandling();
|
||||
List<Advisor> advisors = getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect,"someBean"));
|
||||
Echo echo = (Echo) createProxy(target,
|
||||
advisors,
|
||||
Echo.class);
|
||||
List<Advisor> advisors = getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(afterReturningAspect, "someBean"));
|
||||
Echo echo = (Echo) createProxy(target, advisors, Echo.class);
|
||||
assertEquals(0, afterReturningAspect.successCount);
|
||||
assertEquals("", echo.echo(""));
|
||||
assertEquals(1, afterReturningAspect.successCount);
|
||||
assertEquals(0, afterReturningAspect.failureCount);
|
||||
|
||||
try {
|
||||
echo.echo(new FileNotFoundException());
|
||||
fail();
|
||||
@@ -580,9 +569,9 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testFailureWithoutExplicitDeclarePrecedence() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
new NoDeclarePrecedenceShouldFail(), "someBean");
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
itb.getAge();
|
||||
}
|
||||
|
||||
@@ -590,21 +579,10 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
public void testDeclarePrecedenceNotSupported() {
|
||||
TestBean target = new TestBean();
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new DeclarePrecedenceShouldSucceed(), "someBean");
|
||||
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory),
|
||||
ITestBean.class);
|
||||
new DeclarePrecedenceShouldSucceed(), "someBean");
|
||||
createProxy(target, getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
}
|
||||
|
||||
/** Not supported in 2.0!
|
||||
public void testExplicitDeclarePrecedencePreventsFailure() {
|
||||
TestBean target = new TestBean();
|
||||
ITestBean itb = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(new DeclarePrecedenceShouldSucceed(), "someBean")),
|
||||
ITestBean.class);
|
||||
assertEquals(666, itb.getAge());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@Aspect("percflow(execution(* *(..)))")
|
||||
public static class PerCflowAspect {
|
||||
@@ -723,6 +701,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class NamedPointcutAspectWithoutFQN {
|
||||
|
||||
@Pointcut("execution(* getAge())")
|
||||
public void getAge() {
|
||||
}
|
||||
@@ -779,7 +758,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around(value="setAge(age)",argNames="age")
|
||||
// @ArgNames({"age"}) // AMC needs more work here? ignoring pjp arg... ok??
|
||||
// argNames should be suported in Around as it is in Pointcut
|
||||
// argNames should be suported in Around as it is in Pointcut
|
||||
public void changeReturnType(ProceedingJoinPoint pjp, int age) throws Throwable {
|
||||
pjp.proceed(new Object[] {age*2});
|
||||
}
|
||||
@@ -788,12 +767,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ManyValuedArgs {
|
||||
|
||||
public String mungeArgs(String a, int b, int c, String d, StringBuffer e) {
|
||||
return a + b + c + d + e;
|
||||
}
|
||||
|
||||
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)",
|
||||
argNames="b,c,d,e,a")
|
||||
@Around(value="execution(String mungeArgs(..)) && args(a, b, c, d, e)", argNames="b,c,d,e,a")
|
||||
public String reverseAdvice(ProceedingJoinPoint pjp, int b, int c, String d, StringBuffer e, String a) throws Throwable {
|
||||
assertEquals(a + b+ c+ d+ e, pjp.proceed());
|
||||
return a + b + c + d + e;
|
||||
@@ -803,6 +782,7 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ExceptionAspect {
|
||||
|
||||
private final Exception ex;
|
||||
|
||||
public ExceptionAspect(Exception ex) {
|
||||
@@ -829,8 +809,11 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Aspect
|
||||
public static class ExceptionHandling {
|
||||
|
||||
public int successCount;
|
||||
|
||||
public int failureCount;
|
||||
|
||||
public int afterCount;
|
||||
|
||||
@AfterReturning("execution(* echo(*))")
|
||||
@@ -902,10 +885,12 @@ public abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
abstract class AbstractMakeModifiable {
|
||||
|
||||
public interface MutableModifable extends Modifiable {
|
||||
|
||||
void markDirty();
|
||||
}
|
||||
|
||||
public static class ModifiableImpl implements MutableModifable {
|
||||
|
||||
private boolean modified;
|
||||
|
||||
@Override
|
||||
@@ -924,10 +909,9 @@ abstract class AbstractMakeModifiable {
|
||||
}
|
||||
}
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)",
|
||||
argNames="modifiable,newValue")
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(JoinPoint jp,
|
||||
MutableModifable mixin, Object newValue) {
|
||||
@Before(value="execution(void set*(*)) && this(modifiable) && args(newValue)", argNames="modifiable,newValue")
|
||||
public void recordModificationIfSetterArgumentDiffersFromOldValue(
|
||||
JoinPoint jp, MutableModifable mixin, Object newValue) {
|
||||
|
||||
/*
|
||||
* We use the mixin to check and, if necessary, change,
|
||||
@@ -992,6 +976,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a declare parents pointcut - spr5307
|
||||
* @author Andy Clement
|
||||
@@ -1001,8 +986,7 @@ class MakeITestBeanModifiable extends AbstractMakeModifiable {
|
||||
class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
|
||||
@DeclareParents(value = "(@org.springframework.aop.aspectj.annotation.Measured *)",
|
||||
// @DeclareParents(value = "(@Measured *)", // this would be a nice alternative...
|
||||
defaultImpl=DefaultLockable.class)
|
||||
defaultImpl = DefaultLockable.class)
|
||||
public static Lockable mixin;
|
||||
|
||||
}
|
||||
@@ -1014,14 +998,11 @@ class MakeAnnotatedTypeModifiable extends AbstractMakeModifiable {
|
||||
@Aspect
|
||||
class MakeLockable {
|
||||
|
||||
@DeclareParents(value = "org.springframework..*",
|
||||
defaultImpl=DefaultLockable.class)
|
||||
@DeclareParents(value = "org.springframework..*", defaultImpl = DefaultLockable.class)
|
||||
public static Lockable mixin;
|
||||
|
||||
@Before(value="execution(void set*(*)) && this(mixin)", argNames="mixin")
|
||||
public void checkNotLocked(
|
||||
Lockable mixin) // Bind to arg
|
||||
{
|
||||
public void checkNotLocked( Lockable mixin) {
|
||||
// Can also obtain the mixin (this) this way
|
||||
//Lockable mixin = (Lockable) jp.getThis();
|
||||
if (mixin.locked()) {
|
||||
@@ -1069,6 +1050,7 @@ interface Modifiable {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used as a target.
|
||||
* @author Andy Clement
|
||||
@@ -1076,11 +1058,12 @@ interface Modifiable {
|
||||
interface AnnotatedTarget {
|
||||
}
|
||||
|
||||
|
||||
@Measured
|
||||
class AnnotatedTargetImpl implements AnnotatedTarget {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Measured {}
|
||||
|
||||
@@ -1104,9 +1087,7 @@ class PerThisAspect {
|
||||
|
||||
public int count;
|
||||
|
||||
/**
|
||||
* Just to check that this doesn't cause problems with introduction processing
|
||||
*/
|
||||
// Just to check that this doesn't cause problems with introduction processing
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
|
||||
+5
-5
@@ -70,13 +70,13 @@ public class HotSwappableTargetSourceTests {
|
||||
@Test
|
||||
public void testBasicFunctionality() {
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(INITIAL_COUNT, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT, proxied.getCount());
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
|
||||
|
||||
proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 2, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 2, proxied.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,9 +85,9 @@ public class HotSwappableTargetSourceTests {
|
||||
SideEffectBean target2 = (SideEffectBean) beanFactory.getBean("target2");
|
||||
|
||||
SideEffectBean proxied = (SideEffectBean) beanFactory.getBean("swappable");
|
||||
assertEquals(target1.getCount(), proxied.getCount() );
|
||||
assertEquals(target1.getCount(), proxied.getCount());
|
||||
proxied.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, proxied.getCount());
|
||||
|
||||
HotSwappableTargetSource swapper = (HotSwappableTargetSource) beanFactory.getBean("swapper");
|
||||
Object old = swapper.swap(target2);
|
||||
|
||||
+4
-4
@@ -56,14 +56,14 @@ public class PrototypeTargetSourceTests {
|
||||
@Test
|
||||
public void testPrototypeAndSingletonBehaveDifferently() {
|
||||
SideEffectBean singleton = (SideEffectBean) beanFactory.getBean("singleton");
|
||||
assertEquals(INITIAL_COUNT, singleton.getCount() );
|
||||
assertEquals(INITIAL_COUNT, singleton.getCount());
|
||||
singleton.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, singleton.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, singleton.getCount());
|
||||
|
||||
SideEffectBean prototype = (SideEffectBean) beanFactory.getBean("prototype");
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount());
|
||||
prototype.doWork();
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype.getCount());
|
||||
}
|
||||
|
||||
|
||||
|
||||
+11
-11
@@ -62,9 +62,9 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testUseDifferentManagedInstancesInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
|
||||
ITestBean test = (ITestBean) beanFactory.getBean("threadLocal2");
|
||||
assertEquals("Rod", test.getName());
|
||||
@@ -74,12 +74,12 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testReuseInSameThread() {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
|
||||
apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,20 +106,20 @@ public class ThreadLocalTargetSourceTests {
|
||||
@Test
|
||||
public void testNewThreadHasOwnInstance() throws InterruptedException {
|
||||
SideEffectBean apartment = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT, apartment.getCount());
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
apartment.doWork();
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
|
||||
|
||||
class Runner implements Runnable {
|
||||
public SideEffectBean mine;
|
||||
@Override
|
||||
public void run() {
|
||||
this.mine = (SideEffectBean) beanFactory.getBean("apartment");
|
||||
assertEquals(INITIAL_COUNT, mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT, mine.getCount());
|
||||
mine.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, mine.getCount());
|
||||
}
|
||||
}
|
||||
Runner r = new Runner();
|
||||
@@ -130,11 +130,11 @@ public class ThreadLocalTargetSourceTests {
|
||||
assertNotNull(r);
|
||||
|
||||
// Check it didn't affect the other thread's copy
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, apartment.getCount());
|
||||
|
||||
// When we use other thread's copy in this thread
|
||||
// it should behave like ours
|
||||
assertEquals(INITIAL_COUNT + 3, r.mine.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 3, r.mine.getCount());
|
||||
|
||||
// Bound to two threads
|
||||
assertEquals(2, ((ThreadLocalTargetSourceStats) apartment).getObjectCount());
|
||||
|
||||
@@ -80,8 +80,8 @@ compileTestJava {
|
||||
|
||||
dependencies {
|
||||
aspects(project(":spring-orm"))
|
||||
ajc("org.aspectj:aspectjtools:1.9.0") // for JDK 9+ build compatibility
|
||||
rt("org.aspectj:aspectjrt:1.9.0") // for JDK 9+ build compatibility
|
||||
ajc("org.aspectj:aspectjtools:1.9.1") // for JDK 9+ build compatibility
|
||||
rt("org.aspectj:aspectjrt:1.9.1") // for JDK 9+ build compatibility
|
||||
compile("org.aspectj:aspectjweaver:${aspectjVersion}") // for Maven POM exposure
|
||||
optional(project(":spring-aop")) // for @Async support
|
||||
optional(project(":spring-beans")) // for @Configurable support
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,6 +34,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see org.springframework.cache.annotation.CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.CACHE_ASPECT_BEAN_NAME)
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,6 +34,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see org.springframework.cache.annotation.CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class AspectJJCacheConfiguration extends AbstractJCacheConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.JCACHE_ASPECT_BEAN_NAME)
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,8 +56,8 @@ import org.springframework.util.Assert;
|
||||
* and obviates the need (<b>in part</b>) for a developer to code a method that
|
||||
* simply checks that all required properties have actually been set.
|
||||
*
|
||||
* <p>Please note that an 'init' method may still need to implemented (and may
|
||||
* still be desirable), because all that this class does is enforce that a
|
||||
* <p>Please note that an 'init' method may still need to be implemented (and may
|
||||
* still be desirable), because all that this class does is enforcing that a
|
||||
* 'required' property has actually been configured with a value. It does
|
||||
* <b>not</b> check anything else... In particular, it does not check that a
|
||||
* configured value is not {@code null}.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -225,7 +225,7 @@ public abstract class AbstractFactoryBean<T>
|
||||
* FactoryBean is supposed to implement, for use with an 'early singleton
|
||||
* proxy' that will be exposed in case of a circular reference.
|
||||
* <p>The default implementation returns this FactoryBean's object type,
|
||||
* provided that it is an interface, or {@code null} else. The latter
|
||||
* provided that it is an interface, or {@code null} otherwise. The latter
|
||||
* indicates that early singleton access is not supported by this FactoryBean.
|
||||
* This will lead to a FactoryBeanNotInitializedException getting thrown.
|
||||
* @return the interfaces to use for 'early singletons',
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,9 @@ public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, Single
|
||||
void setBeanClassLoader(@Nullable ClassLoader beanClassLoader);
|
||||
|
||||
/**
|
||||
* Return this factory's class loader for loading bean classes.
|
||||
* Return this factory's class loader for loading bean classes
|
||||
* (only {@code null} if even the system ClassLoader isn't accessible).
|
||||
* @see org.springframework.util.ClassUtils#forName(String, ClassLoader)
|
||||
*/
|
||||
@Nullable
|
||||
ClassLoader getBeanClassLoader();
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,6 +64,8 @@ import org.springframework.lang.Nullable;
|
||||
* Note that the value of "foo" in the first document is not simply replaced
|
||||
* with the value in the second, but its nested values are merged.
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
|
||||
+27
-13
@@ -30,6 +30,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.yaml.snakeyaml.LoaderOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
@@ -45,6 +46,8 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* Base class for YAML factories.
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
@@ -77,15 +80,16 @@ public abstract class YamlProcessor {
|
||||
* name: My Cool App
|
||||
* </pre>
|
||||
* when mapped with
|
||||
* <code>documentMatchers = YamlProcessor.mapMatcher({"environment": "prod"})</code>
|
||||
* <pre class="code">
|
||||
* setDocumentMatchers(properties ->
|
||||
* ("prod".equals(properties.getProperty("environment")) ? MatchStatus.FOUND : MatchStatus.NOT_FOUND));
|
||||
* </pre>
|
||||
* would end up as
|
||||
* <pre class="code">
|
||||
* environment=prod
|
||||
* url=http://foo.bar.com
|
||||
* name=My Cool App
|
||||
* url=http://dev.bar.com
|
||||
* </pre>
|
||||
* @param matchers a map of keys to value patterns (regular expressions)
|
||||
*/
|
||||
public void setDocumentMatchers(DocumentMatcher... matchers) {
|
||||
this.documentMatchers = Arrays.asList(matchers);
|
||||
@@ -94,8 +98,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Flag indicating that a document for which all the
|
||||
* {@link #setDocumentMatchers(DocumentMatcher...) document matchers} abstain will
|
||||
* nevertheless match.
|
||||
* @param matchDefault the flag to set (default true)
|
||||
* nevertheless match. Default is {@code true}.
|
||||
*/
|
||||
public void setMatchDefault(boolean matchDefault) {
|
||||
this.matchDefault = matchDefault;
|
||||
@@ -104,9 +107,7 @@ public abstract class YamlProcessor {
|
||||
/**
|
||||
* Method to use for resolving resources. Each resource will be converted to a Map,
|
||||
* so this property is used to decide which map entries to keep in the final output
|
||||
* from this factory.
|
||||
* @param resolutionMethod the resolution method to set (defaults to
|
||||
* {@link ResolutionMethod#OVERRIDE}).
|
||||
* from this factory. Default is {@link ResolutionMethod#OVERRIDE}.
|
||||
*/
|
||||
public void setResolutionMethod(ResolutionMethod resolutionMethod) {
|
||||
Assert.notNull(resolutionMethod, "ResolutionMethod must not be null");
|
||||
@@ -144,9 +145,14 @@ public abstract class YamlProcessor {
|
||||
|
||||
/**
|
||||
* Create the {@link Yaml} instance to use.
|
||||
* <p>The default implementation sets the "allowDuplicateKeys" flag to {@code false},
|
||||
* enabling built-in duplicate key handling in SnakeYAML 1.18+.
|
||||
* @see LoaderOptions#setAllowDuplicateKeys(boolean)
|
||||
*/
|
||||
protected Yaml createYaml() {
|
||||
return new Yaml(new StrictMapAppenderConstructor());
|
||||
LoaderOptions options = new LoaderOptions();
|
||||
options.setAllowDuplicateKeys(false);
|
||||
return new Yaml(options);
|
||||
}
|
||||
|
||||
private boolean process(MatchCallback callback, Yaml yaml, Resource resource) {
|
||||
@@ -293,10 +299,15 @@ public abstract class YamlProcessor {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
int count = 0;
|
||||
for (Object object : collection) {
|
||||
buildFlattenedMap(result,
|
||||
Collections.singletonMap("[" + (count++) + "]", object), key);
|
||||
if (collection.isEmpty()) {
|
||||
result.put(key, "");
|
||||
}
|
||||
else {
|
||||
int count = 0;
|
||||
for (Object object : collection) {
|
||||
buildFlattenedMap(result, Collections.singletonMap(
|
||||
"[" + (count++) + "]", object), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -389,7 +400,10 @@ public abstract class YamlProcessor {
|
||||
|
||||
/**
|
||||
* A specialized {@link Constructor} that checks for duplicate keys.
|
||||
* @deprecated as of Spring Framework 5.0.6 (not used anymore here),
|
||||
* superseded by SnakeYAML's own duplicate key handling
|
||||
*/
|
||||
@Deprecated
|
||||
protected static class StrictMapAppenderConstructor extends Constructor {
|
||||
|
||||
// Declared as public for use in subclasses
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,6 +74,8 @@ import org.springframework.lang.Nullable;
|
||||
* servers[1]=foo.bar.com
|
||||
* </pre>
|
||||
*
|
||||
* <p>Requires SnakeYAML 1.18 or higher, as of Spring Framework 5.0.6.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
|
||||
+20
-6
@@ -39,6 +39,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
@@ -752,7 +754,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod(
|
||||
factoryMethod, args, getBeanClassLoader());
|
||||
uniqueCandidate = (commonType == null ? factoryMethod : null);
|
||||
uniqueCandidate = (commonType == null && returnType == factoryMethod.getReturnType() ?
|
||||
factoryMethod : null);
|
||||
commonType = ClassUtils.determineCommonAncestor(returnType, commonType);
|
||||
if (commonType == null) {
|
||||
// Ambiguous return types found: return null to indicate "not determinable".
|
||||
@@ -776,12 +779,15 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
if (commonType != null) {
|
||||
// Clear return type found: all factory methods return same type.
|
||||
mbd.factoryMethodReturnType = (uniqueCandidate != null ?
|
||||
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
|
||||
if (commonType == null) {
|
||||
return null;
|
||||
}
|
||||
return commonType;
|
||||
// Common return type found: all factory methods return same type. For a non-parameterized
|
||||
// unique candidate, cache the full type declaration context of the target factory method.
|
||||
cachedReturnType = (uniqueCandidate != null ?
|
||||
ResolvableType.forMethodReturnType(uniqueCandidate) : ResolvableType.forClass(commonType));
|
||||
mbd.factoryMethodReturnType = cachedReturnType;
|
||||
return cachedReturnType.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1866,6 +1872,14 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the logger to collaborating delegates.
|
||||
* @since 5.0.7
|
||||
*/
|
||||
Log getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special DependencyDescriptor variant for Spring's good old autowire="byType" mode.
|
||||
|
||||
+1
-1
@@ -1501,7 +1501,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||
* should be used as fallback.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the merged bean definition for the bean
|
||||
* @return the type for the bean if determinable, or {@code null} else
|
||||
* @return the type for the bean if determinable, or {@code null} otherwise
|
||||
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
|
||||
* @see #getBean(String)
|
||||
*/
|
||||
|
||||
+11
-8
@@ -32,6 +32,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.beans.BeanMetadataElement;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
@@ -78,6 +80,8 @@ class ConstructorResolver {
|
||||
|
||||
private final AbstractAutowireCapableBeanFactory beanFactory;
|
||||
|
||||
private final Log logger;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConstructorResolver for the given factory and instantiation strategy.
|
||||
@@ -85,6 +89,7 @@ class ConstructorResolver {
|
||||
*/
|
||||
public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.logger = beanFactory.getLogger();
|
||||
}
|
||||
|
||||
|
||||
@@ -193,9 +198,8 @@ class ConstructorResolver {
|
||||
getUserDeclaredConstructor(candidate), autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
if (this.beanFactory.logger.isTraceEnabled()) {
|
||||
this.beanFactory.logger.trace(
|
||||
"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
}
|
||||
// Swallow and try next constructor.
|
||||
if (causes == null) {
|
||||
@@ -471,9 +475,8 @@ class ConstructorResolver {
|
||||
beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
|
||||
}
|
||||
catch (UnsatisfiedDependencyException ex) {
|
||||
if (this.beanFactory.logger.isTraceEnabled()) {
|
||||
this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
|
||||
"] of bean '" + beanName + "': " + ex);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
|
||||
}
|
||||
// Swallow and try next overloaded factory method.
|
||||
if (causes == null) {
|
||||
@@ -733,8 +736,8 @@ class ConstructorResolver {
|
||||
|
||||
for (String autowiredBeanName : autowiredBeanNames) {
|
||||
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
|
||||
if (this.beanFactory.logger.isDebugEnabled()) {
|
||||
this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Autowiring by type from bean name '" + beanName +
|
||||
"' via " + (executable instanceof Constructor ? "constructor" : "factory method") +
|
||||
" to bean named '" + autowiredBeanName + "'");
|
||||
}
|
||||
|
||||
-6
@@ -26,9 +26,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanCreationNotAllowedException;
|
||||
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
|
||||
@@ -73,9 +70,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/** Cache of singleton objects: bean name --> bean instance */
|
||||
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
|
||||
|
||||
|
||||
+8
@@ -107,6 +107,11 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
}
|
||||
else {
|
||||
if (shouldPostProcess) {
|
||||
if (isSingletonCurrentlyInCreation(beanName)) {
|
||||
// Temporarily return non-post-processed object, not storing it yet..
|
||||
return object;
|
||||
}
|
||||
beforeSingletonCreation(beanName);
|
||||
try {
|
||||
object = postProcessObjectFromFactoryBean(object, beanName);
|
||||
}
|
||||
@@ -114,6 +119,9 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
|
||||
throw new BeanCreationException(beanName,
|
||||
"Post-processing of FactoryBean's singleton object failed", ex);
|
||||
}
|
||||
finally {
|
||||
afterSingletonCreation(beanName);
|
||||
}
|
||||
}
|
||||
if (containsSingleton(beanName)) {
|
||||
this.factoryBeanObjectCache.put(beanName, object);
|
||||
|
||||
+18
-94
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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.beans.factory.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -56,7 +53,7 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setup() {
|
||||
p1BeanDef = rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${" + P1 + "}")
|
||||
.getBeanDefinition();
|
||||
@@ -66,16 +63,14 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
ppcProperties = new Properties();
|
||||
ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
|
||||
System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
|
||||
getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
|
||||
ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setProperties(ppcProperties);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
public void cleanup() {
|
||||
System.clearProperty(P1);
|
||||
getModifiableSystemEnvironment().remove(P1);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,8 +79,8 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean",
|
||||
genericBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
|
||||
PropertyPlaceholderConfigurer pc = new PropertyPlaceholderConfigurer();
|
||||
Resource resource = new ClassPathResource("PropertyPlaceholderConfigurerTests.properties", this.getClass());
|
||||
@@ -95,7 +90,7 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void resolveFromSystemProperties() {
|
||||
getModifiableSystemEnvironment().put("otherKey", "systemValue");
|
||||
System.setProperty("otherKey", "systemValue");
|
||||
p1BeanDef = rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${" + P1 + "}")
|
||||
.addPropertyValue("sex", "${otherKey}")
|
||||
@@ -105,12 +100,12 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
|
||||
assertThat(bean.getSex(), equalTo("systemValue"));
|
||||
getModifiableSystemEnvironment().remove("otherKey");
|
||||
System.clearProperty("otherKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveFromLocalProperties() {
|
||||
tearDown(); // eliminate entries from system props/environment
|
||||
System.clearProperty(P1);
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
@@ -134,16 +129,6 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
System.clearProperty(P1); // will now fall all the way back to system environment
|
||||
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
TestBean bean = bf.getBean(TestBean.class);
|
||||
assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
|
||||
registerWithGeneratedName(p1BeanDef, bf);
|
||||
@@ -160,7 +145,7 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
* settings regarding resolving properties from the environment.
|
||||
*/
|
||||
@Test
|
||||
public void twoPlacholderConfigurers_withConflictingSettings() {
|
||||
public void twoPlaceholderConfigurers_withConflictingSettings() {
|
||||
String P2 = "p2";
|
||||
String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
|
||||
String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
|
||||
@@ -178,7 +163,6 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
|
||||
System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
|
||||
getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
|
||||
Properties ppc2Properties = new Properties();
|
||||
ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
|
||||
|
||||
@@ -198,7 +182,6 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
|
||||
|
||||
System.clearProperty(P2);
|
||||
getModifiableSystemEnvironment().remove(P2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -210,9 +193,9 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean",
|
||||
rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "@<key1>")
|
||||
.addPropertyValue("sex", "${key2}")
|
||||
.getBeanDefinition());
|
||||
.addPropertyValue("name", "@<key1>")
|
||||
.addPropertyValue("sex", "${key2}")
|
||||
.getBeanDefinition());
|
||||
|
||||
System.setProperty("key1", "systemKey1Value");
|
||||
System.setProperty("key2", "systemKey2Value");
|
||||
@@ -228,100 +211,41 @@ public class PropertyPlaceholderConfigurerTests {
|
||||
public void nullValueIsPreserved() {
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setNullValue("customNull");
|
||||
getModifiableSystemEnvironment().put("my.name", "customNull");
|
||||
System.setProperty("my.name", "customNull");
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), nullValue());
|
||||
getModifiableSystemEnvironment().remove("my.name");
|
||||
System.clearProperty("my.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trimValuesIsOffByDefault() {
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
getModifiableSystemEnvironment().put("my.name", " myValue ");
|
||||
System.setProperty("my.name", " myValue ");
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo(" myValue "));
|
||||
getModifiableSystemEnvironment().remove("my.name");
|
||||
System.clearProperty("my.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trimValuesIsApplied() {
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
ppc.setTrimValues(true);
|
||||
getModifiableSystemEnvironment().put("my.name", " myValue ");
|
||||
System.setProperty("my.name", " myValue ");
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
|
||||
.addPropertyValue("name", "${my.name}")
|
||||
.getBeanDefinition());
|
||||
ppc.postProcessBeanFactory(bf);
|
||||
assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
|
||||
getModifiableSystemEnvironment().remove("my.name");
|
||||
System.clearProperty("my.name");
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Map<String, String> getModifiableSystemEnvironment() {
|
||||
// for os x / linux
|
||||
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
||||
Map<String, String> env = System.getenv();
|
||||
for (Class<?> cl : classes) {
|
||||
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
|
||||
try {
|
||||
Field field = cl.getDeclaredField("m");
|
||||
field.setAccessible(true);
|
||||
Object obj = field.get(env);
|
||||
if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) {
|
||||
return (Map<String, String>) obj;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for windows
|
||||
Class<?> processEnvironmentClass;
|
||||
try {
|
||||
processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
|
||||
theCaseInsensitiveEnvironmentField.setAccessible(true);
|
||||
Object obj = theCaseInsensitiveEnvironmentField.get(null);
|
||||
return (Map<String, String>) obj;
|
||||
}
|
||||
catch (NoSuchFieldException ex) {
|
||||
// do nothing
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
|
||||
theEnvironmentField.setAccessible(true);
|
||||
Object obj = theEnvironmentField.get(null);
|
||||
return (Map<String, String>) obj;
|
||||
}
|
||||
catch (NoSuchFieldException ex) {
|
||||
// do nothing
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
+12
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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 java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.yaml.snakeyaml.constructor.DuplicateKeyException;
|
||||
|
||||
import org.springframework.core.io.AbstractResource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
@@ -41,27 +42,27 @@ public class YamlMapFactoryBeanTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
||||
public void testSetIgnoreResourceNotFound() {
|
||||
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
||||
public void testSetBarfOnResourceNotFound() {
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObject() throws Exception {
|
||||
public void testGetObject() {
|
||||
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testOverrideAndRemoveDefaults() throws Exception {
|
||||
public void testOverrideAndRemoveDefaults() {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||
|
||||
@@ -70,7 +71,7 @@ public class YamlMapFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstFound() throws Exception {
|
||||
public void testFirstFound() {
|
||||
this.factory.setResolutionMethod(YamlProcessor.ResolutionMethod.FIRST_FOUND);
|
||||
this.factory.setResources(new AbstractResource() {
|
||||
@Override
|
||||
@@ -87,7 +88,7 @@ public class YamlMapFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithPeriodsInKey() throws Exception {
|
||||
public void testMapWithPeriodsInKey() {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
@@ -102,7 +103,7 @@ public class YamlMapFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithIntegerValue() throws Exception {
|
||||
public void testMapWithIntegerValue() {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
@@ -116,19 +117,10 @@ public class YamlMapFactoryBeanTests {
|
||||
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateKey() throws Exception {
|
||||
@Test(expected = DuplicateKeyException.class)
|
||||
public void testDuplicateKey() {
|
||||
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("mymap"));
|
||||
Object object = map.get("mymap");
|
||||
assertTrue(object instanceof LinkedHashMap);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> sub = (Map<String, Object>) object;
|
||||
assertEquals(1, sub.size());
|
||||
assertEquals("foo", sub.get("bar"));
|
||||
this.factory.getObject().get("mymap");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
-66
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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.beans.factory.config;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -29,7 +28,6 @@ import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.beans.factory.config.YamlProcessor.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link YamlProcessor}.
|
||||
@@ -48,91 +46,65 @@ public class YamlProcessorTests {
|
||||
@Test
|
||||
public void arrayConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals(4, properties.size());
|
||||
assertEquals("bar", properties.get("foo"));
|
||||
assertEquals("bar", properties.getProperty("foo"));
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals("1", properties.getProperty("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals("2", properties.getProperty("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals("3", properties.getProperty("bar[2]"));
|
||||
}
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals(4, properties.size());
|
||||
assertEquals("bar", properties.get("foo"));
|
||||
assertEquals("bar", properties.getProperty("foo"));
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals("1", properties.getProperty("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals("2", properties.getProperty("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals("3", properties.getProperty("bar[2]"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringResource() throws Exception {
|
||||
public void testStringResource() {
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("foo", map.get("document"));
|
||||
}
|
||||
});
|
||||
this.processor.process((properties, map) -> assertEquals("foo", map.get("document")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadDocumentStart() throws Exception {
|
||||
public void testBadDocumentStart() {
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
||||
this.exception.expect(ParserException.class);
|
||||
this.exception.expectMessage("line 2, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
}
|
||||
});
|
||||
this.processor.process((properties, map) -> {});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
public void testBadResource() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
}
|
||||
});
|
||||
this.processor.process((properties, map) -> {});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
// System.err.println(properties);
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
}
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integerKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("[1]"));
|
||||
assertEquals(2, properties.size());
|
||||
}
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bar", properties.get("[1]"));
|
||||
assertEquals(2, properties.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integerDeepKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
assertEquals(1, properties.size());
|
||||
}
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
assertEquals(1, properties.size());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,18 +112,15 @@ public class YamlProcessorTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
|
||||
assertEquals("bucket", flattenedMap.get("bar.spam"));
|
||||
assertEquals(2, flattenedMap.size());
|
||||
assertTrue(flattenedMap instanceof LinkedHashMap);
|
||||
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
|
||||
assertEquals("bucket", bar.get("spam"));
|
||||
}
|
||||
this.processor.process((properties, map) -> {
|
||||
assertEquals("bucket", properties.get("bar.spam"));
|
||||
assertEquals(2, properties.size());
|
||||
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
|
||||
assertEquals("bucket", flattenedMap.get("bar.spam"));
|
||||
assertEquals(2, flattenedMap.size());
|
||||
assertTrue(flattenedMap instanceof LinkedHashMap);
|
||||
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
|
||||
assertEquals("bucket", bar.get("spam"));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+45
-51
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,11 +19,11 @@ package org.springframework.beans.factory.config;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.DuplicateKeyException;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
@@ -46,17 +46,16 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoadResource() throws Exception {
|
||||
public void testLoadResource() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo: bar\nspam:\n foo: baz".getBytes()));
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam.foo"), equalTo("baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
public void testBadResource() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
@@ -66,7 +65,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourcesWithOverride() throws Exception {
|
||||
public void testLoadResourcesWithOverride() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(
|
||||
new ByteArrayResource("foo: bar\nspam:\n foo: baz".getBytes()),
|
||||
@@ -77,27 +76,24 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourcesWithInternalOverride() throws Exception {
|
||||
@Test(expected = DuplicateKeyException.class)
|
||||
public void testLoadResourcesWithInternalOverride() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo: bar\nspam:\n foo: baz\nfoo: bucket".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bucket"));
|
||||
factory.getObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("We can't fail on duplicate keys because the Map is created by the YAML library")
|
||||
public void testLoadResourcesWithNestedInternalOverride() throws Exception {
|
||||
@Test(expected = DuplicateKeyException.class)
|
||||
public void testLoadResourcesWithNestedInternalOverride() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo:\n bar: spam\n foo: baz\nbreak: it\nfoo: bucket".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo.bar"), equalTo("spam"));
|
||||
factory.getObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithMultipleDocuments() throws Exception {
|
||||
public void testLoadResourceWithMultipleDocuments() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo: bar\nspam: baz\n---\nfoo: bag".getBytes()));
|
||||
@@ -107,37 +103,29 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithSelectedDocuments() throws Exception {
|
||||
public void testLoadResourceWithSelectedDocuments() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
factory.setDocumentMatchers(properties -> ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
assertThat(properties.getProperty("spam"), equalTo("bad"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithDefaultMatch() throws Exception {
|
||||
public void testLoadResourceWithDefaultMatch() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(true);
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"one: two\n---\nfoo: bar\nspam: baz\n---\nfoo: bag\nspam: bad".getBytes()));
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
factory.setDocumentMatchers(properties -> {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
@@ -146,7 +134,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithoutDefaultMatch() throws Exception {
|
||||
public void testLoadResourceWithoutDefaultMatch() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(false);
|
||||
factory.setResources(new ByteArrayResource(
|
||||
@@ -168,20 +156,17 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() throws Exception {
|
||||
public void testLoadResourceWithDefaultMatchSkippingMissedMatch() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setMatchDefault(true);
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"one: two\n---\nfoo: bag\nspam: bad\n---\nfoo: bar\nspam: baz".getBytes()));
|
||||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
factory.setDocumentMatchers(properties -> {
|
||||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bag"));
|
||||
@@ -190,7 +175,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadNonExistentResource() throws Exception {
|
||||
public void testLoadNonExistentResource() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResolutionMethod(ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
factory.setResources(new ClassPathResource("no-such-file.yml"));
|
||||
@@ -199,7 +184,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadNull() throws Exception {
|
||||
public void testLoadNull() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
@@ -208,7 +193,16 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfString() throws Exception {
|
||||
public void testLoadEmptyArrayValue() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("a: alpha\ntest: []".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("a"), equalTo("alpha"));
|
||||
assertThat(properties.getProperty("test"), equalTo(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfString() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
@@ -218,7 +212,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfInteger() throws Exception {
|
||||
public void testLoadArrayOfInteger() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
@@ -228,7 +222,7 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfObject() throws Exception {
|
||||
public void testLoadArrayOfObject() {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
|
||||
@@ -246,8 +240,8 @@ public class YamlPropertiesFactoryBeanTests {
|
||||
public void testYaml() {
|
||||
Yaml yaml = new Yaml();
|
||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo((Object) "baz"));
|
||||
assertThat(map.get("foo"), equalTo("bar"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo("baz"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+46
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +40,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.beans.propertyeditors.CustomNumberEditor;
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
@@ -672,6 +673,8 @@ public class BeanFactoryGenericsTests {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
@@ -700,6 +703,10 @@ public class BeanFactoryGenericsTests {
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class);
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
@@ -717,6 +724,10 @@ public class BeanFactoryGenericsTests {
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class.getName());
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
@@ -732,6 +743,10 @@ public class BeanFactoryGenericsTests {
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(new TypedStringValue(Runnable.class.getName()));
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
@@ -749,6 +764,10 @@ public class BeanFactoryGenericsTests {
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue("x");
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertFalse(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertFalse(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertNull(bf.getType("mock"));
|
||||
assertNull(bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(0, beans.size());
|
||||
}
|
||||
@@ -766,6 +785,32 @@ public class BeanFactoryGenericsTests {
|
||||
rbd.getConstructorArgumentValues().addIndexedArgumentValue(0, Runnable.class);
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
|
||||
@Test // SPR-16720
|
||||
public void parameterizedInstanceFactoryMethodWithTempClassLoader() {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
bf.setTempClassLoader(new OverridingClassLoader(getClass().getClassLoader()));
|
||||
|
||||
RootBeanDefinition rbd = new RootBeanDefinition(MocksControl.class);
|
||||
bf.registerBeanDefinition("mocksControl", rbd);
|
||||
|
||||
rbd = new RootBeanDefinition();
|
||||
rbd.setFactoryBeanName("mocksControl");
|
||||
rbd.setFactoryMethodName("createMock");
|
||||
rbd.getConstructorArgumentValues().addGenericArgumentValue(Runnable.class);
|
||||
bf.registerBeanDefinition("mock", rbd);
|
||||
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertTrue(bf.isTypeMatch("mock", Runnable.class));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
assertEquals(Runnable.class, bf.getType("mock"));
|
||||
Map<String, Runnable> beans = bf.getBeansOfType(Runnable.class);
|
||||
assertEquals(1, beans.size());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.tests.sample.beans;
|
||||
|
||||
public interface AgeHolder {
|
||||
|
||||
default int age() {
|
||||
return getAge();
|
||||
}
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,11 +27,7 @@ import java.io.IOException;
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public interface ITestBean {
|
||||
|
||||
int getAge();
|
||||
|
||||
void setAge(int age);
|
||||
public interface ITestBean extends AgeHolder {
|
||||
|
||||
String getName();
|
||||
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -62,9 +62,9 @@ class TypeHelper {
|
||||
DeclaredType declaredType = (DeclaredType) type;
|
||||
Element enclosingElement = declaredType.asElement().getEnclosingElement();
|
||||
if (enclosingElement != null && enclosingElement instanceof TypeElement) {
|
||||
return getQualifiedName(enclosingElement) + "$"
|
||||
+ declaredType.asElement().getSimpleName().toString();
|
||||
} else {
|
||||
return getQualifiedName(enclosingElement) + "$" + declaredType.asElement().getSimpleName().toString();
|
||||
}
|
||||
else {
|
||||
return getQualifiedName(declaredType.asElement());
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class TypeHelper {
|
||||
public Element getSuperClass(Element element) {
|
||||
List<? extends TypeMirror> superTypes = this.types.directSupertypes(element.asType());
|
||||
if (superTypes.isEmpty()) {
|
||||
return null; // reached java.lang.Object
|
||||
return null; // reached java.lang.Object
|
||||
}
|
||||
return this.types.asElement(superTypes.get(0));
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ dependencies {
|
||||
optional("org.freemarker:freemarker:${freemarkerVersion}")
|
||||
testCompile(project(":spring-context"))
|
||||
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
|
||||
testCompile("org.hibernate:hibernate-validator:6.0.9.Final")
|
||||
testCompile("org.hibernate:hibernate-validator:6.0.10.Final")
|
||||
testCompile("javax.annotation:javax.annotation-api:1.3.2")
|
||||
testRuntime("org.ehcache:jcache:1.0.1")
|
||||
testRuntime("org.ehcache:ehcache:3.4.0")
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see org.springframework.cache.annotation.CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class ProxyJCacheConfiguration extends AbstractJCacheConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.JCACHE_ADVISOR_BEAN_NAME)
|
||||
|
||||
+66
-53
@@ -486,61 +486,21 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
this.resourceLoader = this.applicationContext;
|
||||
}
|
||||
|
||||
// Initialize the SchedulerFactory instance...
|
||||
SchedulerFactory schedulerFactory = prepareSchedulerFactory();
|
||||
|
||||
if (this.resourceLoader != null) {
|
||||
// Make given ResourceLoader available for SchedulerFactory configuration.
|
||||
configTimeResourceLoaderHolder.set(this.resourceLoader);
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
// Make given TaskExecutor available for SchedulerFactory configuration.
|
||||
configTimeTaskExecutorHolder.set(this.taskExecutor);
|
||||
}
|
||||
if (this.dataSource != null) {
|
||||
// Make given DataSource available for SchedulerFactory configuration.
|
||||
configTimeDataSourceHolder.set(this.dataSource);
|
||||
}
|
||||
if (this.nonTransactionalDataSource != null) {
|
||||
// Make given non-transactional DataSource available for SchedulerFactory configuration.
|
||||
configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource);
|
||||
}
|
||||
|
||||
// Get Scheduler instance from SchedulerFactory.
|
||||
// Initialize the Scheduler instance...
|
||||
this.scheduler = prepareScheduler(prepareSchedulerFactory());
|
||||
try {
|
||||
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
|
||||
populateSchedulerContext();
|
||||
|
||||
if (!this.jobFactorySet && !(this.scheduler instanceof RemoteScheduler)) {
|
||||
// Use AdaptableJobFactory as default for a local Scheduler, unless when
|
||||
// explicitly given a null value through the "jobFactory" bean property.
|
||||
this.jobFactory = new AdaptableJobFactory();
|
||||
}
|
||||
if (this.jobFactory != null) {
|
||||
if (this.jobFactory instanceof SchedulerContextAware) {
|
||||
((SchedulerContextAware) this.jobFactory).setSchedulerContext(this.scheduler.getContext());
|
||||
}
|
||||
this.scheduler.setJobFactory(this.jobFactory);
|
||||
}
|
||||
registerListeners();
|
||||
registerJobsAndTriggers();
|
||||
}
|
||||
|
||||
finally {
|
||||
if (this.resourceLoader != null) {
|
||||
configTimeResourceLoaderHolder.remove();
|
||||
catch (Exception ex) {
|
||||
try {
|
||||
this.scheduler.shutdown(true);
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
configTimeTaskExecutorHolder.remove();
|
||||
}
|
||||
if (this.dataSource != null) {
|
||||
configTimeDataSourceHolder.remove();
|
||||
}
|
||||
if (this.nonTransactionalDataSource != null) {
|
||||
configTimeNonTransactionalDataSourceHolder.remove();
|
||||
catch (Exception ex2) {
|
||||
logger.debug("Scheduler shutdown exception after registration failure", ex2);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
registerListeners();
|
||||
registerJobsAndTriggers();
|
||||
}
|
||||
|
||||
|
||||
@@ -607,6 +567,59 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
schedulerFactory.initialize(mergedProps);
|
||||
}
|
||||
|
||||
private Scheduler prepareScheduler(SchedulerFactory schedulerFactory) throws SchedulerException {
|
||||
if (this.resourceLoader != null) {
|
||||
// Make given ResourceLoader available for SchedulerFactory configuration.
|
||||
configTimeResourceLoaderHolder.set(this.resourceLoader);
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
// Make given TaskExecutor available for SchedulerFactory configuration.
|
||||
configTimeTaskExecutorHolder.set(this.taskExecutor);
|
||||
}
|
||||
if (this.dataSource != null) {
|
||||
// Make given DataSource available for SchedulerFactory configuration.
|
||||
configTimeDataSourceHolder.set(this.dataSource);
|
||||
}
|
||||
if (this.nonTransactionalDataSource != null) {
|
||||
// Make given non-transactional DataSource available for SchedulerFactory configuration.
|
||||
configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource);
|
||||
}
|
||||
|
||||
// Get Scheduler instance from SchedulerFactory.
|
||||
try {
|
||||
Scheduler scheduler = createScheduler(schedulerFactory, this.schedulerName);
|
||||
populateSchedulerContext(scheduler);
|
||||
|
||||
if (!this.jobFactorySet && !(scheduler instanceof RemoteScheduler)) {
|
||||
// Use AdaptableJobFactory as default for a local Scheduler, unless when
|
||||
// explicitly given a null value through the "jobFactory" bean property.
|
||||
this.jobFactory = new AdaptableJobFactory();
|
||||
}
|
||||
if (this.jobFactory != null) {
|
||||
if (this.jobFactory instanceof SchedulerContextAware) {
|
||||
((SchedulerContextAware) this.jobFactory).setSchedulerContext(scheduler.getContext());
|
||||
}
|
||||
scheduler.setJobFactory(this.jobFactory);
|
||||
}
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
finally {
|
||||
if (this.resourceLoader != null) {
|
||||
configTimeResourceLoaderHolder.remove();
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
configTimeTaskExecutorHolder.remove();
|
||||
}
|
||||
if (this.dataSource != null) {
|
||||
configTimeDataSourceHolder.remove();
|
||||
}
|
||||
if (this.nonTransactionalDataSource != null) {
|
||||
configTimeNonTransactionalDataSourceHolder.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Scheduler instance for the given factory and scheduler name.
|
||||
* Called by {@link #afterPropertiesSet}.
|
||||
@@ -658,10 +671,10 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
* Expose the specified context attributes and/or the current
|
||||
* ApplicationContext in the Quartz SchedulerContext.
|
||||
*/
|
||||
private void populateSchedulerContext() throws SchedulerException {
|
||||
private void populateSchedulerContext(Scheduler scheduler) throws SchedulerException {
|
||||
// Put specified objects into Scheduler context.
|
||||
if (this.schedulerContextMap != null) {
|
||||
getScheduler().getContext().putAll(this.schedulerContextMap);
|
||||
scheduler.getContext().putAll(this.schedulerContextMap);
|
||||
}
|
||||
|
||||
// Register ApplicationContext in Scheduler context.
|
||||
@@ -671,7 +684,7 @@ public class SchedulerFactoryBean extends SchedulerAccessor implements FactoryBe
|
||||
"SchedulerFactoryBean needs to be set up in an ApplicationContext " +
|
||||
"to be able to handle an 'applicationContextSchedulerContextKey'");
|
||||
}
|
||||
getScheduler().getContext().put(this.applicationContextSchedulerContextKey, this.applicationContext);
|
||||
scheduler.getContext().put(this.applicationContextSchedulerContextKey, this.applicationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -61,7 +61,7 @@ import static org.junit.Assert.*;
|
||||
public class ValidatorFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleValidation() throws Exception {
|
||||
public void testSimpleValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -87,7 +87,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithCustomProvider() throws Exception {
|
||||
public void testSimpleValidationWithCustomProvider() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.setProviderClass(HibernateValidator.class);
|
||||
validator.afterPropertiesSet();
|
||||
@@ -114,9 +114,10 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithClassLevel() throws Exception {
|
||||
public void testSimpleValidationWithClassLevel() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
@@ -129,7 +130,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationFieldType() throws Exception {
|
||||
public void testSpringValidationFieldType() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -144,7 +145,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidation() throws Exception {
|
||||
public void testSpringValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -172,7 +173,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithClassLevel() throws Exception {
|
||||
public void testSpringValidationWithClassLevel() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -190,7 +191,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithAutowiredValidator() throws Exception {
|
||||
public void testSpringValidationWithAutowiredValidator() {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
LocalValidatorFactoryBean.class);
|
||||
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
|
||||
@@ -211,7 +212,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInListElement() throws Exception {
|
||||
public void testSpringValidationWithErrorInListElement() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -229,7 +230,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInSetElement() throws Exception {
|
||||
public void testSpringValidationWithErrorInSetElement() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -247,7 +248,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInnerBeanValidation() throws Exception {
|
||||
public void testInnerBeanValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -259,7 +260,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidationWithOptionalField() throws Exception {
|
||||
public void testValidationWithOptionalField() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -271,7 +272,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListValidation() throws Exception {
|
||||
public void testListValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,6 +35,7 @@ import org.springframework.context.annotation.Role;
|
||||
* @see CachingConfigurationSelector
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class ProxyCachingConfiguration extends AbstractCachingConfiguration {
|
||||
|
||||
@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)
|
||||
|
||||
+15
-8
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cache.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -30,6 +31,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.framework.AopProxyUtils;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -624,6 +627,10 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
|
||||
private final Class<?> targetClass;
|
||||
|
||||
private final Method targetMethod;
|
||||
|
||||
private final AnnotatedElementKey methodKey;
|
||||
|
||||
private final KeyGenerator keyGenerator;
|
||||
|
||||
private final CacheResolver cacheResolver;
|
||||
@@ -632,8 +639,11 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
KeyGenerator keyGenerator, CacheResolver cacheResolver) {
|
||||
|
||||
this.operation = operation;
|
||||
this.method = method;
|
||||
this.method = BridgeMethodResolver.findBridgedMethod(method);
|
||||
this.targetClass = targetClass;
|
||||
this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
|
||||
AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
|
||||
this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
|
||||
this.keyGenerator = keyGenerator;
|
||||
this.cacheResolver = cacheResolver;
|
||||
}
|
||||
@@ -652,15 +662,12 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
|
||||
private final Collection<String> cacheNames;
|
||||
|
||||
private final AnnotatedElementKey methodCacheKey;
|
||||
|
||||
public CacheOperationContext(CacheOperationMetadata metadata, Object[] args, Object target) {
|
||||
this.metadata = metadata;
|
||||
this.args = extractArgs(metadata.method, args);
|
||||
this.target = target;
|
||||
this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver);
|
||||
this.cacheNames = createCacheNames(this.caches);
|
||||
this.methodCacheKey = new AnnotatedElementKey(metadata.method, metadata.targetClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -698,7 +705,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
if (StringUtils.hasText(this.metadata.operation.getCondition())) {
|
||||
EvaluationContext evaluationContext = createEvaluationContext(result);
|
||||
return evaluator.condition(this.metadata.operation.getCondition(),
|
||||
this.methodCacheKey, evaluationContext);
|
||||
this.metadata.methodKey, evaluationContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -713,7 +720,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
}
|
||||
if (StringUtils.hasText(unless)) {
|
||||
EvaluationContext evaluationContext = createEvaluationContext(value);
|
||||
return !evaluator.unless(unless, this.methodCacheKey, evaluationContext);
|
||||
return !evaluator.unless(unless, this.metadata.methodKey, evaluationContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -725,14 +732,14 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
|
||||
protected Object generateKey(@Nullable Object result) {
|
||||
if (StringUtils.hasText(this.metadata.operation.getKey())) {
|
||||
EvaluationContext evaluationContext = createEvaluationContext(result);
|
||||
return evaluator.key(this.metadata.operation.getKey(), this.methodCacheKey, evaluationContext);
|
||||
return evaluator.key(this.metadata.operation.getKey(), this.metadata.methodKey, evaluationContext);
|
||||
}
|
||||
return this.metadata.keyGenerator.generate(this.target, this.metadata.method, this.args);
|
||||
}
|
||||
|
||||
private EvaluationContext createEvaluationContext(@Nullable Object result) {
|
||||
return evaluator.createEvaluationContext(this.caches, this.metadata.method, this.args,
|
||||
this.target, this.metadata.targetClass, result, beanFactory);
|
||||
this.target, this.metadata.targetClass, this.metadata.targetMethod, result, beanFactory);
|
||||
}
|
||||
|
||||
protected Collection<? extends Cache> getCaches() {
|
||||
|
||||
Vendored
+1
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,6 @@ import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Class describing the root object used during the expression evaluation.
|
||||
@@ -45,8 +44,6 @@ class CacheExpressionRootObject {
|
||||
public CacheExpressionRootObject(
|
||||
Collection<? extends Cache> caches, Method method, Object[] args, Object target, Class<?> targetClass) {
|
||||
|
||||
Assert.notNull(method, "Method is required");
|
||||
Assert.notNull(targetClass, "targetClass is required");
|
||||
this.method = method;
|
||||
this.target = target;
|
||||
this.targetClass = targetClass;
|
||||
|
||||
+3
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
@@ -68,18 +67,6 @@ class CacheOperationExpressionEvaluator extends CachedExpressionEvaluator {
|
||||
|
||||
private final Map<ExpressionKey, Expression> unlessCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
private final Map<AnnotatedElementKey, Method> targetMethodCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
|
||||
/**
|
||||
* Create an {@link EvaluationContext} without a return value.
|
||||
* @see #createEvaluationContext(Collection, Method, Object[], Object, Class, Object, BeanFactory)
|
||||
*/
|
||||
public EvaluationContext createEvaluationContext(Collection<? extends Cache> caches,
|
||||
Method method, Object[] args, Object target, Class<?> targetClass, BeanFactory beanFactory) {
|
||||
|
||||
return createEvaluationContext(caches, method, args, target, targetClass, NO_RESULT, beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link EvaluationContext}.
|
||||
@@ -93,12 +80,11 @@ class CacheOperationExpressionEvaluator extends CachedExpressionEvaluator {
|
||||
* @return the evaluation context
|
||||
*/
|
||||
public EvaluationContext createEvaluationContext(Collection<? extends Cache> caches,
|
||||
Method method, Object[] args, Object target, Class<?> targetClass, @Nullable Object result,
|
||||
@Nullable BeanFactory beanFactory) {
|
||||
Method method, Object[] args, Object target, Class<?> targetClass, Method targetMethod,
|
||||
@Nullable Object result, @Nullable BeanFactory beanFactory) {
|
||||
|
||||
CacheExpressionRootObject rootObject = new CacheExpressionRootObject(
|
||||
caches, method, args, target, targetClass);
|
||||
Method targetMethod = getTargetMethod(targetClass, method);
|
||||
CacheEvaluationContext evaluationContext = new CacheEvaluationContext(
|
||||
rootObject, targetMethod, args, getParameterNameDiscoverer());
|
||||
if (result == RESULT_UNAVAILABLE) {
|
||||
@@ -135,18 +121,6 @@ class CacheOperationExpressionEvaluator extends CachedExpressionEvaluator {
|
||||
this.keyCache.clear();
|
||||
this.conditionCache.clear();
|
||||
this.unlessCache.clear();
|
||||
this.targetMethodCache.clear();
|
||||
}
|
||||
|
||||
private Method getTargetMethod(Class<?> targetClass, Method method) {
|
||||
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
|
||||
Method targetMethod = this.targetMethodCache.get(methodKey);
|
||||
if (targetMethod == null) {
|
||||
targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
this.targetMethodCache.put(methodKey, targetMethod);
|
||||
}
|
||||
return targetMethod;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,13 +30,15 @@ class VariableNotAvailableException extends EvaluationException {
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
public VariableNotAvailableException(String name) {
|
||||
super("Variable '" + name + "' is not available");
|
||||
super("Variable not available");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Context information for use by {@link Condition}s.
|
||||
@@ -33,13 +34,17 @@ public interface ConditionContext {
|
||||
/**
|
||||
* Return the {@link BeanDefinitionRegistry} that will hold the bean definition
|
||||
* should the condition match.
|
||||
* @throws IllegalStateException if no registry is available (which is unusual:
|
||||
* only the case with a plain {@link ClassPathScanningCandidateComponentProvider})
|
||||
*/
|
||||
BeanDefinitionRegistry getRegistry();
|
||||
|
||||
/**
|
||||
* Return the {@link ConfigurableListableBeanFactory} that will hold the bean
|
||||
* definition should the condition match.
|
||||
* definition should the condition match, or {@code null} if the bean factory is
|
||||
* not available (or not downcastable to {@code ConfigurableListableBeanFactory}).
|
||||
*/
|
||||
@Nullable
|
||||
ConfigurableListableBeanFactory getBeanFactory();
|
||||
|
||||
/**
|
||||
@@ -53,8 +58,11 @@ public interface ConditionContext {
|
||||
ResourceLoader getResourceLoader();
|
||||
|
||||
/**
|
||||
* Return the {@link ClassLoader} that should be used to load additional classes.
|
||||
* Return the {@link ClassLoader} that should be used to load additional classes
|
||||
* (only {@code null} if even the system ClassLoader isn't accessible).
|
||||
* @see org.springframework.util.ClassUtils#forName(String, ClassLoader)
|
||||
*/
|
||||
@Nullable
|
||||
ClassLoader getClassLoader();
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -120,7 +120,7 @@ class ConditionEvaluator {
|
||||
return (List<String[]>) (values != null ? values : Collections.emptyList());
|
||||
}
|
||||
|
||||
private Condition getCondition(String conditionClassName, ClassLoader classloader) {
|
||||
private Condition getCondition(String conditionClassName, @Nullable ClassLoader classloader) {
|
||||
Class<?> conditionClass = ClassUtils.resolveClassName(conditionClassName, classloader);
|
||||
return (Condition) BeanUtils.instantiateClass(conditionClass);
|
||||
}
|
||||
@@ -202,8 +202,8 @@ class ConditionEvaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ConfigurableListableBeanFactory getBeanFactory() {
|
||||
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory available");
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
@@ -218,8 +218,8 @@ class ConditionEvaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ClassLoader getClassLoader() {
|
||||
Assert.state(this.classLoader != null, "No ClassLoader available");
|
||||
return this.classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -122,8 +122,8 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
* Read a particular {@link ConfigurationClass}, registering bean definitions
|
||||
* for the class itself and all of its {@link Bean} methods.
|
||||
*/
|
||||
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass,
|
||||
TrackedConditionEvaluator trackedConditionEvaluator) {
|
||||
private void loadBeanDefinitionsForConfigurationClass(
|
||||
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
|
||||
|
||||
if (trackedConditionEvaluator.shouldSkip(configClass)) {
|
||||
String beanName = configClass.getBeanName();
|
||||
@@ -140,6 +140,7 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
|
||||
loadBeanDefinitionsForBeanMethod(beanMethod);
|
||||
}
|
||||
|
||||
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
|
||||
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
|
||||
}
|
||||
|
||||
+2
-2
@@ -118,9 +118,9 @@ class ConfigurationClassEnhancer {
|
||||
/**
|
||||
* Creates a new CGLIB {@link Enhancer} instance.
|
||||
*/
|
||||
private Enhancer newEnhancer(Class<?> superclass, @Nullable ClassLoader classLoader) {
|
||||
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(superclass);
|
||||
enhancer.setSuperclass(configSuperClass);
|
||||
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
|
||||
enhancer.setUseFactory(false);
|
||||
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
|
||||
|
||||
+6
-3
@@ -288,9 +288,12 @@ class ConfigurationClassParser {
|
||||
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
|
||||
// Check the set of scanned definitions for any further config classes and parse recursively if needed
|
||||
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
|
||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(
|
||||
holder.getBeanDefinition(), this.metadataReaderFactory)) {
|
||||
parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
|
||||
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
|
||||
if (bdCand == null) {
|
||||
bdCand = holder.getBeanDefinition();
|
||||
}
|
||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
|
||||
parse(bdCand.getBeanClassName(), holder.getBeanName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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.lang.Nullable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Utilities for processing @{@link Configuration} classes.
|
||||
* Utilities for identifying @{@link Configuration} classes.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
@@ -60,7 +60,7 @@ abstract class ConfigurationClassUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationClassUtils.class);
|
||||
|
||||
private static final Set<String> candidateIndicators = new HashSet<>(4);
|
||||
private static final Set<String> candidateIndicators = new HashSet<>(8);
|
||||
|
||||
static {
|
||||
candidateIndicators.add(Component.class.getName());
|
||||
|
||||
+30
-33
@@ -18,6 +18,7 @@ package org.springframework.context.event;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -27,6 +28,7 @@ import java.util.List;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.PayloadApplicationEvent;
|
||||
@@ -35,10 +37,8 @@ import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -66,9 +66,9 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final Class<?> targetClass;
|
||||
private final Method targetMethod;
|
||||
|
||||
private final Method bridgedMethod;
|
||||
private final AnnotatedElementKey methodKey;
|
||||
|
||||
private final List<ResolvableType> declaredEventTypes;
|
||||
|
||||
@@ -77,8 +77,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
private final int order;
|
||||
|
||||
private final AnnotatedElementKey methodKey;
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@@ -88,18 +86,15 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
|
||||
this.beanName = beanName;
|
||||
this.method = method;
|
||||
this.targetClass = targetClass;
|
||||
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
|
||||
Method targetMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(targetMethod, EventListener.class);
|
||||
this.method = BridgeMethodResolver.findBridgedMethod(method);
|
||||
this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
|
||||
AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
|
||||
this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
|
||||
|
||||
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(this.targetMethod, EventListener.class);
|
||||
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
|
||||
this.condition = (ann != null ? ann.condition() : null);
|
||||
this.order = resolveOrder(method);
|
||||
|
||||
this.methodKey = new AnnotatedElementKey(method, targetClass);
|
||||
}
|
||||
|
||||
|
||||
@@ -109,20 +104,23 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
throw new IllegalStateException(
|
||||
"Maximum one parameter is allowed for event listener method: " + method);
|
||||
}
|
||||
if (ann != null && ann.classes().length > 0) {
|
||||
List<ResolvableType> types = new ArrayList<>(ann.classes().length);
|
||||
for (Class<?> eventType : ann.classes()) {
|
||||
types.add(ResolvableType.forClass(eventType));
|
||||
|
||||
if (ann != null) {
|
||||
Class<?>[] classes = ann.classes();
|
||||
if (classes.length > 0) {
|
||||
List<ResolvableType> types = new ArrayList<>(classes.length);
|
||||
for (Class<?> eventType : classes) {
|
||||
types.add(ResolvableType.forClass(eventType));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
return types;
|
||||
}
|
||||
else {
|
||||
if (count == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Event parameter is mandatory for event listener method: " + method);
|
||||
}
|
||||
return Collections.singletonList(ResolvableType.forMethodParameter(method, 0));
|
||||
|
||||
if (count == 0) {
|
||||
throw new IllegalStateException(
|
||||
"Event parameter is mandatory for event listener method: " + method);
|
||||
}
|
||||
return Collections.singletonList(ResolvableType.forMethodParameter(method, 0));
|
||||
}
|
||||
|
||||
private int resolveOrder(Method method) {
|
||||
@@ -245,10 +243,9 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
}
|
||||
String condition = getCondition();
|
||||
if (StringUtils.hasText(condition)) {
|
||||
Assert.notNull(this.evaluator, "EventExpressionEvaluator must no be null");
|
||||
EvaluationContext evaluationContext = this.evaluator.createEvaluationContext(
|
||||
event, this.targetClass, this.method, args, this.applicationContext);
|
||||
return this.evaluator.condition(condition, this.methodKey, evaluationContext);
|
||||
Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");
|
||||
return this.evaluator.condition(
|
||||
condition, event, this.targetMethod, this.methodKey, args, this.applicationContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -259,12 +256,12 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
@Nullable
|
||||
protected Object doInvoke(Object... args) {
|
||||
Object bean = getTargetBean();
|
||||
ReflectionUtils.makeAccessible(this.bridgedMethod);
|
||||
ReflectionUtils.makeAccessible(this.method);
|
||||
try {
|
||||
return this.bridgedMethod.invoke(bean, args);
|
||||
return this.method.invoke(bean, args);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertTargetBean(this.bridgedMethod, bean, args);
|
||||
assertTargetBean(this.method, bean, args);
|
||||
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
@@ -311,7 +308,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
StringBuilder sb = new StringBuilder(message).append("\n");
|
||||
sb.append("HandlerMethod details: \n");
|
||||
sb.append("Bean [").append(bean.getClass().getName()).append("]\n");
|
||||
sb.append("Method [").append(this.bridgedMethod.toGenericString()).append("]\n");
|
||||
sb.append("Method [").append(this.method.toGenericString()).append("]\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
+6
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,14 +20,12 @@ import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.expression.CachedExpressionEvaluator;
|
||||
import org.springframework.context.expression.MethodBasedEvaluationContext;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -43,42 +41,22 @@ class EventExpressionEvaluator extends CachedExpressionEvaluator {
|
||||
|
||||
private final Map<ExpressionKey, Expression> conditionCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
private final Map<AnnotatedElementKey, Method> targetMethodCache = new ConcurrentHashMap<>(64);
|
||||
|
||||
|
||||
/**
|
||||
* Create the suitable {@link EvaluationContext} for the specified event handling
|
||||
* on the specified method.
|
||||
* Specify if the condition defined by the specified expression matches.
|
||||
*/
|
||||
public EvaluationContext createEvaluationContext(ApplicationEvent event, Class<?> targetClass,
|
||||
Method method, Object[] args, @Nullable BeanFactory beanFactory) {
|
||||
public boolean condition(String conditionExpression, ApplicationEvent event, Method targetMethod,
|
||||
AnnotatedElementKey methodKey, Object[] args, @Nullable BeanFactory beanFactory) {
|
||||
|
||||
Method targetMethod = getTargetMethod(targetClass, method);
|
||||
EventExpressionRootObject root = new EventExpressionRootObject(event, args);
|
||||
MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(
|
||||
root, targetMethod, args, getParameterNameDiscoverer());
|
||||
if (beanFactory != null) {
|
||||
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
|
||||
}
|
||||
return evaluationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if the condition defined by the specified expression matches.
|
||||
*/
|
||||
public boolean condition(String conditionExpression, AnnotatedElementKey elementKey, EvaluationContext evalContext) {
|
||||
return (Boolean.TRUE.equals(getExpression(this.conditionCache, elementKey, conditionExpression).getValue(
|
||||
evalContext, Boolean.class)));
|
||||
}
|
||||
|
||||
private Method getTargetMethod(Class<?> targetClass, Method method) {
|
||||
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
|
||||
Method targetMethod = this.targetMethodCache.get(methodKey);
|
||||
if (targetMethod == null) {
|
||||
targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
|
||||
this.targetMethodCache.put(methodKey, targetMethod);
|
||||
}
|
||||
return targetMethod;
|
||||
return (Boolean.TRUE.equals(getExpression(this.conditionCache, methodKey, conditionExpression).getValue(
|
||||
evaluationContext, Boolean.class)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-8
@@ -80,7 +80,8 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
* This allows for very efficient hash lookups, significantly faster
|
||||
* than the ResourceBundle class's own cache.
|
||||
*/
|
||||
private final Map<String, Map<Locale, ResourceBundle>> cachedResourceBundles = new ConcurrentHashMap<>();
|
||||
private final Map<String, Map<Locale, ResourceBundle>> cachedResourceBundles =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache to hold already generated MessageFormats.
|
||||
@@ -90,7 +91,11 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
* very efficient hash lookups without concatenated keys.
|
||||
* @see #getMessageFormat
|
||||
*/
|
||||
private final Map<ResourceBundle, Map<String, Map<Locale, MessageFormat>>> cachedBundleMessageFormats = new ConcurrentHashMap<>();
|
||||
private final Map<ResourceBundle, Map<String, Map<Locale, MessageFormat>>> cachedBundleMessageFormats =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private volatile MessageSourceControl control = new MessageSourceControl();
|
||||
|
||||
|
||||
/**
|
||||
@@ -220,7 +225,24 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
|
||||
ClassLoader classLoader = getBundleClassLoader();
|
||||
Assert.state(classLoader != null, "No bundle ClassLoader set");
|
||||
return ResourceBundle.getBundle(basename, locale, classLoader, new MessageSourceControl());
|
||||
|
||||
MessageSourceControl control = this.control;
|
||||
if (control != null) {
|
||||
try {
|
||||
return ResourceBundle.getBundle(basename, locale, classLoader, control);
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
// Probably in a Jigsaw environment on JDK 9+
|
||||
this.control = null;
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("ResourceBundle.Control not supported in current system environment: " +
|
||||
ex.getMessage() + " - falling back to plain ResourceBundle.getBundle retrieval.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: plain getBundle lookup without Control handle
|
||||
return ResourceBundle.getBundle(basename, locale, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,7 +288,8 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
if (msg != null) {
|
||||
if (codeMap == null) {
|
||||
codeMap = new ConcurrentHashMap<>();
|
||||
Map<String, Map<Locale, MessageFormat>> existing = this.cachedBundleMessageFormats.putIfAbsent(bundle, codeMap);
|
||||
Map<String, Map<Locale, MessageFormat>> existing =
|
||||
this.cachedBundleMessageFormats.putIfAbsent(bundle, codeMap);
|
||||
if (existing != null) {
|
||||
codeMap = existing;
|
||||
}
|
||||
@@ -341,9 +364,9 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
final String resourceName = toResourceName(bundleName, "properties");
|
||||
final ClassLoader classLoader = loader;
|
||||
final boolean reloadFlag = reload;
|
||||
InputStream stream;
|
||||
InputStream inputStream;
|
||||
try {
|
||||
stream = AccessController.doPrivileged((PrivilegedExceptionAction<InputStream>) () -> {
|
||||
inputStream = AccessController.doPrivileged((PrivilegedExceptionAction<InputStream>) () -> {
|
||||
InputStream is = null;
|
||||
if (reloadFlag) {
|
||||
URL url = classLoader.getResource(resourceName);
|
||||
@@ -364,12 +387,12 @@ public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSou
|
||||
catch (PrivilegedActionException ex) {
|
||||
throw (IOException) ex.getException();
|
||||
}
|
||||
if (stream != null) {
|
||||
if (inputStream != null) {
|
||||
String encoding = getDefaultEncoding();
|
||||
if (encoding == null) {
|
||||
encoding = "ISO-8859-1";
|
||||
}
|
||||
try (InputStreamReader bundleReader = new InputStreamReader(stream, encoding)) {
|
||||
try (InputStreamReader bundleReader = new InputStreamReader(inputStream, encoding)) {
|
||||
return loadBundle(bundleReader);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -187,6 +187,12 @@ import org.springframework.scheduling.config.ScheduledTaskRegistrar;
|
||||
* but one demonstration how the code-based approach allows for maximum configurability
|
||||
* through direct access to actual componentry.<p>
|
||||
*
|
||||
* <b>Note: {@code @EnableScheduling} applies to its local application context only,
|
||||
* allowing for selective scheduling of beans at different levels.</b> Please redeclare
|
||||
* {@code @EnableScheduling} in each individual context, e.g. the common root web
|
||||
* application context and any separate {@code DispatcherServlet} application contexts,
|
||||
* if you need to apply its behavior at multiple levels.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
||||
+9
-76
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,23 +18,6 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
||||
/**
|
||||
* Definitions of testing types for use in within this package.
|
||||
* Wherever possible, test types should be defined local to the java
|
||||
* file that makes use of them. In some cases however, a test type may
|
||||
* need to be shared across tests. Such types reside here, with the
|
||||
* intention of reducing the surface area of java files within this
|
||||
* package. This allows developers to think about tests first, and deal
|
||||
* with these second class testing artifacts on an as-needed basis.
|
||||
*
|
||||
* Types here should be defined as package-private top level classes in
|
||||
* order to avoid needing to fully qualify, e.g.: _TestTypes$Foo.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
final class _TestTypes { }
|
||||
|
||||
|
||||
/**
|
||||
* Aspect used as part of before advice binding tests and
|
||||
* serves as base class for a number of more specialized test aspects.
|
||||
@@ -44,13 +27,16 @@ final class _TestTypes { }
|
||||
*/
|
||||
class AdviceBindingTestAspect {
|
||||
|
||||
protected AdviceBindingCollaborator collaborator = null;
|
||||
protected AdviceBindingCollaborator collaborator;
|
||||
|
||||
|
||||
public void setCollaborator(AdviceBindingCollaborator aCollaborator) {
|
||||
this.collaborator = aCollaborator;
|
||||
}
|
||||
|
||||
|
||||
// "advice" methods
|
||||
|
||||
public void oneIntArg(int age) {
|
||||
this.collaborator.oneIntArg(age);
|
||||
}
|
||||
@@ -79,67 +65,14 @@ class AdviceBindingTestAspect {
|
||||
public interface AdviceBindingCollaborator {
|
||||
|
||||
void oneIntArg(int x);
|
||||
|
||||
void oneObjectArg(Object o);
|
||||
|
||||
void oneIntAndOneObject(int x, Object o);
|
||||
|
||||
void needsJoinPoint(String s);
|
||||
|
||||
void needsJoinPointStaticPart(String s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
interface ICounter {
|
||||
|
||||
void increment();
|
||||
|
||||
void decrement();
|
||||
|
||||
int getCount();
|
||||
|
||||
void setCount(int counter);
|
||||
|
||||
void reset();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple counter for use in simple tests (for example, how many times an advice was executed)
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
final class Counter implements ICounter {
|
||||
|
||||
private int count;
|
||||
|
||||
public Counter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment() {
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrement() {
|
||||
count--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCount(int counter) {
|
||||
this.count = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.count = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj;
|
||||
|
||||
/**
|
||||
* A simple counter for use in simple tests (for example, how many times an advice was executed)
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
final class Counter implements ICounter {
|
||||
|
||||
private int count;
|
||||
|
||||
public Counter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment() {
|
||||
count++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrement() {
|
||||
count--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCount(int counter) {
|
||||
this.count = counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj;
|
||||
|
||||
/**
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
interface ICounter {
|
||||
|
||||
void increment();
|
||||
|
||||
void decrement();
|
||||
|
||||
int getCount();
|
||||
|
||||
void setCount(int counter);
|
||||
|
||||
void reset();
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj.autoproxy;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
interface AnnotatedTestBean {
|
||||
|
||||
String doThis();
|
||||
|
||||
String doThat();
|
||||
|
||||
String doTheOther();
|
||||
|
||||
String[] doArray();
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj.autoproxy;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
class AnnotatedTestBeanImpl implements AnnotatedTestBean {
|
||||
|
||||
@Override
|
||||
@TestAnnotation("this value")
|
||||
public String doThis() {
|
||||
return "doThis";
|
||||
}
|
||||
|
||||
@Override
|
||||
@TestAnnotation("that value")
|
||||
public String doThat() {
|
||||
return "doThat";
|
||||
}
|
||||
|
||||
@Override
|
||||
@TestAnnotation("array value")
|
||||
public String[] doArray() {
|
||||
return new String[] {"doThis", "doThat"};
|
||||
}
|
||||
|
||||
// not annotated
|
||||
@Override
|
||||
public String doTheOther() {
|
||||
return "doTheOther";
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj.autoproxy;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
class AnnotationBindingTestAspect {
|
||||
|
||||
public String doWithAnnotation(ProceedingJoinPoint pjp, TestAnnotation testAnnotation) throws Throwable {
|
||||
return testAnnotation.value();
|
||||
}
|
||||
|
||||
}
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,14 +33,16 @@ public class AnnotationPointcutTests {
|
||||
|
||||
private AnnotatedTestBean testBean;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void setup() {
|
||||
ClassPathXmlApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
|
||||
testBean = (AnnotatedTestBean) ctx.getBean("testBean");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAnnotationBindingInAroundAdvice() {
|
||||
assertEquals("this value", testBean.doThis());
|
||||
@@ -61,4 +63,3 @@ class TestMethodInterceptor implements MethodInterceptor {
|
||||
return "this value";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+31
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -185,7 +185,7 @@ public class AspectJAutoProxyCreatorTests {
|
||||
// Create a child factory with a bean that should be woven
|
||||
RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);
|
||||
bd.getPropertyValues().addPropertyValue(new PropertyValue("name", "Adrian"))
|
||||
.addPropertyValue(new PropertyValue("age", new Integer(34)));
|
||||
.addPropertyValue(new PropertyValue("age", 34));
|
||||
childAc.registerBeanDefinition("adrian2", bd);
|
||||
// Register the advisor auto proxy creator with subclass
|
||||
childAc.registerBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class.getName(), new RootBeanDefinition(
|
||||
@@ -270,25 +270,45 @@ public class AspectJAutoProxyCreatorTests {
|
||||
assertEquals(3, adrian1.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoAdviceAspect() {
|
||||
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspect.xml");
|
||||
|
||||
ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
|
||||
testAgeAspect(adrian1, 0, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoAdviceAspectSingleton() {
|
||||
doTestTwoAdviceAspectWith("twoAdviceAspect.xml");
|
||||
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspectSingleton.xml");
|
||||
|
||||
ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
|
||||
testAgeAspect(adrian1, 0, 1);
|
||||
ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
|
||||
assertNotSame(adrian1, adrian2);
|
||||
testAgeAspect(adrian2, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoAdviceAspectPrototype() {
|
||||
doTestTwoAdviceAspectWith("twoAdviceAspectPrototype.xml");
|
||||
}
|
||||
ClassPathXmlApplicationContext bf = newContext("twoAdviceAspectPrototype.xml");
|
||||
|
||||
private void doTestTwoAdviceAspectWith(String location) {
|
||||
ClassPathXmlApplicationContext bf = newContext(location);
|
||||
|
||||
boolean aspectSingleton = bf.isSingleton("aspect");
|
||||
ITestBean adrian1 = (ITestBean) bf.getBean("adrian");
|
||||
testPrototype(adrian1, 0);
|
||||
testAgeAspect(adrian1, 0, 1);
|
||||
ITestBean adrian2 = (ITestBean) bf.getBean("adrian");
|
||||
assertNotSame(adrian1, adrian2);
|
||||
testPrototype(adrian2, aspectSingleton ? 2 : 0);
|
||||
testAgeAspect(adrian2, 0, 1);
|
||||
}
|
||||
|
||||
private void testAgeAspect(ITestBean adrian, int start, int increment) {
|
||||
assertTrue(AopUtils.isAopProxy(adrian));
|
||||
adrian.setName("");
|
||||
assertEquals(start, adrian.age());
|
||||
int newAge = 32;
|
||||
adrian.setAge(newAge);
|
||||
assertEquals(start + increment, adrian.age());
|
||||
adrian.setAge(0);
|
||||
assertEquals(start + increment * 2, adrian.age());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -312,18 +332,6 @@ public class AspectJAutoProxyCreatorTests {
|
||||
assertEquals(68, adrian.getAge());
|
||||
}
|
||||
|
||||
private void testPrototype(ITestBean adrian1, int start) {
|
||||
assertTrue(AopUtils.isAopProxy(adrian1));
|
||||
//TwoAdviceAspect twoAdviceAspect = (TwoAdviceAspect) bf.getBean(TwoAdviceAspect.class.getName());
|
||||
adrian1.setName("");
|
||||
assertEquals(start++, adrian1.getAge());
|
||||
int newAge = 32;
|
||||
adrian1.setAge(newAge);
|
||||
assertEquals(start++, adrian1.getAge());
|
||||
adrian1.setAge(0);
|
||||
assertEquals(start++, adrian1.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForceProxyTargetClass() {
|
||||
ClassPathXmlApplicationContext bf = newContext("aspectsWithCGLIB.xml");
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.aspectj.autoproxy;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TestAnnotation {
|
||||
String value() ;
|
||||
}
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.aop.aspectj.autoproxy;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
|
||||
/**
|
||||
* Definitions of testing types for use in within this package.
|
||||
* Wherever possible, test types should be defined local to the java
|
||||
* file that makes use of them. In some cases however, a test type may
|
||||
* need to be shared across tests. Such types reside here, with the
|
||||
* intention of reducing the surface area of java files within this
|
||||
* package. This allows developers to think about tests first, and deal
|
||||
* with these second class testing artifacts on an as-needed basis.
|
||||
*
|
||||
* Types here should be defined as package-private top level classes in
|
||||
* order to avoid needing to fully qualify, e.g.: _TestTypes$Foo.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
final class _TestTypes { }
|
||||
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
interface AnnotatedTestBean {
|
||||
|
||||
String doThis();
|
||||
|
||||
String doThat();
|
||||
|
||||
String doTheOther();
|
||||
|
||||
String[] doArray();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TestAnnotation {
|
||||
String value() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @since 2.0
|
||||
*/
|
||||
class AnnotatedTestBeanImpl implements AnnotatedTestBean {
|
||||
|
||||
@Override
|
||||
@TestAnnotation("this value")
|
||||
public String doThis() {
|
||||
return "doThis";
|
||||
}
|
||||
|
||||
@Override
|
||||
@TestAnnotation("that value")
|
||||
public String doThat() {
|
||||
return "doThat";
|
||||
}
|
||||
|
||||
@Override
|
||||
@TestAnnotation("array value")
|
||||
public String[] doArray() {
|
||||
return new String[] {"doThis", "doThat"};
|
||||
}
|
||||
|
||||
// not annotated
|
||||
@Override
|
||||
public String doTheOther() {
|
||||
return "doTheOther";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
*/
|
||||
class AnnotationBindingTestAspect {
|
||||
|
||||
public String doWithAnnotation(ProceedingJoinPoint pjp, TestAnnotation testAnnotation) throws Throwable {
|
||||
return testAnnotation.value();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -212,7 +212,7 @@ public abstract class AbstractAopProxyTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializationSerializableTargetAndAdvice() throws Throwable {
|
||||
public void testSerializableTargetAndAdvice() throws Throwable {
|
||||
SerializablePerson personTarget = new SerializablePerson();
|
||||
personTarget.setName("jim");
|
||||
personTarget.setAge(26);
|
||||
@@ -435,7 +435,7 @@ public abstract class AbstractAopProxyTests {
|
||||
TestBean raw = new OwnSpouse();
|
||||
|
||||
ProxyCreatorSupport pc = new ProxyCreatorSupport();
|
||||
pc.setInterfaces(new Class<?>[] {ITestBean.class});
|
||||
pc.setInterfaces(ITestBean.class);
|
||||
pc.setTarget(raw);
|
||||
|
||||
ITestBean tb = (ITestBean) createProxy(pc);
|
||||
@@ -457,7 +457,7 @@ public abstract class AbstractAopProxyTests {
|
||||
pc.addAdvice(mi);
|
||||
|
||||
// We don't care about the object
|
||||
mockTargetSource.setTarget(new Object());
|
||||
mockTargetSource.setTarget(new TestBean());
|
||||
pc.setTargetSource(mockTargetSource);
|
||||
AopProxy aop = createAopProxy(pc);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -174,7 +174,7 @@ public class CglibProxyTests extends AbstractAopProxyTests implements Serializab
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnadvisedProxyCreationWithCallDuringConstructor() throws Exception {
|
||||
public void testUnadvisedProxyCreationWithCallDuringConstructor() {
|
||||
CglibTestBean target = new CglibTestBean();
|
||||
target.setName("Rob Harrop");
|
||||
|
||||
@@ -370,7 +370,7 @@ public class CglibProxyTests extends AbstractAopProxyTests implements Serializab
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyProtectedMethod() throws Exception {
|
||||
public void testProxyProtectedMethod() {
|
||||
CountingBeforeAdvice advice = new CountingBeforeAdvice();
|
||||
ProxyFactory proxyFactory = new ProxyFactory(new MyBean());
|
||||
proxyFactory.addAdvice(advice);
|
||||
@@ -382,14 +382,14 @@ public class CglibProxyTests extends AbstractAopProxyTests implements Serializab
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyTargetClassInCaseOfNoInterfaces() throws Exception {
|
||||
public void testProxyTargetClassInCaseOfNoInterfaces() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(new MyBean());
|
||||
MyBean proxy = (MyBean) proxyFactory.getProxy();
|
||||
assertEquals(4, proxy.add(1, 3));
|
||||
}
|
||||
|
||||
@Test // SPR-13328
|
||||
public void testVarargsWithEnumArray() throws Exception {
|
||||
public void testVarargsWithEnumArray() {
|
||||
ProxyFactory proxyFactory = new ProxyFactory(new MyBean());
|
||||
MyBean proxy = (MyBean) proxyFactory.getProxy();
|
||||
assertTrue(proxy.doWithVarargs(MyEnum.A, MyOtherEnum.C));
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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;
|
||||
|
||||
public class Echo implements IEcho {
|
||||
|
||||
private int a;
|
||||
|
||||
@Override
|
||||
public int echoException(int i, Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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;
|
||||
|
||||
public interface IEcho {
|
||||
|
||||
int echoException(int i, Throwable t) throws Throwable;
|
||||
|
||||
int getA();
|
||||
|
||||
void setA(int a);
|
||||
|
||||
}
|
||||
+7
-7
@@ -260,22 +260,22 @@ public class ProxyFactoryBeanTests {
|
||||
|
||||
// Check it works without AOP
|
||||
SideEffectBean raw = (SideEffectBean) bf.getBean("prototypeTarget");
|
||||
assertEquals(INITIAL_COUNT, raw.getCount() );
|
||||
assertEquals(INITIAL_COUNT, raw.getCount());
|
||||
raw.doWork();
|
||||
assertEquals(INITIAL_COUNT+1, raw.getCount() );
|
||||
assertEquals(INITIAL_COUNT+1, raw.getCount());
|
||||
raw = (SideEffectBean) bf.getBean("prototypeTarget");
|
||||
assertEquals(INITIAL_COUNT, raw.getCount() );
|
||||
assertEquals(INITIAL_COUNT, raw.getCount());
|
||||
|
||||
// Now try with advised instances
|
||||
SideEffectBean prototype2FirstInstance = (SideEffectBean) bf.getBean(beanName);
|
||||
assertEquals(INITIAL_COUNT, prototype2FirstInstance.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype2FirstInstance.getCount());
|
||||
prototype2FirstInstance.doWork();
|
||||
assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount());
|
||||
|
||||
SideEffectBean prototype2SecondInstance = (SideEffectBean) bf.getBean(beanName);
|
||||
assertFalse("Prototypes are not ==", prototype2FirstInstance == prototype2SecondInstance);
|
||||
assertEquals(INITIAL_COUNT, prototype2SecondInstance.getCount() );
|
||||
assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount() );
|
||||
assertEquals(INITIAL_COUNT, prototype2SecondInstance.getCount());
|
||||
assertEquals(INITIAL_COUNT + 1, prototype2FirstInstance.getCount());
|
||||
|
||||
return prototype2FirstInstance;
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package org.springframework.aop.framework;
|
||||
|
||||
/**
|
||||
* Definitions of testing types for use in within this package.
|
||||
* Wherever possible, test types should be defined local to the java
|
||||
* file that makes use of them. In some cases however, a test type may
|
||||
* need to be shared across tests. Such types reside here, with the
|
||||
* intention of reducing the surface area of java files within this
|
||||
* package. This allows developers to think about tests first, and deal
|
||||
* with these second class testing artifacts on an as-needed basis.
|
||||
*
|
||||
* Types here should be defined as package-private top level classes in
|
||||
* order to avoid needing to fully qualify, e.g.: _TestTypes$Foo.
|
||||
*
|
||||
* @author Chris Beams
|
||||
*/
|
||||
final class _TestTypes { }
|
||||
|
||||
|
||||
interface IEcho {
|
||||
int echoException(int i, Throwable t) throws Throwable;
|
||||
int getA();
|
||||
void setA(int a);
|
||||
}
|
||||
|
||||
|
||||
class Echo implements IEcho {
|
||||
private int a;
|
||||
|
||||
@Override
|
||||
public int echoException(int i, Throwable t) throws Throwable {
|
||||
if (t != null)
|
||||
throw t;
|
||||
return i;
|
||||
}
|
||||
@Override
|
||||
public void setA(int a) {
|
||||
this.a = a;
|
||||
}
|
||||
@Override
|
||||
public int getA() {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,13 +35,13 @@ import static org.junit.Assert.*;
|
||||
public class BeanNameAutoProxyCreatorInitTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testIgnoreAdvisorThatIsCurrentlyCreation() {
|
||||
public void testIgnoreAdvisorThatIsCurrentlyInCreation() {
|
||||
ClassPathXmlApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass());
|
||||
TestBean bean = (TestBean) ctx.getBean("bean");
|
||||
bean.setName("foo");
|
||||
assertEquals("foo", bean.getName());
|
||||
bean.setName(null); // should throw
|
||||
bean.setName(null); // should throw
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ public class CommonsPool2TargetSourceTests {
|
||||
// Just check that it works--we can't make assumptions
|
||||
// about the count
|
||||
pooled.doWork();
|
||||
//assertEquals(INITIAL_COUNT + 1, apartment.getCount() );
|
||||
//assertEquals(INITIAL_COUNT + 1, apartment.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ public abstract class AbstractCacheTests<T extends Cache> {
|
||||
String key = createRandomKey();
|
||||
|
||||
assertNull(cache.get(key));
|
||||
Object value = cache.get(key, () -> returnValue );
|
||||
Object value = cache.get(key, () -> returnValue);
|
||||
assertEquals(returnValue, value);
|
||||
assertEquals(value, cache.get(key).get());
|
||||
}
|
||||
|
||||
Vendored
+17
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,7 +59,7 @@ public class ExpressionEvaluatorTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultipleCachingSource() throws Exception {
|
||||
public void testMultipleCachingSource() {
|
||||
Collection<CacheOperation> ops = getOps("multipleCaching");
|
||||
assertEquals(2, ops.size());
|
||||
Iterator<CacheOperation> it = ops.iterator();
|
||||
@@ -74,19 +74,18 @@ public class ExpressionEvaluatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleCachingEval() throws Exception {
|
||||
public void testMultipleCachingEval() {
|
||||
AnnotatedClass target = new AnnotatedClass();
|
||||
Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class,
|
||||
Object.class);
|
||||
Object[] args = new Object[] { new Object(), new Object() };
|
||||
Method method = ReflectionUtils.findMethod(
|
||||
AnnotatedClass.class, "multipleCaching", Object.class, Object.class);
|
||||
Object[] args = new Object[] {new Object(), new Object()};
|
||||
Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
|
||||
|
||||
EvaluationContext evalCtx = this.eval.createEvaluationContext(caches, method, args,
|
||||
target, target.getClass(), null);
|
||||
target, target.getClass(), method, CacheOperationExpressionEvaluator.NO_RESULT, null);
|
||||
Collection<CacheOperation> ops = getOps("multipleCaching");
|
||||
|
||||
Iterator<CacheOperation> it = ops.iterator();
|
||||
|
||||
AnnotatedElementKey key = new AnnotatedElementKey(method, AnnotatedClass.class);
|
||||
|
||||
Object keyA = this.eval.key(it.next().getKey(), key, evalCtx);
|
||||
@@ -97,28 +96,28 @@ public class ExpressionEvaluatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withReturnValue() throws Exception {
|
||||
public void withReturnValue() {
|
||||
EvaluationContext context = createEvaluationContext("theResult");
|
||||
Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
|
||||
assertThat(value, equalTo("theResult"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withNullReturn() throws Exception {
|
||||
public void withNullReturn() {
|
||||
EvaluationContext context = createEvaluationContext(null);
|
||||
Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
|
||||
assertThat(value, nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withoutReturnValue() throws Exception {
|
||||
public void withoutReturnValue() {
|
||||
EvaluationContext context = createEvaluationContext(CacheOperationExpressionEvaluator.NO_RESULT);
|
||||
Object value = new SpelExpressionParser().parseExpression("#result").getValue(context);
|
||||
assertThat(value, nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unavailableReturnValue() throws Exception {
|
||||
public void unavailableReturnValue() {
|
||||
EvaluationContext context = createEvaluationContext(CacheOperationExpressionEvaluator.RESULT_UNAVAILABLE);
|
||||
try {
|
||||
new SpelExpressionParser().parseExpression("#result").getValue(context);
|
||||
@@ -130,7 +129,7 @@ public class ExpressionEvaluatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveBeanReference() throws Exception {
|
||||
public void resolveBeanReference() {
|
||||
StaticApplicationContext applicationContext = new StaticApplicationContext();
|
||||
BeanDefinition beanDefinition = new RootBeanDefinition(String.class);
|
||||
applicationContext.registerBeanDefinition("myBean", beanDefinition);
|
||||
@@ -147,11 +146,12 @@ public class ExpressionEvaluatorTests {
|
||||
|
||||
private EvaluationContext createEvaluationContext(Object result, BeanFactory beanFactory) {
|
||||
AnnotatedClass target = new AnnotatedClass();
|
||||
Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class,
|
||||
Object.class);
|
||||
Object[] args = new Object[] { new Object(), new Object() };
|
||||
Method method = ReflectionUtils.findMethod(
|
||||
AnnotatedClass.class, "multipleCaching", Object.class, Object.class);
|
||||
Object[] args = new Object[] {new Object(), new Object()};
|
||||
Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
|
||||
return this.eval.createEvaluationContext(caches, method, args, target, target.getClass(), result, beanFactory);
|
||||
return this.eval.createEvaluationContext(
|
||||
caches, method, args, target, target.getClass(), method, result, beanFactory);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+52
-1
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.annotation.Lookup;
|
||||
@@ -351,7 +352,7 @@ public class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test // SPR-15384
|
||||
public void nestedConfigurationClassesProcessedInCorrectOrder() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedNestedClasses.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
@@ -363,6 +364,19 @@ public class ConfigurationClassPostProcessorTests {
|
||||
assertSame(foo, bar.foo);
|
||||
}
|
||||
|
||||
@Test // SPR-16734
|
||||
public void innerConfigurationClassesProcessedInCorrectOrder() {
|
||||
beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedInnerClasses.class));
|
||||
ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor();
|
||||
pp.postProcessBeanFactory(beanFactory);
|
||||
beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
|
||||
|
||||
Foo foo = beanFactory.getBean(Foo.class);
|
||||
assertTrue(foo instanceof ExtendedFoo);
|
||||
Bar bar = beanFactory.getBean(Bar.class);
|
||||
assertSame(foo, bar.foo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scopedProxyTargetMarkedAsNonAutowireCandidate() {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
@@ -890,6 +904,43 @@ public class ConfigurationClassPostProcessorTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ConfigWithOrderedInnerClasses {
|
||||
|
||||
@Configuration
|
||||
@Order(1)
|
||||
class SingletonBeanConfig {
|
||||
|
||||
public SingletonBeanConfig(ConfigWithOrderedInnerClasses other) {
|
||||
}
|
||||
|
||||
public @Bean Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
public @Bean Bar bar() {
|
||||
return new Bar(foo());
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(2)
|
||||
class OverridingSingletonBeanConfig {
|
||||
|
||||
public OverridingSingletonBeanConfig(ObjectProvider<SingletonBeanConfig> other) {
|
||||
other.getObject();
|
||||
}
|
||||
|
||||
public @Bean ExtendedFoo foo() {
|
||||
return new ExtendedFoo();
|
||||
}
|
||||
|
||||
public @Bean Bar bar() {
|
||||
return new Bar(foo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class Foo {
|
||||
}
|
||||
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.context.annotation.configuration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* @author Andy Wilkinson
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class DuplicatePostProcessingTests {
|
||||
|
||||
@Test
|
||||
public void testWithFactoryBeanAndEventListener() {
|
||||
new AnnotationConfigApplicationContext(Config.class).getBean(ExampleBean.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public ExampleFactoryBean exampleFactory() {
|
||||
return new ExampleFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public static ExampleBeanPostProcessor exampleBeanPostProcessor() {
|
||||
return new ExampleBeanPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ExampleApplicationEventListener exampleApplicationEventListener() {
|
||||
return new ExampleApplicationEventListener();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ExampleFactoryBean implements FactoryBean<ExampleBean> {
|
||||
|
||||
private final ExampleBean exampleBean = new ExampleBean();
|
||||
|
||||
@Override
|
||||
public ExampleBean getObject() {
|
||||
return this.exampleBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return ExampleBean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ExampleBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof ExampleBean) {
|
||||
this.applicationContext.publishEvent(new ExampleApplicationEvent(this));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class ExampleApplicationEvent extends ApplicationEvent {
|
||||
|
||||
public ExampleApplicationEvent(Object source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ExampleApplicationEventListener implements ApplicationListener<ExampleApplicationEvent>, BeanFactoryAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ExampleApplicationEvent event) {
|
||||
this.beanFactory.getBean(ExampleBean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ExampleBean {
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.context.annotation.spr16756;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ScannedComponent {
|
||||
|
||||
@Autowired
|
||||
private State state;
|
||||
|
||||
public String iDoAnything() {
|
||||
return state.anyMethod();
|
||||
}
|
||||
|
||||
|
||||
public interface State {
|
||||
|
||||
String anyMethod();
|
||||
}
|
||||
|
||||
|
||||
@Component
|
||||
@Scope(proxyMode = ScopedProxyMode.INTERFACES, value = "prototype")
|
||||
public static class StateImpl implements State {
|
||||
|
||||
public String anyMethod() {
|
||||
return "anyMethod called";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.context.annotation.spr16756;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@ComponentScan
|
||||
public class ScanningConfiguration {
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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.context.annotation.spr16756;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class Spr16756Tests {
|
||||
|
||||
@Test
|
||||
public void shouldNotFailOnNestedScopedComponent() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(ScanningConfiguration.class);
|
||||
context.refresh();
|
||||
context.getBean(ScannedComponent.class);
|
||||
context.getBean(ScannedComponent.State.class);
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -89,7 +89,7 @@ public class LocalSlsbInvokerInterceptorTests {
|
||||
|
||||
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class } );
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class });
|
||||
pf.addAdvice(si);
|
||||
BusinessMethods target = (BusinessMethods) pf.getProxy();
|
||||
|
||||
@@ -110,7 +110,7 @@ public class LocalSlsbInvokerInterceptorTests {
|
||||
|
||||
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class } );
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { BusinessMethods.class });
|
||||
pf.addAdvice(si);
|
||||
BusinessMethods target = (BusinessMethods) pf.getProxy();
|
||||
|
||||
@@ -129,7 +129,7 @@ public class LocalSlsbInvokerInterceptorTests {
|
||||
|
||||
LocalSlsbInvokerInterceptor si = configuredInterceptor(mockContext, jndiName);
|
||||
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { LocalInterfaceWithBusinessMethods.class } );
|
||||
ProxyFactory pf = new ProxyFactory(new Class<?>[] { LocalInterfaceWithBusinessMethods.class });
|
||||
pf.addAdvice(si);
|
||||
LocalInterfaceWithBusinessMethods target = (LocalInterfaceWithBusinessMethods) pf.getProxy();
|
||||
|
||||
|
||||
+14
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,7 +60,7 @@ import static org.junit.Assert.*;
|
||||
public class ValidatorFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testSimpleValidation() throws Exception {
|
||||
public void testSimpleValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -86,7 +86,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithCustomProvider() throws Exception {
|
||||
public void testSimpleValidationWithCustomProvider() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.setProviderClass(HibernateValidator.class);
|
||||
validator.afterPropertiesSet();
|
||||
@@ -113,9 +113,10 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleValidationWithClassLevel() throws Exception {
|
||||
public void testSimpleValidationWithClassLevel() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
@@ -128,7 +129,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationFieldType() throws Exception {
|
||||
public void testSpringValidationFieldType() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -143,7 +144,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidation() throws Exception {
|
||||
public void testSpringValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -171,7 +172,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithClassLevel() throws Exception {
|
||||
public void testSpringValidationWithClassLevel() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -189,7 +190,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithAutowiredValidator() throws Exception {
|
||||
public void testSpringValidationWithAutowiredValidator() {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
LocalValidatorFactoryBean.class);
|
||||
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
|
||||
@@ -210,7 +211,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInListElement() throws Exception {
|
||||
public void testSpringValidationWithErrorInListElement() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -228,7 +229,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInSetElement() throws Exception {
|
||||
public void testSpringValidationWithErrorInSetElement() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -246,7 +247,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInnerBeanValidation() throws Exception {
|
||||
public void testInnerBeanValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -258,7 +259,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidationWithOptionalField() throws Exception {
|
||||
public void testValidationWithOptionalField() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
@@ -270,7 +271,7 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListValidation() throws Exception {
|
||||
public void testListValidation() {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright 2002-2018 the original author 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 test.aspect;
|
||||
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,15 +23,17 @@ import org.aspectj.lang.annotation.Before;
|
||||
|
||||
@Aspect
|
||||
public class TwoAdviceAspect {
|
||||
|
||||
private int totalCalls;
|
||||
|
||||
@Around("execution(* getAge())")
|
||||
@Around("execution(* org.springframework.tests.sample.beans.ITestBean.age())")
|
||||
public int returnCallCount(ProceedingJoinPoint pjp) throws Exception {
|
||||
return totalCalls;
|
||||
}
|
||||
|
||||
@Before("execution(* setAge(int)) && args(newAge)")
|
||||
@Before("execution(* org.springframework.tests.sample.beans.ITestBean.setAge(int)) && args(newAge)")
|
||||
public void countSet(int newAge) throws Exception {
|
||||
++totalCalls;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-3
@@ -7,9 +7,13 @@
|
||||
|
||||
<bean id="aspect" class="test.aspect.TwoAdviceAspect"/>
|
||||
|
||||
<bean id="adrian" class="org.springframework.tests.sample.beans.TestBean" scope="prototype">
|
||||
<property name="name" value="adrian"/>
|
||||
<property name="age" value="34"/>
|
||||
<bean id="adrian" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="target">
|
||||
<bean class="org.springframework.tests.sample.beans.TestBean">
|
||||
<property name="name" value="adrian"/>
|
||||
<property name="age" value="34"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
+1
-2
@@ -5,8 +5,7 @@
|
||||
|
||||
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
|
||||
|
||||
<bean id="aspect" class="test.aspect.TwoAdviceAspect"
|
||||
scope="prototype"/>
|
||||
<bean id="aspect" class="test.aspect.TwoAdviceAspect" scope="prototype"/>
|
||||
|
||||
<bean id="adrian" class="org.springframework.tests.sample.beans.TestBean" scope="prototype">
|
||||
<property name="name" value="adrian"/>
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
|
||||
|
||||
<beans>
|
||||
|
||||
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
|
||||
|
||||
<bean id="aspect" class="test.aspect.TwoAdviceAspect"/>
|
||||
|
||||
<bean id="adrian" class="org.springframework.tests.sample.beans.TestBean" scope="prototype">
|
||||
<property name="name" value="adrian"/>
|
||||
<property name="age" value="34"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -1,16 +1,10 @@
|
||||
description = "Spring Core"
|
||||
|
||||
apply plugin: "io.spring.dependency-management"
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "io.projectreactor:reactor-bom:${reactorVersion}"
|
||||
mavenBom "io.netty:netty-bom:${nettyVersion}"
|
||||
}
|
||||
resolutionStrategy {
|
||||
cacheChangingModulesFor 0, 'seconds'
|
||||
}
|
||||
applyMavenExclusions = false
|
||||
}
|
||||
|
||||
// As of Spring 4.0.3, spring-core includes asm 5.x and repackages cglib 3.2, inlining
|
||||
@@ -40,7 +34,7 @@ task cglibRepackJar(type: Jar) { repackJar ->
|
||||
}
|
||||
// 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")
|
||||
@@ -86,8 +80,9 @@ dependencies {
|
||||
optional("io.reactivex.rxjava2:rxjava:${rxjava2Version}")
|
||||
optional("io.netty:netty-buffer")
|
||||
testCompile("io.projectreactor:reactor-test")
|
||||
testCompile("javax.xml.bind:jaxb-api:2.3.0")
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||
testCompile("org.xmlunit:xmlunit-matchers:2.5.1")
|
||||
testCompile("javax.xml.bind:jaxb-api:2.3.0")
|
||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.0.3") {
|
||||
exclude group: "stax", module: "stax-api"
|
||||
}
|
||||
|
||||
@@ -419,7 +419,18 @@ public class MethodParameter {
|
||||
paramType = (method != null ? method.getGenericReturnType() : void.class);
|
||||
}
|
||||
else {
|
||||
paramType = this.executable.getGenericParameterTypes()[this.parameterIndex];
|
||||
Type[] genericParameterTypes = this.executable.getGenericParameterTypes();
|
||||
int index = this.parameterIndex;
|
||||
if (this.executable instanceof Constructor &&
|
||||
ClassUtils.isInnerClass(this.executable.getDeclaringClass()) &&
|
||||
genericParameterTypes.length == this.executable.getParameterCount() - 1) {
|
||||
// Bug in javac: type array excludes enclosing instance parameter
|
||||
// for inner classes with at least one generic constructor parameter,
|
||||
// so access it with the actual parameter index lowered by 1
|
||||
index = this.parameterIndex - 1;
|
||||
}
|
||||
paramType = (index >= 0 && index < genericParameterTypes.length ?
|
||||
genericParameterTypes[index] : getParameterType());
|
||||
}
|
||||
this.genericParameterType = paramType;
|
||||
}
|
||||
@@ -525,12 +536,8 @@ public class MethodParameter {
|
||||
// for inner classes, so access it with the actual parameter index lowered by 1
|
||||
index = this.parameterIndex - 1;
|
||||
}
|
||||
if (index >= 0 && index < annotationArray.length) {
|
||||
paramAnns = adaptAnnotationArray(annotationArray[index]);
|
||||
}
|
||||
else {
|
||||
paramAnns = EMPTY_ANNOTATION_ARRAY;
|
||||
}
|
||||
paramAnns = (index >= 0 && index < annotationArray.length ?
|
||||
adaptAnnotationArray(annotationArray[index]) : EMPTY_ANNOTATION_ARRAY);
|
||||
this.parameterAnnotations = paramAnns;
|
||||
}
|
||||
return paramAnns;
|
||||
@@ -770,7 +777,6 @@ public class MethodParameter {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,11 +24,10 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapt a Reactive Streams {@link Publisher} to and from an async/reactive type
|
||||
* such as {@code CompletableFuture}, an RxJava {@code Observable}, etc.
|
||||
* Adapter for a Reactive Streams {@link Publisher} to and from an async/reactive
|
||||
* type such as {@code CompletableFuture}, RxJava {@code Observable}, and others.
|
||||
*
|
||||
* <p>Use the {@link ReactiveAdapterRegistry} to register reactive types and
|
||||
* obtain adapters from.
|
||||
* <p>An adapter is typically obtained via {@link ReactiveAdapterRegistry}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
@@ -71,28 +70,28 @@ public class ReactiveAdapter {
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut for {@code getDescriptor().getReactiveType()}.
|
||||
* Shortcut for {@code getDescriptor().getReactiveType()}.
|
||||
*/
|
||||
public Class<?> getReactiveType() {
|
||||
return getDescriptor().getReactiveType();
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut for {@code getDescriptor().isMultiValue()}.
|
||||
* Shortcut for {@code getDescriptor().isMultiValue()}.
|
||||
*/
|
||||
public boolean isMultiValue() {
|
||||
return getDescriptor().isMultiValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut for {@code getDescriptor().supportsEmpty()}.
|
||||
* Shortcut for {@code getDescriptor().supportsEmpty()}.
|
||||
*/
|
||||
public boolean supportsEmpty() {
|
||||
return getDescriptor().supportsEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* A shortcut for {@code getDescriptor().isNoValue()}.
|
||||
* Shortcut for {@code getDescriptor().isNoValue()}.
|
||||
*/
|
||||
public boolean isNoValue() {
|
||||
return getDescriptor().isNoValue();
|
||||
@@ -100,8 +99,9 @@ public class ReactiveAdapter {
|
||||
|
||||
|
||||
/**
|
||||
* Adapt the given instance to a Reactive Streams Publisher.
|
||||
* @param source the source object to adapt from
|
||||
* Adapt the given instance to a Reactive Streams {@code Publisher}.
|
||||
* @param source the source object to adapt from; if the given object is
|
||||
* {@code null}, {@link ReactiveTypeDescriptor#getEmptyValue()} is used.
|
||||
* @return the Publisher representing the adaptation
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,13 +34,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.springframework.core.ReactiveTypeDescriptor.multiValue;
|
||||
import static org.springframework.core.ReactiveTypeDescriptor.noValue;
|
||||
import static org.springframework.core.ReactiveTypeDescriptor.singleOptionalValue;
|
||||
import static org.springframework.core.ReactiveTypeDescriptor.singleRequiredValue;
|
||||
|
||||
/**
|
||||
* A registry of adapters to adapt a Reactive Streams {@link Publisher} to/from
|
||||
* A registry of adapters to adapt Reactive Streams {@link Publisher} to/from
|
||||
* various async/reactive types such as {@code CompletableFuture}, RxJava
|
||||
* {@code Observable}, and others.
|
||||
*
|
||||
@@ -64,6 +59,7 @@ public class ReactiveAdapterRegistry {
|
||||
|
||||
/**
|
||||
* Create a registry and auto-register default adapters.
|
||||
* @see #getSharedInstance()
|
||||
*/
|
||||
public ReactiveAdapterRegistry() {
|
||||
|
||||
@@ -168,49 +164,54 @@ public class ReactiveAdapterRegistry {
|
||||
/**
|
||||
* Return a shared default {@code ReactiveAdapterRegistry} instance, lazily
|
||||
* building it once needed.
|
||||
*
|
||||
* <p><b>NOTE:</b> We highly recommend passing a long-lived, pre-configured
|
||||
* {@code ReactiveAdapterRegistry} instance for customization purposes.
|
||||
* This accessor is only meant as a fallback for code paths that want to
|
||||
* fall back on a default instance if one isn't provided.
|
||||
*
|
||||
* @return the shared {@code ReactiveAdapterRegistry} instance (never {@code null})
|
||||
* @since 5.0.2
|
||||
*/
|
||||
public static ReactiveAdapterRegistry getSharedInstance() {
|
||||
ReactiveAdapterRegistry ar = sharedInstance;
|
||||
if (ar == null) {
|
||||
ReactiveAdapterRegistry registry = sharedInstance;
|
||||
if (registry == null) {
|
||||
synchronized (ReactiveAdapterRegistry.class) {
|
||||
ar = sharedInstance;
|
||||
if (ar == null) {
|
||||
ar = new ReactiveAdapterRegistry();
|
||||
sharedInstance = ar;
|
||||
registry = sharedInstance;
|
||||
if (registry == null) {
|
||||
registry = new ReactiveAdapterRegistry();
|
||||
sharedInstance = registry;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ar;
|
||||
return registry;
|
||||
}
|
||||
|
||||
|
||||
private static class ReactorRegistrar {
|
||||
|
||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||
// Flux and Mono ahead of Publisher...
|
||||
|
||||
// Register Flux and Mono before Publisher...
|
||||
|
||||
registry.registerReactiveType(
|
||||
singleOptionalValue(Mono.class, Mono::empty),
|
||||
ReactiveTypeDescriptor.singleOptionalValue(Mono.class, Mono::empty),
|
||||
source -> (Mono<?>) source,
|
||||
Mono::from
|
||||
);
|
||||
|
||||
registry.registerReactiveType(multiValue(Flux.class, Flux::empty),
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.multiValue(Flux.class, Flux::empty),
|
||||
source -> (Flux<?>) source,
|
||||
Flux::from);
|
||||
|
||||
registry.registerReactiveType(multiValue(Publisher.class, Flux::empty),
|
||||
registry.registerReactiveType(
|
||||
ReactiveTypeDescriptor.multiValue(Publisher.class, Flux::empty),
|
||||
source -> (Publisher<?>) source,
|
||||
source -> source);
|
||||
|
||||
registry.registerReactiveType(
|
||||
singleOptionalValue(CompletableFuture.class, () -> {
|
||||
ReactiveTypeDescriptor.singleOptionalValue(CompletableFuture.class, () -> {
|
||||
CompletableFuture<?> empty = new CompletableFuture<>();
|
||||
empty.complete(null);
|
||||
return empty;
|
||||
@@ -226,17 +227,17 @@ public class ReactiveAdapterRegistry {
|
||||
|
||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||
registry.registerReactiveType(
|
||||
multiValue(rx.Observable.class, rx.Observable::empty),
|
||||
ReactiveTypeDescriptor.multiValue(rx.Observable.class, rx.Observable::empty),
|
||||
source -> RxReactiveStreams.toPublisher((rx.Observable<?>) source),
|
||||
RxReactiveStreams::toObservable
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
singleRequiredValue(rx.Single.class),
|
||||
ReactiveTypeDescriptor.singleRequiredValue(rx.Single.class),
|
||||
source -> RxReactiveStreams.toPublisher((rx.Single<?>) source),
|
||||
RxReactiveStreams::toSingle
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
noValue(rx.Completable.class, rx.Completable::complete),
|
||||
ReactiveTypeDescriptor.noValue(rx.Completable.class, rx.Completable::complete),
|
||||
source -> RxReactiveStreams.toPublisher((rx.Completable) source),
|
||||
RxReactiveStreams::toCompletable
|
||||
);
|
||||
@@ -248,27 +249,27 @@ public class ReactiveAdapterRegistry {
|
||||
|
||||
void registerAdapters(ReactiveAdapterRegistry registry) {
|
||||
registry.registerReactiveType(
|
||||
multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
|
||||
ReactiveTypeDescriptor.multiValue(io.reactivex.Flowable.class, io.reactivex.Flowable::empty),
|
||||
source -> (io.reactivex.Flowable<?>) source,
|
||||
Flowable::fromPublisher
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
|
||||
ReactiveTypeDescriptor.multiValue(io.reactivex.Observable.class, io.reactivex.Observable::empty),
|
||||
source -> ((io.reactivex.Observable<?>) source).toFlowable(BackpressureStrategy.BUFFER),
|
||||
source -> io.reactivex.Flowable.fromPublisher(source).toObservable()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
singleRequiredValue(io.reactivex.Single.class),
|
||||
ReactiveTypeDescriptor.singleRequiredValue(io.reactivex.Single.class),
|
||||
source -> ((io.reactivex.Single<?>) source).toFlowable(),
|
||||
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().singleElement().toSingle()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
|
||||
ReactiveTypeDescriptor.singleOptionalValue(io.reactivex.Maybe.class, io.reactivex.Maybe::empty),
|
||||
source -> ((io.reactivex.Maybe<?>) source).toFlowable(),
|
||||
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().singleElement()
|
||||
);
|
||||
registry.registerReactiveType(
|
||||
noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
|
||||
ReactiveTypeDescriptor.noValue(io.reactivex.Completable.class, io.reactivex.Completable::complete),
|
||||
source -> ((io.reactivex.Completable) source).toFlowable(),
|
||||
source -> io.reactivex.Flowable.fromPublisher(source).toObservable().ignoreElements()
|
||||
);
|
||||
@@ -278,15 +279,15 @@ public class ReactiveAdapterRegistry {
|
||||
|
||||
private static class ReactorJdkFlowAdapterRegistrar {
|
||||
|
||||
// TODO: remove reflection when build requires JDK 9+
|
||||
void registerAdapter(ReactiveAdapterRegistry registry) throws Exception {
|
||||
// TODO: remove reflection when build requires JDK 9+
|
||||
Class<?> type = ClassUtils.forName("java.util.concurrent.Flow.Publisher", getClass().getClassLoader());
|
||||
Method toFluxMethod = getMethod("flowPublisherToFlux", type);
|
||||
Method toFlowMethod = getMethod("publisherToFlowPublisher", Publisher.class);
|
||||
Object emptyFlow = ReflectionUtils.invokeMethod(toFlowMethod, null, Flux.empty());
|
||||
|
||||
registry.registerReactiveType(
|
||||
multiValue(type, () -> emptyFlow),
|
||||
ReactiveTypeDescriptor.multiValue(type, () -> emptyFlow),
|
||||
source -> (Publisher<?>) ReflectionUtils.invokeMethod(toFluxMethod, null, source),
|
||||
publisher -> ReflectionUtils.invokeMethod(toFlowMethod, null, publisher)
|
||||
);
|
||||
@@ -299,9 +300,10 @@ public class ReactiveAdapterRegistry {
|
||||
|
||||
|
||||
/**
|
||||
* Extension of ReactiveAdapter that wraps adapted (raw) Publisher's as
|
||||
* {@link Flux} or {@link Mono} depending on the underlying reactive type's
|
||||
* stream semantics.
|
||||
* ReactiveAdapter variant that wraps adapted Publishers as {@link Flux} or
|
||||
* {@link Mono} depending on {@link ReactiveTypeDescriptor#isMultiValue()}.
|
||||
* This is important in places where only the stream and stream element type
|
||||
* information is available like encoders and decoders.
|
||||
*/
|
||||
private static class ReactorAdapter extends ReactiveAdapter {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author 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,8 +22,8 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Descriptor for a reactive type with information about its stream semantics, i.e.
|
||||
* how many values it can produce.
|
||||
* Describes the semantics of a reactive type including boolean checks for
|
||||
* {@link #isMultiValue()}, {@link #supportsEmpty()}, and {@link #isNoValue()}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
@@ -55,21 +55,12 @@ public class ReactiveTypeDescriptor {
|
||||
|
||||
|
||||
/**
|
||||
* Return the reactive type the descriptor was created for.
|
||||
* Return the reactive type for this descriptor.
|
||||
*/
|
||||
public Class<?> getReactiveType() {
|
||||
return this.reactiveType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an empty-value instance for the underlying reactive or async type.
|
||||
* Use of this type implies {@link #supportsEmpty()} is true.
|
||||
*/
|
||||
public Object getEmptyValue() {
|
||||
Assert.state(this.emptyValueSupplier != null, "Empty values not supported");
|
||||
return this.emptyValueSupplier.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if the reactive type can produce more than 1 value
|
||||
* can be produced and is therefore a good fit to adapt to {@code Flux}.
|
||||
@@ -95,6 +86,15 @@ public class ReactiveTypeDescriptor {
|
||||
return this.noValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an empty-value instance for the underlying reactive or async type.
|
||||
* Use of this type implies {@link #supportsEmpty()} is true.
|
||||
*/
|
||||
public Object getEmptyValue() {
|
||||
Assert.state(this.emptyValueSupplier != null, "Empty values not supported");
|
||||
return this.emptyValueSupplier.get();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user