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 4d0392c2478..c7575168899 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; @@ -135,7 +142,7 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence */ private int joinPointStaticPartArgumentIndex = -1; - private Map argumentBindings = null; + private Map argumentBindings; private boolean argumentsIntrospected = false; @@ -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; } @@ -250,17 +259,17 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence this.argumentNames[i] + "' that is not a valid Java identifier"); } } - if (argumentNames != null) { - if (aspectJAdviceMethod.getParameterTypes().length == argumentNames.length + 1) { + if (this.argumentNames != null) { + if (this.aspectJAdviceMethod.getParameterTypes().length == this.argumentNames.length + 1) { // May need to add implicit join point arg name... - Class firstArgType = aspectJAdviceMethod.getParameterTypes()[0]; + Class firstArgType = this.aspectJAdviceMethod.getParameterTypes()[0]; if (firstArgType == JoinPoint.class || firstArgType == ProceedingJoinPoint.class || firstArgType == JoinPoint.StaticPart.class) { - String[] oldNames = argumentNames; - argumentNames = new String[oldNames.length + 1]; - argumentNames[0] = "THIS_JOIN_POINT"; - System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length); + String[] oldNames = this.argumentNames; + this.argumentNames = new String[oldNames.length + 1]; + this.argumentNames[0] = "THIS_JOIN_POINT"; + System.arraycopy(oldNames, 0, this.argumentNames, 1, oldNames.length); } } } @@ -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--; @@ -456,13 +465,13 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length; if (this.argumentNames.length != numExpectedArgumentNames) { - throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames - + " arguments to bind by name in advice, but actually found " + + throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames + + " arguments to bind by name in advice, but actually found " + this.argumentNames.length + " arguments."); } // So we match in number... - int argumentIndexOffset = this.adviceInvocationArgumentCount - numArgumentsLeftToBind; + int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind; for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) { this.argumentBindings.put(this.argumentNames[i], i); } @@ -471,8 +480,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence // specified, and find the discovered argument types. if (this.returningName != null) { if (!this.argumentBindings.containsKey(this.returningName)) { - throw new IllegalStateException("Returning argument name '" - + this.returningName + "' was not bound in advice arguments"); + throw new IllegalStateException("Returning argument name '" + this.returningName + + "' was not bound in advice arguments"); } else { Integer index = this.argumentBindings.get(this.returningName); @@ -482,8 +491,8 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence } if (this.throwingName != null) { if (!this.argumentBindings.containsKey(this.throwingName)) { - throw new IllegalStateException("Throwing argument name '" - + this.throwingName + "' was not bound in advice arguments"); + throw new IllegalStateException("Throwing argument name '" + this.throwingName + + "' was not bound in advice arguments"); } else { Integer index = this.argumentBindings.get(this.throwingName); @@ -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,11 +589,10 @@ public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedence } } - if (numBound != this.adviceInvocationArgumentCount) { - throw new IllegalStateException("Required to bind " + this.adviceInvocationArgumentCount - + " arguments, but only bound " + numBound + " (JoinPointMatch " + - (jpMatch == null ? "was NOT" : "WAS") + - " bound in invocation)"); + 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)"); } return adviceInvocationArgs; @@ -665,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 c6669af2511..3de3c25aaf0 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 @@ -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,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) { @@ -37,6 +40,7 @@ public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodI super(aspectJBeforeAdviceMethod, pointcut, aif); } + @Override public Object invoke(MethodInvocation mi) throws Throwable { try { 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 59d5ae6e097..40a547560cd 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) { @@ -40,6 +43,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement super(aspectJBeforeAdviceMethod, pointcut, aif); } + @Override public boolean isBeforeAdvice() { return false; @@ -62,6 +66,7 @@ public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implement } } + /** * Following AspectJ semantics, if a returning clause was specified, then the * advice is only invoked if the returned value is an instance of the given 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 486b2612754..fcf89a1215f 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 @@ -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,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) { @@ -37,6 +40,7 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements super(aspectJBeforeAdviceMethod, pointcut, aif); } + @Override public boolean isBeforeAdvice() { return false; @@ -57,11 +61,11 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements try { return mi.proceed(); } - catch (Throwable t) { - if (shouldInvokeOnThrowing(t)) { - invokeAdviceMethod(getJoinPointMatch(), null, t); + catch (Throwable ex) { + if (shouldInvokeOnThrowing(ex)) { + invokeAdviceMethod(getJoinPointMatch(), null, ex); } - throw t; + throw ex; } } @@ -69,8 +73,8 @@ public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements * In AspectJ semantics, after throwing advice that specifies a throwing clause * is only invoked if the thrown exception is a subtype of the given throwing type. */ - private boolean shouldInvokeOnThrowing(Throwable t) { - return getDiscoveredThrowingType().isAssignableFrom(t.getClass()); + private boolean shouldInvokeOnThrowing(Throwable ex) { + return getDiscoveredThrowingType().isAssignableFrom(ex.getClass()); } } 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 b9c546342b5..66f3b03bf41 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 @@ -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,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) { @@ -41,6 +43,7 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method super(aspectJAroundAdviceMethod, pointcut, aif); } + @Override public boolean isBeforeAdvice() { return false; @@ -56,7 +59,6 @@ public class AspectJAroundAdvice extends AbstractAspectJAdvice implements Method return true; } - @Override public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { 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 6f7ce26b395..b18345667c4 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 @@ -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,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) { @@ -35,6 +37,7 @@ public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements super(aspectJBeforeAdviceMethod, pointcut, aif); } + @Override public void before(Method method, Object[] args, Object target) throws Throwable { invokeAdviceMethod(getJoinPointMatch(), null, null); 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 1e8f723efb1..d311f620068 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 a70010e1f99..dd8823ec1cd 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,12 +44,27 @@ 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) - + * allows us to determine if two pieces of advice come from the + * same aspect and hence their relative precedence. + */ + private final String aspectName; + + /** + * The aspect class, stored separately for re-resolution of the + * corresponding AjType on deserialization. + */ + private final Class aspectClass; /** * 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 @@ -54,13 +73,6 @@ public class AspectMetadata { */ private final Pointcut perClausePointcut; - /** - * The name of this aspect as defined to Spring (the bean name) - - * allows us to determine if two pieces of advice come from the - * same aspect and hence their relative precedence. - */ - private String aspectName; - /** * Create a new AspectMetadata instance for the given aspect class. @@ -83,10 +95,11 @@ public class AspectMetadata { if (ajType == null) { throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect"); } - this.ajType = ajType; - if (this.ajType.getDeclarePrecedence().length > 0) { + 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()) { case SINGLETON : @@ -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 4ac2b0282cf..e2cb10cd2d3 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 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.annotation; +import java.io.Serializable; + import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.Ordered; @@ -37,7 +39,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; 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 200936f1407..b58d4ffc1fa 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 @@ -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,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,26 +40,33 @@ 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 Pointcut pointcut; + private final Class declaringClass; - private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; + private final String methodName; - private final Method method; + private final Class[] parameterTypes; - private final boolean lazy; + private transient Method aspectJAdviceMethod; private final AspectJAdvisorFactory atAspectJAdvisorFactory; - private Advice instantiatedAdvice; + private final MetadataAwareAspectInstanceFactory aspectInstanceFactory; - private int declarationOrder; + private final int declarationOrder; - private String aspectName; + private final String aspectName; + + private final Pointcut pointcut; + + private final boolean lazy; + + private Advice instantiatedAdvice; private Boolean isBeforeAdvice; @@ -67,7 +77,10 @@ class InstantiationModelAwarePointcutAdvisorImpl MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { this.declaredPointcut = ajexp; - this.method = method; + this.declaringClass = method.getDeclaringClass(); + this.methodName = method.getName(); + this.parameterTypes = method.getParameterTypes(); + this.aspectJAdviceMethod = method; this.atAspectJAdvisorFactory = af; this.aspectInstanceFactory = aif; this.declarationOrder = declarationOrderInAspect; @@ -86,9 +99,9 @@ class InstantiationModelAwarePointcutAdvisorImpl } else { // A singleton aspect. - this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); - this.pointcut = declaredPointcut; + this.pointcut = this.declaredPointcut; this.lazy = false; + this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } } @@ -142,8 +155,8 @@ class InstantiationModelAwarePointcutAdvisorImpl private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { - return this.atAspectJAdvisorFactory.getAdvice( - this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); + return this.atAspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut, + this.aspectInstanceFactory, this.declarationOrder, this.aspectName); } public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() { @@ -191,7 +204,7 @@ class InstantiationModelAwarePointcutAdvisorImpl */ private void determineAdviceType() { AspectJAnnotation aspectJAnnotation = - AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.method); + AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(this.aspectJAdviceMethod); if (aspectJAnnotation == null) { this.isBeforeAdvice = false; this.isAfterAdvice = false; @@ -220,11 +233,21 @@ class InstantiationModelAwarePointcutAdvisorImpl @Override public String toString() { return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() + - "]; advice method [" + this.method + "]; perClauseKind=" + + "]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" + this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind(); } + private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + inputStream.defaultReadObject(); + try { + this.aspectJAdviceMethod = this.declaringClass.getMethod(this.methodName, this.parameterTypes); + } + catch (NoSuchMethodException ex) { + throw new IllegalStateException("Failed to find advice method on deserialization", ex); + } + } + /** * Pointcut implementation that changes its behaviour when the advice is instantiated. 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 36bb4eeb42e..3baa84d03b0 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 @@ -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.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; 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 5d6fc9079b1..e1e171557be 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 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,11 +16,13 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; + import org.springframework.beans.factory.BeanFactory; /** - * AspectInstanceFactory backed by a BeanFactory-provided prototype, - * enforcing prototype semantics. + * {@link org.springframework.aop.aspectj.AspectInstanceFactory} backed by a + * {@link BeanFactory}-provided prototype, enforcing prototype semantics. * *

Note that this may instantiate multiple times, which probably won't give the * semantics you expect. Use a {@link LazySingletonAspectInstanceFactoryDecorator} @@ -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 bf8cab2b087..825cb0ceab2 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 @@ -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,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_COMPARATOR; 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 0f83e6c2f08..b16e8d1576d 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-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.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; diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJPointcutAdvisorTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJPointcutAdvisorTests.java index b524e0c74bb..3cf475bee43 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJPointcutAdvisorTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectJPointcutAdvisorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,9 +31,10 @@ import static org.junit.Assert.*; * @author Rod Johnson * @author Chris Beams */ -public final class AspectJPointcutAdvisorTests { +public class AspectJPointcutAdvisorTests { + + private final AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory(); - private AspectJAdvisorFactory af = new ReflectiveAspectJAdvisorFactory(); @Test public void testSingleton() throws SecurityException, NoSuchMethodException { @@ -41,8 +42,8 @@ public final class AspectJPointcutAdvisorTests { ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS); InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp, - new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null),"someBean"), - TestBean.class.getMethod("getAge", (Class[]) null),1,"someBean"); + new SingletonMetadataAwareAspectInstanceFactory(new AbstractAspectJAdvisorFactoryTests.ExceptionAspect(null), "someBean"), + TestBean.class.getMethod("getAge", (Class[]) null), 1, "someBean"); assertSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut()); assertFalse(ajpa.isPerInstance()); } @@ -53,33 +54,32 @@ public final class AspectJPointcutAdvisorTests { ajexp.setExpression(AspectJExpressionPointcutTests.MATCH_ALL_METHODS); InstantiationModelAwarePointcutAdvisorImpl ajpa = new InstantiationModelAwarePointcutAdvisorImpl(af, ajexp, - new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(),"someBean"), null, 1, "someBean"); + new SingletonMetadataAwareAspectInstanceFactory(new PerTargetAspect(),"someBean"), + TestBean.class.getMethod("getAge", (Class[]) null), 1, "someBean"); assertNotSame(Pointcut.TRUE, ajpa.getAspectMetadata().getPerClausePointcut()); assertTrue(ajpa.getAspectMetadata().getPerClausePointcut() instanceof AspectJExpressionPointcut); assertTrue(ajpa.isPerInstance()); assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getClassFilter().matches(TestBean.class)); assertFalse(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches( - TestBean.class.getMethod("getAge", (Class[]) null), - TestBean.class)); + TestBean.class.getMethod("getAge", (Class[]) null), TestBean.class)); assertTrue(ajpa.getAspectMetadata().getPerClausePointcut().getMethodMatcher().matches( - TestBean.class.getMethod("getSpouse", (Class[]) null), - TestBean.class)); + TestBean.class.getMethod("getSpouse", (Class[]) null), TestBean.class)); } - @Test(expected=AopConfigException.class) + @Test(expected = AopConfigException.class) public void testPerCflowTarget() { testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowAspect.class); } - @Test(expected=AopConfigException.class) + @Test(expected = AopConfigException.class) public void testPerCflowBelowTarget() { testIllegalInstantiationModel(AbstractAspectJAdvisorFactoryTests.PerCflowBelowAspect.class); } private void testIllegalInstantiationModel(Class c) throws AopConfigException { - new AspectMetadata(c,"someBean"); + new AspectMetadata(c, "someBean"); } } diff --git a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectProxyFactoryTests.java b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectProxyFactoryTests.java index 4113f1699d8..0c4304c95dd 100644 --- a/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectProxyFactoryTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/aspectj/annotation/AspectProxyFactoryTests.java @@ -16,13 +16,13 @@ package org.springframework.aop.aspectj.annotation; +import java.io.Serializable; import java.util.Arrays; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; -import org.junit.Ignore; import org.junit.Test; import test.aop.PerThisAspect; @@ -80,7 +80,18 @@ public class AspectProxyFactoryTests { } @Test - @Ignore // InstantiationModelAwarePointcutAdvisorImpl not serializable yet + @SuppressWarnings("unchecked") + public void testSerializable() throws Exception { + AspectJProxyFactory proxyFactory = new AspectJProxyFactory(new TestBean()); + proxyFactory.addAspect(LoggingAspectOnVarargs.class); + ITestBean proxy = proxyFactory.getProxy(); + assertTrue(proxy.doWithVarargs(MyEnum.A, MyOtherEnum.C)); + ITestBean tb = (ITestBean) SerializationTestUtils.serializeAndDeserialize(proxy); + assertTrue(tb.doWithVarargs(MyEnum.A, MyOtherEnum.C)); + } + + @Test + @SuppressWarnings("unchecked") public void testWithInstance() throws Exception { MultiplyReturnValue aspect = new MultiplyReturnValue(); int multiple = 3; @@ -133,7 +144,8 @@ public class AspectProxyFactoryTests { } - public static class TestBean implements ITestBean { + @SuppressWarnings("serial") + public static class TestBean implements ITestBean, Serializable { private int age; @@ -171,7 +183,8 @@ public class AspectProxyFactoryTests { @Aspect - public static class LoggingAspectOnVarargs { + @SuppressWarnings("serial") + public static class LoggingAspectOnVarargs implements Serializable { @Around("execution(* doWithVarargs(*))") public Object doLog(ProceedingJoinPoint pjp) throws Throwable { @@ -193,11 +206,9 @@ public class AspectProxyFactoryTests { } -/** - * @author Rod Johnson - */ @Aspect -class MultiplyReturnValue { +@SuppressWarnings("serial") +class MultiplyReturnValue implements Serializable { private int multiple = 2;