@Override public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) { checkReadyToMatch(); Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); ShadowMatch shadowMatch = getShadowMatch(targetMethod, method); // Special handling for this, target, @this, @target, @annotation // in Spring - we can optimize since we know we have exactly this class, // and there will never be matching subclass at runtime. if (shadowMatch.alwaysMatches()) { return true; } else if (shadowMatch.neverMatches()) { return false; } else { // the maybe case if (beanHasIntroductions) { return true; } // A match test returned maybe - if there are any subtype sensitive variables // involved in the test (this, target, at_this, at_target, at_annotation) then // we say this is not a match as in Spring there will never be a different // runtime subtype. RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch); return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass)); } }
@Override public boolean matches(Class<?> targetClass) { checkReadyToMatch(); try { try { return this.pointcutExpression.couldMatchJoinPointsInType(targetClass); } catch (ReflectionWorldException ex) { logger.debug( "PointcutExpression matching rejected target class - trying fallback expression", ex); // Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough // yet PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass); if (fallbackExpression != null) { return fallbackExpression.couldMatchJoinPointsInType(targetClass); } } } catch (BCException ex) { logger.debug("PointcutExpression matching rejected target class", ex); } return false; }
@Override public boolean matches(Method method, Class<?> targetClass, Object[] args) { checkReadyToMatch(); ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method); ShadowMatch originalShadowMatch = getShadowMatch(method, method); // Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target, // consistent with return of MethodInvocationProceedingJoinPoint ProxyMethodInvocation pmi = null; Object targetObject = null; Object thisObject = null; try { MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation(); targetObject = mi.getThis(); if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException( "MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); } pmi = (ProxyMethodInvocation) mi; thisObject = pmi.getProxy(); } catch (IllegalStateException ex) { // No current invocation... // TODO: Should we really proceed here? if (logger.isDebugEnabled()) { logger.debug("Could not access current invocation - matching with limited context: " + ex); } } try { JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args); /* * Do a final check to see if any this(TYPE) kind of residue match. For * this purpose, we use the original method's (proxy method's) shadow to * ensure that 'this' is correctly checked against. Without this check, * we get incorrect match on this(TYPE) where TYPE matches the target * type but not 'this' (as would be the case of JDK dynamic proxies). * <p>See SPR-2979 for the original bug. */ if (pmi != null) { // there is a current invocation RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch); if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) { return false; } if (joinPointMatch.matches()) { bindParameters(pmi, joinPointMatch); } } return joinPointMatch.matches(); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Failed to evaluate join point for arguments " + Arrays.asList(args) + " - falling back to non-match", ex); } return false; } }
@Override public boolean isRuntime() { checkReadyToMatch(); return this.pointcutExpression.mayNeedDynamicTest(); }
/** Return the underlying AspectJ pointcut expression. */ public PointcutExpression getPointcutExpression() { checkReadyToMatch(); return this.pointcutExpression; }
@Override public MethodMatcher getMethodMatcher() { checkReadyToMatch(); return this; }
@Override public ClassFilter getClassFilter() { checkReadyToMatch(); return this; }