From 2d525901ff6b11d6d26dc072f640b6a4d698cee8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 1 Feb 2010 14:43:35 +0000 Subject: [PATCH] proxies with AspectJ pointcuts are fully serializable within a BeanFactory now (SPR-6681) --- .../aspectj/AspectJExpressionPointcut.java | 69 +++++++++++-------- .../AbstractBeanFactoryPointcutAdvisor.java | 24 +++++-- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java b/org.springframework.aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java index c468e32919d..57985b283aa 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/aspectj/AspectJExpressionPointcut.java @@ -16,6 +16,8 @@ package org.springframework.aop.aspectj; +import java.io.IOException; +import java.io.ObjectInputStream; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Map; @@ -75,27 +77,29 @@ import org.springframework.util.StringUtils; public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware { - private static final Set DEFAULT_SUPPORTED_PRIMITIVES = new HashSet(); + private static final Set SUPPORTED_PRIMITIVES = new HashSet(); static { - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS); - DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS); + SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET); } private static final Log logger = LogFactory.getLog(AspectJExpressionPointcut.class); - private final Map shadowMatchCache = new ConcurrentHashMap(32); + private transient PointcutParser pointcutParser; - private PointcutParser pointcutParser; + private transient PointcutExpression pointcutExpression; + + private transient Map shadowMatchCache = new ConcurrentHashMap(32); private Class pointcutDeclarationScope; @@ -105,26 +109,12 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut private BeanFactory beanFactory; - private PointcutExpression pointcutExpression; - /** * Create a new default AspectJExpressionPointcut. */ public AspectJExpressionPointcut() { - this(DEFAULT_SUPPORTED_PRIMITIVES); - } - - /** - * Create a new AspectJExpressionPointcut with the given supported primitives. - * @param supportedPrimitives Set of {@link org.aspectj.weaver.tools.PointcutPrimitive} - * instances - */ - public AspectJExpressionPointcut(Set supportedPrimitives) { - this.pointcutParser = - PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution( - supportedPrimitives); - this.pointcutParser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler()); + initializePointcutParser(); } /** @@ -134,7 +124,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut * @param paramTypes the parameter types for the pointcut */ public AspectJExpressionPointcut(Class declarationScope, String[] paramNames, Class[] paramTypes) { - this(DEFAULT_SUPPORTED_PRIMITIVES); + initializePointcutParser(); this.pointcutDeclarationScope = declarationScope; if (paramNames.length != paramTypes.length) { throw new IllegalStateException( @@ -144,6 +134,13 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut this.pointcutParameterTypes = paramTypes; } + private void initializePointcutParser() { + this.pointcutParser = + PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution( + SUPPORTED_PRIMITIVES); + this.pointcutParser.registerPointcutDesignatorHandler(new BeanNamePointcutDesignatorHandler()); + } + /** * Set the declaration scope for the pointcut. @@ -528,4 +525,18 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut } } + + //--------------------------------------------------------------------- + // Serialization support + //--------------------------------------------------------------------- + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + // Rely on default serialization, just initialize state after deserialization. + ois.defaultReadObject(); + + // Initialize transient fields. + initializePointcutParser(); + this.shadowMatchCache = new ConcurrentHashMap(32); + } + } diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.java b/org.springframework.aop/src/main/java/org/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.java index 5b0694bbb7f..4a68cb2324c 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2010 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.support; +import java.io.IOException; +import java.io.ObjectInputStream; + import org.aopalliance.aop.Advice; import org.springframework.beans.factory.BeanFactory; @@ -41,9 +44,9 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu private BeanFactory beanFactory; - private Advice advice; + private transient Advice advice; - private final Object adviceMonitor = new Object(); + private transient volatile Object adviceMonitor = new Object(); /** @@ -74,7 +77,7 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu synchronized (this.adviceMonitor) { if (this.advice == null && this.adviceBeanName != null) { Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'"); - this.advice = (Advice) this.beanFactory.getBean(this.adviceBeanName, Advice.class); + this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); } return this.advice; } @@ -85,4 +88,17 @@ public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcu return getClass().getName() + ": advice bean '" + getAdviceBeanName() + "'"; } + + //--------------------------------------------------------------------- + // Serialization support + //--------------------------------------------------------------------- + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + // Rely on default serialization, just initialize state after deserialization. + ois.defaultReadObject(); + + // Initialize transient fields. + this.adviceMonitor = new Object(); + } + }