1 16 17 package org.springframework.aop.aspectj.annotation; 18 19 import java.lang.reflect.Field ; 20 import java.lang.reflect.Method ; 21 import java.util.LinkedList ; 22 import java.util.List ; 23 24 import org.aopalliance.aop.Advice; 25 import org.aspectj.lang.JoinPoint; 26 import org.aspectj.lang.ProceedingJoinPoint; 27 import org.aspectj.lang.annotation.AfterReturning; 28 import org.aspectj.lang.annotation.AfterThrowing; 29 import org.aspectj.lang.annotation.DeclareParents; 30 import org.aspectj.lang.annotation.Pointcut; 31 32 import org.springframework.aop.Advisor; 33 import org.springframework.aop.MethodBeforeAdvice; 34 import org.springframework.aop.aspectj.AbstractAspectJAdvice; 35 import org.springframework.aop.aspectj.AspectJAfterAdvice; 36 import org.springframework.aop.aspectj.AspectJAfterReturningAdvice; 37 import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice; 38 import org.springframework.aop.aspectj.AspectJAroundAdvice; 39 import org.springframework.aop.aspectj.AspectJExpressionPointcut; 40 import org.springframework.aop.aspectj.AspectJMethodBeforeAdvice; 41 import org.springframework.aop.aspectj.DeclareParentsAdvisor; 42 import org.springframework.aop.framework.AopConfigException; 43 import org.springframework.aop.support.DefaultPointcutAdvisor; 44 import org.springframework.core.annotation.AnnotationUtils; 45 import org.springframework.util.ReflectionUtils; 46 import org.springframework.util.StringUtils; 47 48 58 public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory { 59 60 public List <Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { 61 final Class <?> aspectClass = maaif.getAspectMetadata().getAspectClass(); 62 final String aspectName = maaif.getAspectMetadata().getAspectName(); 63 validate(aspectClass); 64 65 final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = 68 new LazySingletonAspectInstanceFactoryDecorator(maaif); 69 70 final List <Advisor> advisors = new LinkedList <Advisor>(); 71 ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() { 72 public void doWith(Method method) throws IllegalArgumentException { 73 if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { 75 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); 76 if (advisor != null) { 77 advisors.add(advisor); 78 } 79 } 80 } 81 }); 82 83 if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { 85 Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); 86 advisors.add(0, instantiationAdvisor); 87 } 88 89 for (Field field : aspectClass.getDeclaredFields()) { 91 Advisor advisor = getDeclareParentsAdvisor(field); 92 if (advisor != null) { 93 advisors.add(advisor); 94 } 95 } 96 97 return advisors; 98 } 99 100 107 private Advisor getDeclareParentsAdvisor(Field introductionField) { 108 DeclareParents declareParents = (DeclareParents) introductionField.getAnnotation(DeclareParents.class); 109 if (declareParents == null) { 110 return null; 112 } 113 114 if (DeclareParents.class.equals(declareParents.defaultImpl())) { 115 throw new IllegalStateException ("defaultImpl must be set on DeclareParents"); 118 } 119 120 return new DeclareParentsAdvisor( 121 introductionField.getType(), declareParents.value(), declareParents.defaultImpl()); 122 } 123 124 125 public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, 126 int declarationOrderInAspect, String aspectName) { 127 128 validate(aif.getAspectMetadata().getAspectClass()); 129 130 AspectJExpressionPointcut ajexp = 131 getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass()); 132 if (ajexp == null) { 133 return null; 134 } 135 return new InstantiationModelAwarePointcutAdvisorImpl( 136 this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName); 137 } 138 139 private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class <?> candidateAspectClass) { 140 AspectJAnnotation<?> aspectJAnnotation = 141 AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); 142 if (aspectJAnnotation == null) { 143 return null; 144 } 145 AspectJExpressionPointcut ajexp = 146 new AspectJExpressionPointcut(candidateAspectClass, new String [0], new Class [0]); 147 ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); 148 return ajexp; 149 } 150 151 152 public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, 153 MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { 154 155 Class <?> candidateAspectClass = aif.getAspectMetadata().getAspectClass(); 156 validate(candidateAspectClass); 157 158 AspectJAnnotation<?> aspectJAnnotation = 159 AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); 160 if (aspectJAnnotation == null) { 161 return null; 162 } 163 164 if (!isAspect(candidateAspectClass)) { 167 throw new AopConfigException("Advice must be declared inside an aspect type: " + 168 "Offending method '" + candidateAdviceMethod + "' in class [" + 169 candidateAspectClass.getName() + "]"); 170 } 171 172 if (logger.isDebugEnabled()) { 173 logger.debug("Found AspectJ method: " + candidateAdviceMethod); 174 } 175 176 AbstractAspectJAdvice springAdvice; 177 178 switch (aspectJAnnotation.getAnnotationType()) { 179 case AtBefore: 180 springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif); 181 break; 182 case AtAfter: 183 springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif); 184 break; 185 case AtAfterReturning: 186 springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif); 187 AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); 188 if (StringUtils.hasText(afterReturningAnnotation.returning())) { 189 springAdvice.setReturningName(afterReturningAnnotation.returning()); 190 } 191 break; 192 case AtAfterThrowing: 193 springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif); 194 AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); 195 if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { 196 springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); 197 } 198 break; 199 case AtAround: 200 springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif); 201 break; 202 case AtPointcut: 203 if (logger.isDebugEnabled()) { 204 logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); 205 } 206 return null; 207 default: 208 throw new UnsupportedOperationException ( 209 "Unsupported advice type on method " + candidateAdviceMethod); 210 } 211 212 springAdvice.setAspectName(aspectName); 214 springAdvice.setDeclarationOrder(declarationOrderInAspect); 215 String [] argNames = getArgumentNames(candidateAdviceMethod); 216 if (argNames != null) { 217 springAdvice.setArgumentNamesFromStringArray(argNames); 218 } 219 try { 220 springAdvice.afterPropertiesSet(); 221 } 222 catch (Exception ex) { 223 throw new IllegalArgumentException ("Advice configuration failed", ex); 224 } 225 return (Advice) springAdvice; 226 } 227 228 private String [] getArgumentNames(Method forMethod) { 229 String [] argNames = this.parameterNameDiscoverer.getParameterNames(forMethod); 230 if (argNames != null) { 231 if (forMethod.getParameterTypes().length == argNames.length + 1) { 232 Class firstArgType = forMethod.getParameterTypes()[0]; 234 if (firstArgType == JoinPoint.class || 235 firstArgType == ProceedingJoinPoint.class || 236 firstArgType == JoinPoint.StaticPart.class) { 237 String [] oldNames = argNames; 238 argNames = new String [oldNames.length + 1]; 239 argNames[0] = "THIS_JOIN_POINT"; 240 System.arraycopy(oldNames, 0, argNames, 1, oldNames.length); 241 } 242 } 243 } 244 return argNames; 245 } 246 247 248 253 protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor { 254 255 public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) { 256 super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() { 257 public void before(Method method, Object [] args, Object target) { 258 aif.getAspectInstance(); 260 } 261 }); 262 } 263 } 264 265 } 266 | Popular Tags |