diff options
Diffstat (limited to 'spring-aop/src/main/java/org/springframework')
27 files changed, 258 insertions, 64 deletions
diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java index 71bd31d9..c7575168 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java @@ -16,6 +16,9 @@ package org.springframework.aop.aspectj; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -55,7 +58,8 @@ import org.springframework.util.StringUtils; * @author Ramnivas Laddad * @since 2.0 */ -public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation { +@SuppressWarnings("serial") +public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable { /** * Key used in ReflectiveMethodInvocation userAtributes map for the current joinpoint. @@ -86,10 +90,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence } - protected final Method aspectJAdviceMethod; + private final Class<?> declaringClass; - /** The total number of arguments we have to populate on advice dispatch */ - private final int adviceInvocationArgumentCount; + private final String methodName; + + private final Class<?>[] parameterTypes; + + protected transient Method aspectJAdviceMethod; private final AspectJExpressionPointcut pointcut; @@ -154,8 +161,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) { Assert.notNull(aspectJAdviceMethod, "Advice method must not be null"); + this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); + this.methodName = aspectJAdviceMethod.getName(); + this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); this.aspectJAdviceMethod = aspectJAdviceMethod; - this.adviceInvocationArgumentCount = this.aspectJAdviceMethod.getParameterTypes().length; this.pointcut = pointcut; this.aspectInstanceFactory = aspectInstanceFactory; } @@ -359,11 +368,11 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence */ public synchronized final void calculateArgumentBindings() { // The simple case... nothing to bind. - if (this.argumentsIntrospected || this.adviceInvocationArgumentCount == 0) { + if (this.argumentsIntrospected || this.parameterTypes.length == 0) { return; } - int numUnboundArgs = this.adviceInvocationArgumentCount; + int numUnboundArgs = this.parameterTypes.length; Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes(); if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) { numUnboundArgs--; @@ -462,7 +471,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence } // So we match in number... - int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind; + int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind; for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) { this.argumentBindings.put(this.argumentNames[i], i); } @@ -543,7 +552,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence calculateArgumentBindings(); // AMC start - Object[] adviceInvocationArgs = new Object[this.adviceInvocationArgumentCount]; + Object[] adviceInvocationArgs = new Object[this.parameterTypes.length]; int numBound = 0; if (this.joinPointArgumentIndex != -1) { @@ -580,8 +589,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence } } - if (numBound != this.adviceInvocationArgumentCount) { - throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount + + if (numBound != this.parameterTypes.length) { + throw new IllegalStateException("Required to bind " + this.parameterTypes.length + " arguments, but only bound " + numBound + " (JoinPointMatch " + (jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)"); } @@ -664,6 +673,16 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence "aspect name '" + this.aspectName + "'"; } + private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + try { + this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes); + } + catch (NoSuchMethodException ex) { + throw new IllegalStateException("Failed to find advice method on deserialization", ex); + } + } + /** * MethodMatcher that excludes the specified advice method. diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java index a1900b89..3de3c25a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterAdvice.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; @@ -29,7 +30,9 @@ import org.springframework.aop.AfterAdvice; * @author Rod Johnson * @since 2.0 */ -public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice { +@SuppressWarnings("serial") +public class AspectJAfterAdvice extends AbstractAspectJAdvice + implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterReturningAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterReturningAdvice.java index 3a852bdb..92f9cb4a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterReturningAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterReturningAdvice.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -32,7 +33,9 @@ import org.springframework.util.TypeUtils; * @author Ramnivas Laddad * @since 2.0 */ -public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice { +@SuppressWarnings("serial") +public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice + implements AfterReturningAdvice, AfterAdvice, Serializable { public AspectJAfterReturningAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java index be74c7e4..fcf89a12 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAfterThrowingAdvice.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; @@ -29,7 +30,9 @@ import org.springframework.aop.AfterAdvice; * @author Rod Johnson * @since 2.0 */ -public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice { +@SuppressWarnings("serial") +public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice + implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterThrowingAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java index 3efefd27..66f3b03b 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAroundAdvice.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; @@ -33,7 +34,8 @@ import org.springframework.aop.ProxyMethodInvocation; * @author Juergen Hoeller * @since 2.0 */ -public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor { +@SuppressWarnings("serial") +public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable { public AspectJAroundAdvice( Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJMethodBeforeAdvice.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJMethodBeforeAdvice.java index 65a5dce1..b1834566 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJMethodBeforeAdvice.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJMethodBeforeAdvice.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; @@ -27,7 +28,8 @@ import org.springframework.aop.MethodBeforeAdvice; * @author Adrian Colyer * @since 2.0 */ -public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice { +@SuppressWarnings("serial") +public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable { public AspectJMethodBeforeAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java index 3272b922..47e46155 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/DeclareParentsAdvisor.java @@ -65,7 +65,7 @@ public class DeclareParentsAdvisor implements IntroductionAdvisor { /** * Private constructor to share common code between impl-based delegate and reference-based delegate - * (cannot use method such as init() to share common code, due the the use of final fields) + * (cannot use method such as init() to share common code, due the use of final fields) * @param interfaceType static field defining the introduction * @param typePattern type pattern the introduction is restricted to * @param implementationClass implementation class diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java index f1275dae..5d413bd6 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/SimpleAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,10 +55,12 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory { return this.aspectClass.newInstance(); } catch (InstantiationException ex) { - throw new AopConfigException("Unable to instantiate aspect class [" + this.aspectClass.getName() + "]", ex); + throw new AopConfigException( + "Unable to instantiate aspect class: " + this.aspectClass.getName(), ex); } catch (IllegalAccessException ex) { - throw new AopConfigException("Cannot access element class [" + this.aspectClass.getName() + "]", ex); + throw new AopConfigException( + "Could not access aspect constructor: " + this.aspectClass.getName(), ex); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/SingletonAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/SingletonAspectInstanceFactory.java index 1e8f723e..d311f620 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/SingletonAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/SingletonAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj; +import java.io.Serializable; + import org.springframework.core.Ordered; import org.springframework.util.Assert; @@ -29,7 +31,8 @@ import org.springframework.util.Assert; * @since 2.0 * @see SimpleAspectInstanceFactory */ -public class SingletonAspectInstanceFactory implements AspectInstanceFactory { +@SuppressWarnings("serial") +public class SingletonAspectInstanceFactory implements AspectInstanceFactory, Serializable { private final Object aspectInstance; diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java index d20e5222..dd8823ec 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java @@ -16,6 +16,10 @@ package org.springframework.aop.aspectj.annotation; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; + import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.AjType; import org.aspectj.lang.reflect.AjTypeSystem; @@ -40,7 +44,8 @@ import org.springframework.aop.support.ComposablePointcut; * @since 2.0 * @see org.springframework.aop.aspectj.AspectJExpressionPointcut */ -public class AspectMetadata { +@SuppressWarnings("serial") +public class AspectMetadata implements Serializable { /** * The name of this aspect as defined to Spring (the bean name) - @@ -50,9 +55,16 @@ public class AspectMetadata { private final String aspectName; /** + * The aspect class, stored separately for re-resolution of the + * corresponding AjType on deserialization. + */ + private final Class<?> aspectClass; + + /** * AspectJ reflection information (AspectJ 5 / Java 5 specific). + * Re-resolved on deserialization since it isn't serializable itself. */ - private final AjType<?> ajType; + private transient AjType<?> ajType; /** * Spring AOP pointcut corresponding to the per clause of the @@ -86,6 +98,7 @@ public class AspectMetadata { if (ajType.getDeclarePrecedence().length > 0) { throw new IllegalArgumentException("DeclarePrecendence not presently supported in Spring AOP"); } + this.aspectClass = ajType.getJavaClass(); this.ajType = ajType; switch (this.ajType.getPerClause().getKind()) { @@ -132,7 +145,7 @@ public class AspectMetadata { * Return the aspect class. */ public Class<?> getAspectClass() { - return this.ajType.getJavaClass(); + return this.aspectClass; } /** @@ -173,4 +186,10 @@ public class AspectMetadata { return (isPerThisOrPerTarget() || isPerTypeWithin()); } + + private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + this.ajType = AjTypeSystem.getAjType(this.aspectClass); + } + } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java index 713fb44f..f68fea56 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/BeanFactoryAspectInstanceFactory.java @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.Ordered; @@ -38,7 +40,8 @@ import org.springframework.util.ClassUtils; * @see org.springframework.beans.factory.BeanFactory * @see LazySingletonAspectInstanceFactoryDecorator */ -public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory { +@SuppressWarnings("serial") +public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInstanceFactory, Serializable { private final BeanFactory beanFactory; @@ -92,6 +95,7 @@ public class BeanFactoryAspectInstanceFactory implements MetadataAwareAspectInst return this.aspectMetadata; } + @Override public Object getAspectCreationMutex() { return (this.beanFactory instanceof ConfigurableBeanFactory ? ((ConfigurableBeanFactory) this.beanFactory).getSingletonMutex() : this); diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java index 750a1eb2..27d3a9ba 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/InstantiationModelAwarePointcutAdvisorImpl.java @@ -16,6 +16,9 @@ package org.springframework.aop.aspectj.annotation; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; import java.lang.reflect.Method; import org.aopalliance.aop.Advice; @@ -37,12 +40,19 @@ import org.springframework.aop.support.Pointcuts; * @author Juergen Hoeller * @since 2.0 */ +@SuppressWarnings("serial") class InstantiationModelAwarePointcutAdvisorImpl - implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation { + implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable { private final AspectJExpressionPointcut declaredPointcut; - private final Method aspectJAdviceMethod; + private final Class<?> declaringClass; + + private final String methodName; + + private final Class<?>[] parameterTypes; + + private transient Method aspectJAdviceMethod; private final AspectJAdvisorFactory aspectJAdvisorFactory; @@ -68,6 +78,9 @@ class InstantiationModelAwarePointcutAdvisorImpl MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { this.declaredPointcut = declaredPointcut; + this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); + this.methodName = aspectJAdviceMethod.getName(); + this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); this.aspectJAdviceMethod = aspectJAdviceMethod; this.aspectJAdvisorFactory = aspectJAdvisorFactory; this.aspectInstanceFactory = aspectInstanceFactory; @@ -227,6 +240,16 @@ class InstantiationModelAwarePointcutAdvisorImpl } + private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + try { + this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes); + } + catch (NoSuchMethodException ex) { + throw new IllegalStateException("Failed to find advice method on deserialization", ex); + } + } + /** * Pointcut implementation that changes its behaviour when the advice is instantiated. diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/LazySingletonAspectInstanceFactoryDecorator.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/LazySingletonAspectInstanceFactoryDecorator.java index 78df5465..3e76fb47 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/LazySingletonAspectInstanceFactoryDecorator.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/LazySingletonAspectInstanceFactoryDecorator.java @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; + import org.springframework.util.Assert; /** @@ -25,7 +27,8 @@ import org.springframework.util.Assert; * @author Juergen Hoeller * @since 2.0 */ -public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory { +@SuppressWarnings("serial") +public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwareAspectInstanceFactory, Serializable { private final MetadataAwareAspectInstanceFactory maaif; @@ -45,11 +48,7 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar @Override public Object getAspectInstance() { if (this.materialized == null) { - Object mutex = this; - if (this.maaif instanceof BeanFactoryAspectInstanceFactory) { - mutex = ((BeanFactoryAspectInstanceFactory) this.maaif).getAspectCreationMutex(); - } - synchronized (mutex) { + synchronized (this.maaif.getAspectCreationMutex()) { if (this.materialized == null) { this.materialized = this.maaif.getAspectInstance(); } @@ -73,6 +72,11 @@ public class LazySingletonAspectInstanceFactoryDecorator implements MetadataAwar } @Override + public Object getAspectCreationMutex() { + return this.maaif.getAspectCreationMutex(); + } + + @Override public int getOrder() { return this.maaif.getOrder(); } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/MetadataAwareAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/MetadataAwareAspectInstanceFactory.java index cb9a77d4..a001efbc 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/MetadataAwareAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/MetadataAwareAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,4 +39,11 @@ public interface MetadataAwareAspectInstanceFactory extends AspectInstanceFactor */ AspectMetadata getAspectMetadata(); + /** + * Return the best possible creation mutex for this factory. + * @return the mutex object (never {@code null}) + * @since 4.3 + */ + Object getAspectCreationMutex(); + } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/PrototypeAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/PrototypeAspectInstanceFactory.java index fc2978a9..e1e17155 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/PrototypeAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/PrototypeAspectInstanceFactory.java @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; + import org.springframework.beans.factory.BeanFactory; /** @@ -32,7 +34,8 @@ import org.springframework.beans.factory.BeanFactory; * @see org.springframework.beans.factory.BeanFactory * @see LazySingletonAspectInstanceFactoryDecorator */ -public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory { +@SuppressWarnings("serial") +public class PrototypeAspectInstanceFactory extends BeanFactoryAspectInstanceFactory implements Serializable { /** * Create a PrototypeAspectInstanceFactory. AspectJ will be called to diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java index 1a354930..ce139f71 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java @@ -16,6 +16,7 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -65,7 +66,8 @@ import org.springframework.util.comparator.InstanceComparator; * @author Phillip Webb * @since 2.0 */ -public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory { +@SuppressWarnings("serial") +public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable { private static final Comparator<Method> METHOD_COMPARATOR; diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SimpleMetadataAwareAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SimpleMetadataAwareAspectInstanceFactory.java index 5b8113e7..2aa2431a 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SimpleMetadataAwareAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SimpleMetadataAwareAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,6 +51,11 @@ public class SimpleMetadataAwareAspectInstanceFactory extends SimpleAspectInstan } @Override + public Object getAspectCreationMutex() { + return this; + } + + @Override protected int getOrderForAspectClass(Class<?> aspectClass) { return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE); } diff --git a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SingletonMetadataAwareAspectInstanceFactory.java b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SingletonMetadataAwareAspectInstanceFactory.java index 0f83e6c2..15edfbbd 100644 --- a/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SingletonMetadataAwareAspectInstanceFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/SingletonMetadataAwareAspectInstanceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; + import org.springframework.aop.aspectj.SingletonAspectInstanceFactory; import org.springframework.core.Ordered; import org.springframework.core.annotation.OrderUtils; @@ -30,8 +32,9 @@ import org.springframework.core.annotation.OrderUtils; * @since 2.0 * @see SimpleMetadataAwareAspectInstanceFactory */ +@SuppressWarnings("serial") public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspectInstanceFactory - implements MetadataAwareAspectInstanceFactory { + implements MetadataAwareAspectInstanceFactory, Serializable { private final AspectMetadata metadata; @@ -53,6 +56,11 @@ public class SingletonMetadataAwareAspectInstanceFactory extends SingletonAspect } @Override + public Object getAspectCreationMutex() { + return this; + } + + @Override protected int getOrderForAspectClass(Class<?> aspectClass) { return OrderUtils.getOrder(aspectClass, Ordered.LOWEST_PRECEDENCE); } diff --git a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java index d3f199c5..c2271500 100644 --- a/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -97,7 +97,7 @@ public abstract class AopConfigUtils { } } - static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { + public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java index 9b3b3074..40940374 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -586,7 +586,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised { * Simple wrapper class around a Method. Used as the key when * caching methods, for efficient equals and hashCode comparisons. */ - private static class MethodCacheKey { + private static final class MethodCacheKey implements Comparable<MethodCacheKey> { private final Method method; @@ -599,17 +599,28 @@ public class AdvisedSupport extends ProxyConfig implements Advised { @Override public boolean equals(Object other) { - if (other == this) { - return true; - } - MethodCacheKey otherKey = (MethodCacheKey) other; - return (this.method == otherKey.method); + return (this == other || (other instanceof MethodCacheKey && + this.method == ((MethodCacheKey) other).method)); } @Override public int hashCode() { return this.hashCode; } + + @Override + public String toString() { + return this.method.toString(); + } + + @Override + public int compareTo(MethodCacheKey other) { + int result = this.method.getName().compareTo(other.method.getName()); + if (result == 0) { + result = this.method.toString().compareTo(other.method.toString()); + } + return result; + } } } diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java b/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java index 4e063d2b..15535a5e 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AopProxyUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.springframework.aop.TargetClassAware; import org.springframework.aop.TargetSource; import org.springframework.aop.support.AopUtils; import org.springframework.aop.target.SingletonTargetSource; +import org.springframework.core.DecoratingProxy; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -78,11 +79,29 @@ public abstract class AopProxyUtils { * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the * {@link org.springframework.aop.SpringProxy} marker interface. + * @param advised the proxy config * @return the complete set of interfaces to proxy + * @see SpringProxy * @see Advised - * @see org.springframework.aop.SpringProxy */ public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) { + return completeProxiedInterfaces(advised, false); + } + + /** + * Determine the complete set of interfaces to proxy for the given AOP configuration. + * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's + * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the + * {@link org.springframework.aop.SpringProxy} marker interface. + * @param advised the proxy config + * @param decoratingProxy whether to expose the {@link DecoratingProxy} interface + * @return the complete set of interfaces to proxy + * @since 4.3 + * @see SpringProxy + * @see Advised + * @see DecoratingProxy + */ + static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces(); if (specifiedInterfaces.length == 0) { // No user-specified interfaces: check whether target class is an interface. @@ -99,6 +118,7 @@ public abstract class AopProxyUtils { } boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class); boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class); + boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)); int nonUserIfcCount = 0; if (addSpringProxy) { nonUserIfcCount++; @@ -106,13 +126,22 @@ public abstract class AopProxyUtils { if (addAdvised) { nonUserIfcCount++; } + if (addDecoratingProxy) { + nonUserIfcCount++; + } Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length + nonUserIfcCount]; System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length); + int index = specifiedInterfaces.length; if (addSpringProxy) { - proxiedInterfaces[specifiedInterfaces.length] = SpringProxy.class; + proxiedInterfaces[index] = SpringProxy.class; + index++; } if (addAdvised) { - proxiedInterfaces[proxiedInterfaces.length - 1] = Advised.class; + proxiedInterfaces[index] = Advised.class; + index++; + } + if (addDecoratingProxy) { + proxiedInterfaces[index] = DecoratingProxy.class; } return proxiedInterfaces; } @@ -134,6 +163,9 @@ public abstract class AopProxyUtils { if (proxy instanceof Advised) { nonUserIfcCount++; } + if (proxy instanceof DecoratingProxy) { + nonUserIfcCount++; + } Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - nonUserIfcCount]; System.arraycopy(proxyInterfaces, 0, userInterfaces, 0, userInterfaces.length); Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces"); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java index e98c3085..1f90b0b5 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.aop.AopInvocationException; import org.springframework.aop.RawTargetAccess; import org.springframework.aop.TargetSource; import org.springframework.aop.support.AopUtils; +import org.springframework.core.DecoratingProxy; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -116,7 +117,7 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } - Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised); + Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } @@ -164,11 +165,15 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa // The target does not implement the equals(Object) method itself. return equals(args[0]); } - if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { + else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } - if (!this.advised.opaque && method.getDeclaringClass().isInterface() && + else if (method.getDeclaringClass() == DecoratingProxy.class) { + // There is only getDecoratedClass() declared -> dispatch to proxy config. + return AopProxyUtils.ultimateTargetClass(this.advised); + } + else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/ProxyProcessorSupport.java b/spring-aop/src/main/java/org/springframework/aop/framework/ProxyProcessorSupport.java index af1cf603..a94c53b1 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/ProxyProcessorSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/ProxyProcessorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -139,7 +139,8 @@ public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanC * @return whether the given interface is an internal language interface */ protected boolean isInternalLanguageInterface(Class<?> ifc) { - return ifc.getName().equals("groovy.lang.GroovyObject"); + return (ifc.getName().equals("groovy.lang.GroovyObject") || + ifc.getName().endsWith(".cglib.proxy.Factory")); } } diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java index eb476b4e..72934308 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.Advisor; +import org.springframework.aop.Pointcut; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.AopInfrastructureBean; import org.springframework.aop.framework.ProxyFactory; @@ -370,6 +371,7 @@ public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport */ protected boolean isInfrastructureClass(Class<?> beanClass) { boolean retVal = Advice.class.isAssignableFrom(beanClass) || + Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); if (retVal && logger.isTraceEnabled()) { diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java index a771146f..af39672c 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/autoproxy/AutoProxyUtils.java @@ -35,7 +35,7 @@ public abstract class AutoProxyUtils { * to be proxied with its target class (in case of it getting proxied in the first * place). The value is {@code Boolean.TRUE} or {@code Boolean.FALSE}. * <p>Proxy factories can set this attribute if they built a target class proxy - * for a specific bean, and want to enforce that that bean can always be cast + * for a specific bean, and want to enforce that bean can always be cast * to its target class (even if AOP advices get applied through auto-proxying). * @see #shouldProxyTargetClass */ diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java index b1cdaa0f..28917436 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java @@ -235,7 +235,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { if (logger.isInfoEnabled()) { logger.info("More than one TaskExecutor bean found within the context, and none is named " + "'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " + - "as an alias) in order to use it for async processing."); + "as an alias) in order to use it for async processing: " + ex.getBeanNamesFound()); } } } diff --git a/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java b/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java index 1ed373ca..4c8273ec 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package org.springframework.aop.support; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -34,6 +35,7 @@ import org.springframework.aop.PointcutAdvisor; import org.springframework.aop.SpringProxy; import org.springframework.aop.TargetClassAware; import org.springframework.core.BridgeMethodResolver; +import org.springframework.core.MethodIntrospector; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -113,6 +115,30 @@ public abstract class AopUtils { } /** + * Select an invocable method on the target type: either the given method itself + * if actually exposed on the target type, or otherwise a corresponding method + * on one of the target type's interfaces or on the target type itself. + * @param method the method to check + * @param targetType the target type to search methods on (typically an AOP proxy) + * @return a corresponding invocable method on the target type + * @throws IllegalStateException if the given method is not invocable on the given + * target type (typically due to a proxy mismatch) + * @since 4.3 + * @see MethodIntrospector#selectInvocableMethod(Method, Class) + */ + public static Method selectInvocableMethod(Method method, Class<?> targetType) { + Method methodToUse = MethodIntrospector.selectInvocableMethod(method, targetType); + if (Modifier.isPrivate(methodToUse.getModifiers()) && !Modifier.isStatic(methodToUse.getModifiers()) && + SpringProxy.class.isAssignableFrom(targetType)) { + throw new IllegalStateException(String.format( + "Need to invoke method '%s' found on proxy for target class '%s' but cannot " + + "be delegated to target bean. Switch its visibility to package or protected.", + method.getName(), method.getDeclaringClass().getSimpleName())); + } + return methodToUse; + } + + /** * Determine whether the given method is an "equals" method. * @see java.lang.Object#equals */ @@ -196,6 +222,11 @@ public abstract class AopUtils { } MethodMatcher methodMatcher = pc.getMethodMatcher(); + if (methodMatcher == MethodMatcher.TRUE) { + // No need to iterate the methods if we're matching any method anyway... + return true; + } + IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; @@ -204,7 +235,7 @@ public abstract class AopUtils { Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { - Method[] methods = clazz.getMethods(); + Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || |