mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
95 Commits
main
...
v5.0.6.RELEASE
| Author | SHA1 | Date | |
|---|---|---|---|
| f5e8f4983f | |||
| 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
|
||||
|
||||
+9
-10
@@ -14,7 +14,7 @@ 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.kotlin.jvm" version "1.2.41" apply false
|
||||
id "org.jetbrains.dokka" version "0.9.16"
|
||||
id "org.asciidoctor.convert" version "1.5.6"
|
||||
}
|
||||
@@ -46,21 +46,21 @@ configure(allprojects) { project ->
|
||||
ext.groovyVersion = "2.4.15"
|
||||
ext.hsqldbVersion = "2.4.0"
|
||||
ext.jackson2Version = "2.9.5"
|
||||
ext.jettyVersion = "9.4.9.v20180320"
|
||||
ext.jettyVersion = "9.4.10.v20180503"
|
||||
ext.junitJupiterVersion = "5.0.3"
|
||||
ext.junitPlatformVersion = "1.0.3"
|
||||
ext.junitVintageVersion = "4.12.3"
|
||||
ext.kotlinVersion = "1.2.31"
|
||||
ext.kotlinVersion = "1.2.41"
|
||||
ext.log4jVersion = "2.11.0"
|
||||
ext.nettyVersion = "4.1.22.Final"
|
||||
ext.reactorVersion = "Bismuth-SR8"
|
||||
ext.nettyVersion = "4.1.24.Final"
|
||||
ext.reactorVersion = "Bismuth-SR9"
|
||||
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.rxjava2Version = "2.1.13"
|
||||
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.tomcatVersion = "8.5.31"
|
||||
ext.undertowVersion = "1.4.25.Final"
|
||||
|
||||
ext.gradleScriptDir = "${rootProject.projectDir}/gradle"
|
||||
|
||||
@@ -154,7 +154,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}")
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
version=5.0.5.BUILD-SNAPSHOT
|
||||
version=5.0.6.RELEASE
|
||||
|
||||
+6
-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,7 +123,7 @@ task docsZip(type: Zip, dependsOn: ['api', 'asciidoctor', 'dokka']) {
|
||||
into "javadoc-api"
|
||||
}
|
||||
|
||||
from (asciidoctor) {
|
||||
from (asciidoctor.outputDir) {
|
||||
into "spring-framework-reference"
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
+22
-11
@@ -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.
|
||||
@@ -289,10 +289,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 +304,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 +330,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 +365,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 +425,19 @@ 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()) {
|
||||
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 +445,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);
|
||||
@@ -459,7 +470,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
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 +479,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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-18
@@ -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.
|
||||
@@ -31,25 +31,24 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +86,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));
|
||||
@@ -167,8 +161,10 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
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));
|
||||
@@ -181,8 +177,10 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
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));
|
||||
@@ -209,8 +207,10 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
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 +260,14 @@ public class TigerAspectJExpressionPointcutTests {
|
||||
|
||||
@EmptySpringAnnotation
|
||||
public static class SpringAnnotated {
|
||||
|
||||
public void foo() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class BeanA {
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
@@ -283,6 +285,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
|
||||
|
||||
+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}.
|
||||
|
||||
+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
|
||||
|
||||
+20
-5
@@ -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
|
||||
@@ -144,9 +147,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 +301,14 @@ 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 +401,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
|
||||
|
||||
+10
-6
@@ -752,7 +752,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 +777,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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+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((DocumentMatcher) 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((DocumentMatcher) 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((DocumentMatcher) 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();
|
||||
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
|
||||
+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 {
|
||||
}
|
||||
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.BeansException;
|
||||
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() throws Exception {
|
||||
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) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof ExampleBean) {
|
||||
this.applicationContext.publishEvent(new ExampleApplicationEvent(this));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) throws BeansException {
|
||||
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();
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -40,7 +40,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 +86,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
-1
@@ -107,7 +107,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||
}
|
||||
Integer priority = OrderUtils.getPriority(obj.getClass());
|
||||
if (priority == null && obj instanceof DecoratingProxy) {
|
||||
priority = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
|
||||
priority = OrderUtils.getPriority(((DecoratingProxy) obj).getDecoratedClass());
|
||||
}
|
||||
return priority;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ public abstract class AnnotationUtils {
|
||||
private static final Map<Class<?>, Set<Method>> annotatedBaseTypeCache =
|
||||
new ConcurrentReferenceHashMap<>(256);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated // just here for older tool versions trying to reflectively clear the cache
|
||||
private static final Map<Class<?>, ?> annotatedInterfaceCache = annotatedBaseTypeCache;
|
||||
|
||||
@@ -165,7 +166,8 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
Class<? extends Annotation> annotatedElement = annotation.annotationType();
|
||||
try {
|
||||
return synthesizeAnnotation(annotatedElement.getAnnotation(annotationType), annotatedElement);
|
||||
A metaAnn = annotatedElement.getAnnotation(annotationType);
|
||||
return (metaAnn != null ? synthesizeAnnotation(metaAnn, annotatedElement) : null);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleIntrospectionFailure(annotatedElement, ex);
|
||||
@@ -553,13 +555,18 @@ public abstract class AnnotationUtils {
|
||||
if (clazz == null || Object.class == clazz) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
|
||||
Method resolvedEquivalentMethod = BridgeMethodResolver.findBridgedMethod(equivalentMethod);
|
||||
result = findAnnotation((AnnotatedElement) resolvedEquivalentMethod, annotationType);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// No equivalent method found
|
||||
Set<Method> annotatedMethods = getAnnotatedMethodsInBaseType(clazz);
|
||||
if (!annotatedMethods.isEmpty()) {
|
||||
for (Method annotatedMethod : annotatedMethods) {
|
||||
if (annotatedMethod.getName().equals(method.getName()) &&
|
||||
Arrays.equals(annotatedMethod.getParameterTypes(), method.getParameterTypes())) {
|
||||
Method resolvedSuperMethod = BridgeMethodResolver.findBridgedMethod(annotatedMethod);
|
||||
result = findAnnotation((AnnotatedElement) resolvedSuperMethod, annotationType);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
result = searchOnInterfaces(method, annotationType, clazz.getInterfaces());
|
||||
|
||||
@@ -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,7 +33,7 @@ import javax.annotation.meta.When;
|
||||
* <p>Should be used at parameter, return value, and field level. Methods override should
|
||||
* repeat parent {@code @Nullable} annotations unless they behave differently.
|
||||
*
|
||||
* <p>Can be used in association with {@code NonNullApi} or {@code @NonNullFields} to
|
||||
* <p>Can be used in association with {@code @NonNullApi} or {@code @NonNullFields} to
|
||||
* override the default non-nullable semantic to nullable.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -209,14 +209,18 @@ public abstract class StringUtils {
|
||||
return str;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(str);
|
||||
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
|
||||
sb.deleteCharAt(0);
|
||||
int beginIndex = 0;
|
||||
int endIndex = str.length() - 1;
|
||||
|
||||
while (beginIndex <= endIndex && Character.isWhitespace(str.charAt(beginIndex))) {
|
||||
beginIndex++;
|
||||
}
|
||||
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
|
||||
while (endIndex > beginIndex && Character.isWhitespace(str.charAt(endIndex))) {
|
||||
endIndex--;
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
return str.substring(beginIndex, endIndex + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -114,7 +115,7 @@ public class MethodParameterTests {
|
||||
|
||||
@Test // SPR-16652
|
||||
public void annotatedConstructorParameterInInnerClass() throws Exception {
|
||||
Constructor<?> constructor = InnerClass.class.getConstructor(getClass(), String.class, Integer.class);
|
||||
Constructor<?> constructor = InnerClass.class.getConstructor(getClass(), String.class, Callable.class);
|
||||
|
||||
MethodParameter methodParameter = MethodParameter.forExecutable(constructor, 0);
|
||||
assertEquals(getClass(), methodParameter.getParameterType());
|
||||
@@ -125,10 +126,28 @@ public class MethodParameterTests {
|
||||
assertNotNull("Failed to find @Param annotation", methodParameter.getParameterAnnotation(Param.class));
|
||||
|
||||
methodParameter = MethodParameter.forExecutable(constructor, 2);
|
||||
assertEquals(Integer.class, methodParameter.getParameterType());
|
||||
assertEquals(Callable.class, methodParameter.getParameterType());
|
||||
assertNull(methodParameter.getParameterAnnotation(Param.class));
|
||||
}
|
||||
|
||||
@Test // SPR-16734
|
||||
public void genericConstructorParameterInInnerClass() throws Exception {
|
||||
Constructor<?> constructor = InnerClass.class.getConstructor(getClass(), String.class, Callable.class);
|
||||
|
||||
MethodParameter methodParameter = MethodParameter.forExecutable(constructor, 0);
|
||||
assertEquals(getClass(), methodParameter.getParameterType());
|
||||
assertEquals(getClass(), methodParameter.getGenericParameterType());
|
||||
|
||||
methodParameter = MethodParameter.forExecutable(constructor, 1);
|
||||
assertEquals(String.class, methodParameter.getParameterType());
|
||||
assertEquals(String.class, methodParameter.getGenericParameterType());
|
||||
|
||||
methodParameter = MethodParameter.forExecutable(constructor, 2);
|
||||
assertEquals(Callable.class, methodParameter.getParameterType());
|
||||
assertEquals(ResolvableType.forClassWithGenerics(Callable.class, Integer.class).getType(),
|
||||
methodParameter.getGenericParameterType());
|
||||
}
|
||||
|
||||
|
||||
public int method(String p1, long p2) {
|
||||
return 42;
|
||||
@@ -144,7 +163,7 @@ public class MethodParameterTests {
|
||||
@SuppressWarnings("unused")
|
||||
private class InnerClass {
|
||||
|
||||
public InnerClass(@Param String s, Integer i) {
|
||||
public InnerClass(@Param String s, Callable<Integer> i) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -44,20 +45,21 @@ import static org.junit.Assert.*;
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class ClassUtilsTests {
|
||||
|
||||
private ClassLoader classLoader = getClass().getClassLoader();
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
public void clearStatics() {
|
||||
InnerClass.noArgCalled = false;
|
||||
InnerClass.argCalled = false;
|
||||
InnerClass.overloadedCalled = false;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsPresent() throws Exception {
|
||||
public void testIsPresent() {
|
||||
assertTrue(ClassUtils.isPresent("java.lang.String", classLoader));
|
||||
assertFalse(ClassUtils.isPresent("java.lang.MySpecialString", classLoader));
|
||||
}
|
||||
@@ -114,6 +116,36 @@ public class ClassUtilsTests {
|
||||
assertEquals(double[].class, ClassUtils.forName(double[].class.getName(), classLoader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsCacheSafe() {
|
||||
ClassLoader childLoader1 = new ClassLoader(classLoader) {};
|
||||
ClassLoader childLoader2 = new ClassLoader(classLoader) {};
|
||||
ClassLoader childLoader3 = new ClassLoader(classLoader) {
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
return childLoader1.loadClass(name);
|
||||
}
|
||||
};
|
||||
Class<?> composite = ClassUtils.createCompositeInterface(
|
||||
new Class<?>[] {Serializable.class, Externalizable.class}, childLoader1);
|
||||
|
||||
assertTrue(ClassUtils.isCacheSafe(String.class, null));
|
||||
assertTrue(ClassUtils.isCacheSafe(String.class, classLoader));
|
||||
assertTrue(ClassUtils.isCacheSafe(String.class, childLoader1));
|
||||
assertTrue(ClassUtils.isCacheSafe(String.class, childLoader2));
|
||||
assertTrue(ClassUtils.isCacheSafe(String.class, childLoader3));
|
||||
assertFalse(ClassUtils.isCacheSafe(InnerClass.class, null));
|
||||
assertTrue(ClassUtils.isCacheSafe(InnerClass.class, classLoader));
|
||||
assertTrue(ClassUtils.isCacheSafe(InnerClass.class, childLoader1));
|
||||
assertTrue(ClassUtils.isCacheSafe(InnerClass.class, childLoader2));
|
||||
assertTrue(ClassUtils.isCacheSafe(InnerClass.class, childLoader3));
|
||||
assertFalse(ClassUtils.isCacheSafe(composite, null));
|
||||
assertFalse(ClassUtils.isCacheSafe(composite, classLoader));
|
||||
assertTrue(ClassUtils.isCacheSafe(composite, childLoader1));
|
||||
assertFalse(ClassUtils.isCacheSafe(composite, childLoader2));
|
||||
assertTrue(ClassUtils.isCacheSafe(composite, childLoader3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetShortName() {
|
||||
String className = ClassUtils.getShortName(getClass());
|
||||
@@ -199,7 +231,7 @@ public class ClassUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasMethod() throws Exception {
|
||||
public void testHasMethod() {
|
||||
assertTrue(ClassUtils.hasMethod(Collection.class, "size"));
|
||||
assertTrue(ClassUtils.hasMethod(Collection.class, "remove", Object.class));
|
||||
assertFalse(ClassUtils.hasMethod(Collection.class, "remove"));
|
||||
@@ -207,7 +239,7 @@ public class ClassUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMethodIfAvailable() throws Exception {
|
||||
public void testGetMethodIfAvailable() {
|
||||
Method method = ClassUtils.getMethodIfAvailable(Collection.class, "size");
|
||||
assertNotNull(method);
|
||||
assertEquals("size", method.getName());
|
||||
@@ -278,7 +310,7 @@ public class ClassUtilsTests {
|
||||
@Test
|
||||
public void testClassPackageAsResourcePath() {
|
||||
String result = ClassUtils.classPackageAsResourcePath(Proxy.class);
|
||||
assertTrue(result.equals("java/lang/reflect"));
|
||||
assertEquals("java/lang/reflect", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -294,7 +326,7 @@ public class ClassUtilsTests {
|
||||
@Test
|
||||
public void testGetAllInterfaces() {
|
||||
DerivedTestObject testBean = new DerivedTestObject();
|
||||
List ifcs = Arrays.asList(ClassUtils.getAllInterfaces(testBean));
|
||||
List<Class<?>> ifcs = Arrays.asList(ClassUtils.getAllInterfaces(testBean));
|
||||
assertEquals("Correct number of interfaces", 4, ifcs.size());
|
||||
assertTrue("Contains Serializable", ifcs.contains(Serializable.class));
|
||||
assertTrue("Contains ITestBean", ifcs.contains(ITestObject.class));
|
||||
@@ -303,13 +335,13 @@ public class ClassUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testClassNamesToString() {
|
||||
List ifcs = new LinkedList();
|
||||
List<Class<?>> ifcs = new LinkedList<>();
|
||||
ifcs.add(Serializable.class);
|
||||
ifcs.add(Runnable.class);
|
||||
assertEquals("[interface java.io.Serializable, interface java.lang.Runnable]", ifcs.toString());
|
||||
assertEquals("[java.io.Serializable, java.lang.Runnable]", ClassUtils.classNamesToString(ifcs));
|
||||
|
||||
List classes = new LinkedList();
|
||||
List<Class<?>> classes = new LinkedList<>();
|
||||
classes.add(LinkedList.class);
|
||||
classes.add(Integer.class);
|
||||
assertEquals("[class java.util.LinkedList, class java.lang.Integer]", classes.toString());
|
||||
@@ -319,7 +351,7 @@ public class ClassUtilsTests {
|
||||
assertEquals("[java.util.List]", ClassUtils.classNamesToString(List.class));
|
||||
|
||||
assertEquals("[]", Collections.EMPTY_LIST.toString());
|
||||
assertEquals("[]", ClassUtils.classNamesToString(Collections.EMPTY_LIST));
|
||||
assertEquals("[]", ClassUtils.classNamesToString(Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -48,7 +48,7 @@ public class SpelEvaluationException extends EvaluationException {
|
||||
}
|
||||
|
||||
public SpelEvaluationException(int position, Throwable cause, SpelMessage message, Object... inserts) {
|
||||
super(position, message.formatMessage(inserts),cause);
|
||||
super(position, message.formatMessage(inserts), cause);
|
||||
this.message = message;
|
||||
this.inserts = inserts;
|
||||
}
|
||||
|
||||
+17
-11
@@ -45,13 +45,13 @@ public enum SpelMessage {
|
||||
"A problem occurred whilst attempting to construct an object of type ''{0}'' using arguments ''{1}''"),
|
||||
|
||||
METHOD_NOT_FOUND(Kind.ERROR, 1004,
|
||||
"Method call: Method {0} cannot be found on {1} type"),
|
||||
"Method call: Method {0} cannot be found on type {1}"),
|
||||
|
||||
TYPE_NOT_FOUND(Kind.ERROR, 1005,
|
||||
"Type cannot be found ''{0}''"),
|
||||
|
||||
FUNCTION_NOT_DEFINED(Kind.ERROR, 1006,
|
||||
"The function ''{0}'' could not be found"),
|
||||
"Function ''{0}'' could not be found"),
|
||||
|
||||
PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL(Kind.ERROR, 1007,
|
||||
"Property or field ''{0}'' cannot be found on null"),
|
||||
@@ -156,7 +156,7 @@ public enum SpelMessage {
|
||||
NOT_A_REAL(Kind.ERROR, 1040,
|
||||
"The value ''{0}'' cannot be parsed as a double"),
|
||||
|
||||
MORE_INPUT(Kind.ERROR,1041,
|
||||
MORE_INPUT(Kind.ERROR, 1041,
|
||||
"After parsing a valid expression, there is still more data in the expression: ''{0}''"),
|
||||
|
||||
RIGHT_OPERAND_PROBLEM(Kind.ERROR, 1042,
|
||||
@@ -226,21 +226,22 @@ public enum SpelMessage {
|
||||
"A required array dimension has not been specified"),
|
||||
|
||||
INITIALIZER_LENGTH_INCORRECT(Kind.ERROR, 1064,
|
||||
"array initializer size does not match array dimensions"),
|
||||
"Array initializer size does not match array dimensions"),
|
||||
|
||||
UNEXPECTED_ESCAPE_CHAR(Kind.ERROR, 1065, "unexpected escape character."),
|
||||
UNEXPECTED_ESCAPE_CHAR(Kind.ERROR, 1065,
|
||||
"Unexpected escape character"),
|
||||
|
||||
OPERAND_NOT_INCREMENTABLE(Kind.ERROR, 1066,
|
||||
"the expression component ''{0}'' does not support increment"),
|
||||
"The expression component ''{0}'' does not support increment"),
|
||||
|
||||
OPERAND_NOT_DECREMENTABLE(Kind.ERROR, 1067,
|
||||
"the expression component ''{0}'' does not support decrement"),
|
||||
"The expression component ''{0}'' does not support decrement"),
|
||||
|
||||
NOT_ASSIGNABLE(Kind.ERROR, 1068,
|
||||
"the expression component ''{0}'' is not assignable"),
|
||||
"The expression component ''{0}'' is not assignable"),
|
||||
|
||||
MISSING_CHARACTER(Kind.ERROR, 1069,
|
||||
"missing expected character ''{0}''"),
|
||||
"Missing expected character ''{0}''"),
|
||||
|
||||
LEFT_OPERAND_PROBLEM(Kind.ERROR, 1070,
|
||||
"Problem parsing left operand"),
|
||||
@@ -248,8 +249,13 @@ public enum SpelMessage {
|
||||
MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071,
|
||||
"A required selection expression has not been specified"),
|
||||
|
||||
EXCEPTION_RUNNING_COMPILED_EXPRESSION(Kind.ERROR,1072,
|
||||
"An exception occurred whilst evaluating a compiled expression");
|
||||
/** @since 4.1 */
|
||||
EXCEPTION_RUNNING_COMPILED_EXPRESSION(Kind.ERROR, 1072,
|
||||
"An exception occurred whilst evaluating a compiled expression"),
|
||||
|
||||
/** @since 4.3.17 */
|
||||
FLAWED_PATTERN(Kind.ERROR, 1073,
|
||||
"Failed to efficiently evaluate pattern ''{0}'': consider redesigning it");
|
||||
|
||||
|
||||
private final Kind kind;
|
||||
|
||||
+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.
|
||||
@@ -23,7 +23,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Utility methods (formatters, etc) used during parsing and evaluation.
|
||||
* Utility methods (formatters etc) used during parsing and evaluation.
|
||||
*
|
||||
* @author Andy Clement
|
||||
*/
|
||||
|
||||
+19
-12
@@ -131,7 +131,7 @@ public class MethodReference extends SpelNodeImpl {
|
||||
}
|
||||
|
||||
// either there was no accessor or it no longer existed
|
||||
executorToUse = findAccessorForMethod(this.name, argumentTypes, value, evaluationContext);
|
||||
executorToUse = findAccessorForMethod(argumentTypes, value, evaluationContext);
|
||||
this.cachedExecutor = new CachedMethodExecutor(
|
||||
executorToUse, (value instanceof Class ? (Class<?>) value : null), targetType, argumentTypes);
|
||||
try {
|
||||
@@ -196,33 +196,40 @@ public class MethodReference extends SpelNodeImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
private MethodExecutor findAccessorForMethod(String name, List<TypeDescriptor> argumentTypes,
|
||||
Object targetObject, EvaluationContext evaluationContext) throws SpelEvaluationException {
|
||||
private MethodExecutor findAccessorForMethod(List<TypeDescriptor> argumentTypes, Object targetObject,
|
||||
EvaluationContext evaluationContext) throws SpelEvaluationException {
|
||||
|
||||
AccessException accessException = null;
|
||||
List<MethodResolver> methodResolvers = evaluationContext.getMethodResolvers();
|
||||
for (MethodResolver methodResolver : methodResolvers) {
|
||||
try {
|
||||
MethodExecutor methodExecutor = methodResolver.resolve(
|
||||
evaluationContext, targetObject, name, argumentTypes);
|
||||
evaluationContext, targetObject, this.name, argumentTypes);
|
||||
if (methodExecutor != null) {
|
||||
return methodExecutor;
|
||||
}
|
||||
}
|
||||
catch (AccessException ex) {
|
||||
throw new SpelEvaluationException(getStartPosition(), ex,
|
||||
SpelMessage.PROBLEM_LOCATING_METHOD, name, targetObject.getClass());
|
||||
accessException = ex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.METHOD_NOT_FOUND,
|
||||
FormatHelper.formatMethodForMessage(name, argumentTypes),
|
||||
FormatHelper.formatClassNameForMessage(
|
||||
targetObject instanceof Class ? ((Class<?>) targetObject) : targetObject.getClass()));
|
||||
String method = FormatHelper.formatMethodForMessage(this.name, argumentTypes);
|
||||
String className = FormatHelper.formatClassNameForMessage(
|
||||
targetObject instanceof Class ? ((Class<?>) targetObject) : targetObject.getClass());
|
||||
if (accessException != null) {
|
||||
throw new SpelEvaluationException(
|
||||
getStartPosition(), accessException, SpelMessage.PROBLEM_LOCATING_METHOD, method, className);
|
||||
}
|
||||
else {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.METHOD_NOT_FOUND, method, className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the AccessException, throwing a lightweight evaluation exception or, if the
|
||||
* cause was a RuntimeException, throw the RuntimeException directly.
|
||||
* Decode the AccessException, throwing a lightweight evaluation exception or,
|
||||
* if the cause was a RuntimeException, throw the RuntimeException directly.
|
||||
*/
|
||||
private void throwSimpleExceptionIfPossible(Object value, AccessException ex) {
|
||||
if (ex.getCause() instanceof InvocationTargetException) {
|
||||
|
||||
+53
-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.
|
||||
@@ -40,6 +40,8 @@ import org.springframework.expression.spel.support.BooleanTypedValue;
|
||||
*/
|
||||
public class OperatorMatches extends Operator {
|
||||
|
||||
private static final int PATTERN_ACCESS_THRESHOLD = 1000000;
|
||||
|
||||
private final ConcurrentMap<String, Pattern> patternCache = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
@@ -79,11 +81,59 @@ public class OperatorMatches extends Operator {
|
||||
pattern = Pattern.compile(rightString);
|
||||
this.patternCache.putIfAbsent(rightString, pattern);
|
||||
}
|
||||
Matcher matcher = pattern.matcher(left);
|
||||
Matcher matcher = pattern.matcher(new MatcherInput(left, new AccessCount()));
|
||||
return BooleanTypedValue.forValue(matcher.matches());
|
||||
}
|
||||
catch (PatternSyntaxException ex) {
|
||||
throw new SpelEvaluationException(rightOp.getStartPosition(), ex, SpelMessage.INVALID_PATTERN, right);
|
||||
throw new SpelEvaluationException(
|
||||
rightOp.getStartPosition(), ex, SpelMessage.INVALID_PATTERN, right);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
throw new SpelEvaluationException(
|
||||
rightOp.getStartPosition(), ex, SpelMessage.FLAWED_PATTERN, right);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class AccessCount {
|
||||
|
||||
private int count;
|
||||
|
||||
public void check() throws IllegalStateException {
|
||||
if (this.count++ > PATTERN_ACCESS_THRESHOLD) {
|
||||
throw new IllegalStateException("Pattern access threshold exceeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MatcherInput implements CharSequence {
|
||||
|
||||
private final CharSequence value;
|
||||
|
||||
private AccessCount access;
|
||||
|
||||
public MatcherInput(CharSequence value, AccessCount access) {
|
||||
this.value = value;
|
||||
this.access = access;
|
||||
}
|
||||
|
||||
public char charAt(int index) {
|
||||
this.access.check();
|
||||
return this.value.charAt(index);
|
||||
}
|
||||
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return new MatcherInput(this.value.subSequence(start, end), this.access);
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return this.value.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.value.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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.
|
||||
@@ -265,7 +265,7 @@ class Tokenizer {
|
||||
raiseParseException(this.pos, SpelMessage.UNEXPECTED_ESCAPE_CHAR);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Cannot handle (" + Integer.valueOf(ch) + ") '" + ch + "'");
|
||||
throw new IllegalStateException("Cannot handle (" + (int) ch + ") '" + ch + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -194,6 +194,22 @@ public class EvaluationTests extends AbstractExpressionTests {
|
||||
evaluate("27 matches '^.*2.*$'", true, Boolean.class); // conversion int>string
|
||||
}
|
||||
|
||||
@Test // SPR-16731
|
||||
public void testMatchesWithPatternAccessThreshold() {
|
||||
String pattern = "^(?=[a-z0-9-]{1,47})([a-z0-9]+[-]{0,1}){1,47}[a-z0-9]{1}$";
|
||||
String expression = "'abcde-fghijklmn-o42pasdfasdfasdf.qrstuvwxyz10x.xx.yyy.zasdfasfd' matches \'" + pattern + "\'";
|
||||
Expression expr = parser.parseExpression(expression);
|
||||
try {
|
||||
expr.getValue();
|
||||
fail("Should have exceeded threshold");
|
||||
}
|
||||
catch (EvaluationException ee) {
|
||||
SpelEvaluationException see = (SpelEvaluationException) ee;
|
||||
assertEquals(SpelMessage.FLAWED_PATTERN, see.getMessageCode());
|
||||
assertTrue(see.getCause() instanceof IllegalStateException);
|
||||
}
|
||||
}
|
||||
|
||||
// mixing operators
|
||||
@Test
|
||||
public void testMixingOperators01() {
|
||||
|
||||
+12
-8
@@ -76,7 +76,7 @@ public class DatabaseStartupValidator implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Set the interval between validation runs (in seconds).
|
||||
* Default is 1.
|
||||
* Default is {@value #DEFAULT_INTERVAL}.
|
||||
*/
|
||||
public void setInterval(int interval) {
|
||||
this.interval = interval;
|
||||
@@ -84,7 +84,7 @@ public class DatabaseStartupValidator implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Set the timeout (in seconds) after which a fatal exception
|
||||
* will be thrown. Default is 60.
|
||||
* will be thrown. Default is {@value #DEFAULT_TIMEOUT}.
|
||||
*/
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
@@ -127,11 +127,15 @@ public class DatabaseStartupValidator implements InitializingBean {
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
latestEx = ex;
|
||||
logger.debug("Validation query [" + this.validationQuery + "] threw exception", ex);
|
||||
float rest = ((float) (deadLine - System.currentTimeMillis())) / 1000;
|
||||
if (rest > this.interval) {
|
||||
logger.warn("Database has not started up yet - retrying in " + this.interval +
|
||||
" seconds (timeout in " + rest + " seconds)");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Validation query [" + this.validationQuery + "] threw exception", ex);
|
||||
}
|
||||
if (logger.isWarnEnabled()) {
|
||||
float rest = ((float) (deadLine - System.currentTimeMillis())) / 1000;
|
||||
if (rest > this.interval) {
|
||||
logger.warn("Database has not started up yet - retrying in " + this.interval +
|
||||
" seconds (timeout in " + rest + " seconds)");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
@@ -149,8 +153,8 @@ public class DatabaseStartupValidator implements InitializingBean {
|
||||
"Database has not started up within " + this.timeout + " seconds", latestEx);
|
||||
}
|
||||
|
||||
float duration = (System.currentTimeMillis() - beginTime)*1f / 1000;
|
||||
if (logger.isInfoEnabled()) {
|
||||
float duration = ((float) (System.currentTimeMillis() - beginTime)) / 1000;
|
||||
logger.info("Database startup detected after " + duration + " seconds");
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class SqlLobValueTests {
|
||||
lob.setTypeValue(preparedStatement, 1, Types.CLOB, "test");
|
||||
verify(creator).setClobAsAsciiStream(eq(preparedStatement), eq(1), inputStreamCaptor.capture(), eq(3));
|
||||
byte[] bytes = new byte[3];
|
||||
inputStreamCaptor.getValue().read(bytes );
|
||||
inputStreamCaptor.getValue().read(bytes);
|
||||
assertThat(bytes, equalTo(testContent));
|
||||
}
|
||||
|
||||
|
||||
+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.
|
||||
@@ -65,7 +65,7 @@ public class DataSourceTransactionManagerTests {
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
public void setup() throws Exception {
|
||||
ds = mock(DataSource.class);
|
||||
con = mock(Connection.class);
|
||||
given(ds.getConnection()).willReturn(con);
|
||||
|
||||
+6
-2
@@ -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.
|
||||
@@ -84,6 +84,7 @@ public class JmsMessageEndpointFactory extends AbstractMessageEndpointFactory {
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
Throwable endpointEx = null;
|
||||
boolean applyDeliveryCalls = !hasBeforeDeliveryBeenCalled();
|
||||
if (applyDeliveryCalls) {
|
||||
try {
|
||||
@@ -97,6 +98,7 @@ public class JmsMessageEndpointFactory extends AbstractMessageEndpointFactory {
|
||||
getMessageListener().onMessage(message);
|
||||
}
|
||||
catch (RuntimeException | Error ex) {
|
||||
endpointEx = ex;
|
||||
onEndpointException(ex);
|
||||
throw ex;
|
||||
}
|
||||
@@ -106,7 +108,9 @@ public class JmsMessageEndpointFactory extends AbstractMessageEndpointFactory {
|
||||
afterDelivery();
|
||||
}
|
||||
catch (ResourceException ex) {
|
||||
throw new JmsResourceException(ex);
|
||||
if (endpointEx == null) {
|
||||
throw new JmsResourceException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -49,7 +49,7 @@ import static org.mockito.BDDMockito.*;
|
||||
public class JmsTransactionManagerTests {
|
||||
|
||||
@After
|
||||
public void verifyTransactionSynchronizationManager() {
|
||||
public void verifyTransactionSynchronizationManagerState() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ dependencies {
|
||||
testCompile("org.apache.tomcat.embed:tomcat-embed-websocket:${tomcatVersion}")
|
||||
testCompile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
testCompile("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
testCompile("org.xmlunit:xmlunit-matchers:2.5.1")
|
||||
testRuntime("com.sun.xml.bind:jaxb-core:2.3.0")
|
||||
testRuntime("com.sun.xml.bind:jaxb-impl:2.3.0")
|
||||
testRuntime("com.sun.activation:javax.activation:1.2.0")
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class HeaderMethodArgumentResolver extends AbstractNamedValueMethodArgume
|
||||
logger.warn("Message headers contain two values for the same header '" + name + "', " +
|
||||
"one in the top level header map and a second in the nested map with native headers. " +
|
||||
"Using the value from top level map. " +
|
||||
"Use 'nativeHeader.myHeader' to resolve to the value from the nested native header map." );
|
||||
"Use 'nativeHeader.myHeader' to resolve to the value from the nested native header map.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user