1 16 17 package org.springframework.aop.aspectj.annotation; 18 19 import java.lang.annotation.Annotation ; 20 import java.lang.reflect.Constructor ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Modifier ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 import java.util.StringTokenizer ; 26 27 import org.apache.commons.logging.Log; 28 import org.apache.commons.logging.LogFactory; 29 import org.aspectj.lang.annotation.After; 30 import org.aspectj.lang.annotation.AfterReturning; 31 import org.aspectj.lang.annotation.AfterThrowing; 32 import org.aspectj.lang.annotation.Around; 33 import org.aspectj.lang.annotation.Aspect; 34 import org.aspectj.lang.annotation.Before; 35 import org.aspectj.lang.annotation.Pointcut; 36 import org.aspectj.lang.reflect.AjType; 37 import org.aspectj.lang.reflect.AjTypeSystem; 38 import org.aspectj.lang.reflect.PerClauseKind; 39 40 import org.springframework.aop.aspectj.AspectJExpressionPointcut; 41 import org.springframework.aop.framework.AopConfigException; 42 import org.springframework.core.ParameterNameDiscoverer; 43 import org.springframework.core.PrioritizedParameterNameDiscoverer; 44 import org.springframework.core.annotation.AnnotationUtils; 45 import org.springframework.util.StringUtils; 46 47 59 public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory { 60 61 protected static final ParameterNameDiscoverer ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER = 62 new AspectJAnnotationParameterNameDiscoverer(); 63 64 65 69 protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method aMethod) { 70 Class <? extends Annotation >[] classesToLookFor = (Class <? extends Annotation >[]) new Class [] { 71 Before.class, 72 Around.class, 73 After.class, 74 AfterReturning.class, 75 AfterThrowing.class, 76 Pointcut.class 77 }; 78 for (Class <? extends Annotation > c : classesToLookFor) { 79 AspectJAnnotation foundAnnotation = findAnnotation(aMethod, c); 80 if (foundAnnotation != null) { 81 return foundAnnotation; 82 } 83 } 84 return null; 85 } 86 87 private static <A extends Annotation > AspectJAnnotation<A> findAnnotation(Method method, Class <A> toLookFor) { 88 A result = AnnotationUtils.findAnnotation(method, toLookFor); 89 if (result != null) { 90 return new AspectJAnnotation<A>(result); 91 } 92 else { 93 return null; 94 } 95 } 96 97 98 99 protected final Log logger = LogFactory.getLog(getClass()); 100 101 protected final ParameterNameDiscoverer parameterNameDiscoverer; 102 103 104 protected AbstractAspectJAdvisorFactory() { 105 PrioritizedParameterNameDiscoverer prioritizedParameterNameDiscoverer = new PrioritizedParameterNameDiscoverer(); 106 prioritizedParameterNameDiscoverer.addDiscoverer(ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER); 107 this.parameterNameDiscoverer = prioritizedParameterNameDiscoverer; 108 } 109 110 public boolean isAspect(Class <?> clazz) { 111 return (AjTypeSystem.getAjType(clazz).isAspect() && clazz.getAnnotation(Aspect.class) != null); 112 } 113 114 public void validate(Class <?> aspectClass) throws AopConfigException { 115 if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null && 117 !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) { 118 throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" + 119 aspectClass.getSuperclass().getName() + "]"); 120 } 121 122 AjType<?> ajType = AjTypeSystem.getAjType(aspectClass); 123 if (!ajType.isAspect()) { 124 throw new NotAnAtAspectException(aspectClass); 125 } 126 if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) { 127 throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " + 128 "This is not supported in Spring AOP."); 129 } 130 if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) { 131 throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " + 132 "This is not supported in Spring AOP."); 133 } 134 } 135 136 141 protected AspectJExpressionPointcut createPointcutExpression( 142 Method annotatedMethod, Class declarationScope, String [] pointcutParameterNames) { 143 144 Class <?> [] pointcutParameterTypes = new Class <?>[0]; 145 if (pointcutParameterNames != null) { 146 pointcutParameterTypes = extractPointcutParameterTypes(pointcutParameterNames,annotatedMethod); 147 } 148 149 AspectJExpressionPointcut ajexp = 150 new AspectJExpressionPointcut(declarationScope,pointcutParameterNames,pointcutParameterTypes); 151 ajexp.setLocation(annotatedMethod.toString()); 152 return ajexp; 153 } 154 155 161 private Class <?>[] extractPointcutParameterTypes(String [] argNames, Method adviceMethod) { 162 Class <?>[] ret = new Class <?>[argNames.length]; 163 Class <?>[] paramTypes = adviceMethod.getParameterTypes(); 164 if (argNames.length > paramTypes.length) { 165 throw new IllegalStateException ("Expecting at least " + argNames.length + 166 " arguments in the advice declaration, but only found " + paramTypes.length); 167 } 168 int typeOffset = paramTypes.length - argNames.length; 171 for (int i = 0; i < ret.length; i++) { 172 ret[i] = paramTypes[i+typeOffset]; 173 } 174 return ret; 175 } 176 177 178 protected enum AspectJAnnotationType { 179 AtPointcut, 180 AtBefore, 181 AtAfter, 182 AtAfterReturning, 183 AtAfterThrowing, 184 AtAround 185 }; 186 187 188 192 protected static class AspectJAnnotation<A extends Annotation > { 193 194 private static Map <Class ,AspectJAnnotationType> annotationTypes = new HashMap <Class ,AspectJAnnotationType>(); 195 196 private static final String [] EXPRESSION_PROPERTIES = new String []{"value", "pointcut"}; 197 198 static { 199 annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut); 200 annotationTypes.put(After.class,AspectJAnnotationType.AtAfter); 201 annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning); 202 annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing); 203 annotationTypes.put(Around.class,AspectJAnnotationType.AtAround); 204 annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore); 205 } 206 207 private final A annotation; 208 private AspectJAnnotationType annotationType; 209 private final String expression; 210 private final String argNames; 211 212 public AspectJAnnotation(A aspectjAnnotation) { 213 this.annotation = aspectjAnnotation; 214 for (Class type : annotationTypes.keySet()) { 215 if (type.isInstance(this.annotation)) { 216 this.annotationType = annotationTypes.get(type); 217 break; 218 } 219 } 220 if (this.annotationType == null) { 221 throw new IllegalStateException ("Unknown annotation type: " + this.annotation.toString()); 222 } 223 224 try { 227 this.expression = resolveExpression(); 228 this.argNames = (String ) 229 this.annotation.getClass().getMethod("argNames", (Class []) null).invoke(this.annotation); 230 } 231 catch (Exception ex) { 232 throw new IllegalArgumentException (aspectjAnnotation + " cannot be an AspectJ annotation", ex); 233 } 234 } 235 236 private String resolveExpression() throws Exception { 237 String expression = null; 238 for (int i = 0; i < EXPRESSION_PROPERTIES.length; i++) { 239 String methodName = EXPRESSION_PROPERTIES[i]; 240 Method method; 241 try { 242 method = this.annotation.getClass().getDeclaredMethod(methodName); 243 } 244 catch (NoSuchMethodException ex) { 245 method = null; 246 } 247 if (method != null) { 248 String candidate = (String ) method.invoke(this.annotation); 249 if (StringUtils.hasText(candidate)) { 250 expression = candidate; 251 } 252 } 253 } 254 return expression; 255 } 256 257 public AspectJAnnotationType getAnnotationType() { 258 return this.annotationType; 259 } 260 261 public A getAnnotation() { 262 return this.annotation; 263 } 264 265 public String getPointcutExpression() { 266 return this.expression; 267 } 268 269 public String getArgNames() { 270 return this.argNames; 271 } 272 273 public String toString() { 274 return this.annotation.toString(); 275 } 276 } 277 278 279 283 private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer { 284 285 public String [] getParameterNames(Method method) { 286 if (method.getParameterTypes().length == 0) { 287 return new String [0]; 288 } 289 AspectJAnnotation annotation = findAspectJAnnotationOnMethod(method); 290 if (annotation == null) { 291 return null; 292 } 293 StringTokenizer strTok = new StringTokenizer (annotation.getArgNames(), ","); 294 if (strTok.countTokens() > 0) { 295 String [] names = new String [strTok.countTokens()]; 296 for (int i = 0; i < names.length; i++) { 297 names[i] = strTok.nextToken(); 298 } 299 return names; 300 } 301 else { 302 return null; 303 } 304 } 305 306 public String [] getParameterNames(Constructor ctor) { 307 throw new UnsupportedOperationException ("Spring AOP cannot handle constructor advice"); 308 } 309 } 310 311 } 312 | Popular Tags |