Spring基于注解形式的 AOP的原理流程及源码解析(三)
2017-11-06 10:06
1001 查看
此篇博客主要讲解Spring如何验证将要实例化的Bean是否应该被代理,生成代理对象的时机问题。
在第二篇博客中,Spring对容器内所有的标识了@Aspect注解的的类的切面方法(标识了@Around, @Before, @After, @AfterReturning, @AfterThrowing的方法)生成切面Advisor,切面由切入点Pointcut和通知组成,切入点一般是ExpressionPointcut,及带表达式的切入点,由注解上的value或pointcut属性来指定;通知一般就是被织入的方法,就是注解标识的方法。
Spring代理Bean默认是singleton形式,即多个织入方法织入同一个代理对象,而不是每个方法生成一个对象。传统的AOP是每个方法生成一个代理对象。详情可查看@Aspect的value属性。如果被代理对象的scope不是singleton,则需要在value属性上指定代理的类型,比如是perTarget等。
基于注解形式的AOP的代理对象生成的时机一般是在每个Bean初始化之后,及执行BeanPostProcessor的postProcessAfterInitialization方法,可看AbstractAutoProxyCreator的方法结构。如果对象的scope非singleton,那么生成代理对象的时机肯定在postProcessAfterInitialization;如果对象的scope是singleton,那么可能在postProcessAfterInitialization,也可能在getEarlyBeanReference方法。如果被代理的Bean触发了循环引用circular references,即Bean A注入了Bean B,而B内也注入了A,那么在解析B的时候会触发A的getEarlyBeanReference方法,如果A符合被代理的条件,则会直接生产代理对象,将代理对象注入B的属性中。在这种情况下有危险,B本来想注入A,但是结果注入的是A的代理对象,此时A还是一个原始的对象,还未注入属性及执行初始化方法,所以有很大程度上会报异常。结论 : 动态代理scope = singleton时请注意避免循环引用。
接下来将生成代理对象的代码:
代码块1
验证在实例化的Bean是否应该被代理,如果应该则发挥那些符合条件的待织入切面Advisor:
代码块2
AopUtils工具类循环的将每个Advisor与BeanClass匹配,如果匹配上就方法返回的集合中,
验证步骤:
在类上做精确匹配,如果匹配规则定义在方法上,则返回maybetrue,如果规则定义在类上,不匹配则直接返回false
当类上返回的结果为true或者maybetrue,再进行方法的匹配。方法的匹配也是先做模糊匹配,如果返回的为nevermatch或者alwaysmatche,则得到了结果。
如果返回的结果不能确定为true或false,则需要根据实际的去验证,比如args(…)则验证方法的参数是否有指定的类型,@args则验证方法的参数是否标识了指定的注解
在方法上做模糊匹配的原因是一个类从父类继承,实现接口及自身的方法很多,如果能提前做一个大致的预估,如果预估的结果是肯定不匹配或不匹配,则可以省去对其所有方法的匹配解析。
代码块3
表达式形式的切入点对类的匹配验证:
代码块4
根据切面注解的value值,比如@After(“@args(….)”),生成不同实例的切入点表达式实例,即Pointcut实现类,切入点的实现类有很多,但Spring并不是每种都支持,支持的类型可以在AspectJExpressionPointcut的SUPPORTED_PRIMITIVES属性中看到。
代码块5
切入点表达式实例即PointcutExpression验证一个类是否匹配表达式,主要是根据其内部持有的Pointcut实例来匹配验证,而Pointcut实例则根据切面注解的value值如@After(“@args(…..)”)来生成相应的Pointcut实现类,以这个实现类来验证:
代码块6
在第二篇博客中,Spring对容器内所有的标识了@Aspect注解的的类的切面方法(标识了@Around, @Before, @After, @AfterReturning, @AfterThrowing的方法)生成切面Advisor,切面由切入点Pointcut和通知组成,切入点一般是ExpressionPointcut,及带表达式的切入点,由注解上的value或pointcut属性来指定;通知一般就是被织入的方法,就是注解标识的方法。
Spring代理Bean默认是singleton形式,即多个织入方法织入同一个代理对象,而不是每个方法生成一个对象。传统的AOP是每个方法生成一个代理对象。详情可查看@Aspect的value属性。如果被代理对象的scope不是singleton,则需要在value属性上指定代理的类型,比如是perTarget等。
基于注解形式的AOP的代理对象生成的时机一般是在每个Bean初始化之后,及执行BeanPostProcessor的postProcessAfterInitialization方法,可看AbstractAutoProxyCreator的方法结构。如果对象的scope非singleton,那么生成代理对象的时机肯定在postProcessAfterInitialization;如果对象的scope是singleton,那么可能在postProcessAfterInitialization,也可能在getEarlyBeanReference方法。如果被代理的Bean触发了循环引用circular references,即Bean A注入了Bean B,而B内也注入了A,那么在解析B的时候会触发A的getEarlyBeanReference方法,如果A符合被代理的条件,则会直接生产代理对象,将代理对象注入B的属性中。在这种情况下有危险,B本来想注入A,但是结果注入的是A的代理对象,此时A还是一个原始的对象,还未注入属性及执行初始化方法,所以有很大程度上会报异常。结论 : 动态代理scope = singleton时请注意避免循环引用。
接下来将生成代理对象的代码:
代码块1
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware { //如果scope = singleton的Bean触发circular references,会在此步生成代理实例,生成时机比正常的早得多 public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { this.earlyProxyReferences.add(cacheKey); } return wrapIfNecessary(bean, beanName, cacheKey); } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); //大部分的动态代理对象均在此步骤生成,此步骤是Bean实例化的最后一步 if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. //校验此类是否应该被代理,也就是将此类和所有的ExpressionPointcut匹配,匹配代码解析看下一块(代码块2) Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }
验证在实例化的Bean是否应该被代理,如果应该则发挥那些符合条件的待织入切面Advisor:
代码块2
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator { protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //获取容器中的所有切面 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //验证beanClass是否该被代理,如果应该,则返回所有符合条件的待织入切面 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 4000 extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //匹配过程,看下一块代码(代码块3) return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } }
AopUtils工具类循环的将每个Advisor与BeanClass匹配,如果匹配上就方法返回的集合中,
验证步骤:
在类上做精确匹配,如果匹配规则定义在方法上,则返回maybetrue,如果规则定义在类上,不匹配则直接返回false
当类上返回的结果为true或者maybetrue,再进行方法的匹配。方法的匹配也是先做模糊匹配,如果返回的为nevermatch或者alwaysmatche,则得到了结果。
如果返回的结果不能确定为true或false,则需要根据实际的去验证,比如args(…)则验证方法的参数是否有指定的类型,@args则验证方法的参数是否标识了指定的注解
在方法上做模糊匹配的原因是一个类从父类继承,实现接口及自身的方法很多,如果能提前做一个大致的预估,如果预估的结果是肯定不匹配或不匹配,则可以省去对其所有方法的匹配解析。
代码块3
public abstract class AopUtils { public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); for (Advisor candidate : candidateAdvisors) { //基于注解形式生成的Advisor均是PointcutAdvisor,所以条件均不符合 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; } public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; //pca.getPointcut()返回的是一个AspectJExpressionPointcut类型对象 return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); //先对类做匹配,如果结果为false则说明不匹配,代码详解看代码块4 if (!pc.getClassFilter().matches(targetClass)) { return false; } //再对方法做匹配,有些匹配规则只作用在类上,那么方法的匹配确定返回true, //很多规则是针对方法的代理,所以需要继续对合适的类里的所有方法做验证 MethodMatcher methodMatcher = pc.getMethodMatcher(); //methodMatcher 一般是AspectJExpressionPointcut对象自身,所有此步不符合 if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { //获取类所实现的所有接口和所有类层级的方法,循环验证 if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; } public boolean matches(Method method, Class<?> targetClass) { return matches(method, targetClass, false); } public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) { checkReadyToMatch(); Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); //getShadowMatch方法的调用繁杂,有点类似Class的匹配,最终也会调用到Pointcut的match(Shadow shadow)方法 //Pointcut对方法的匹配看下一个方法 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. //this, target, @this, @target, @annotation这些匹配规则都是匹配类的,当类的匹配通过时,方法均通过 if (shadowMatch.alwaysMatches()) { return true; } else if (shadowMatch.neverMatches()) { return false; } else { // the maybe case if (beanHasIntroductions) { return true; } //如果FuzzyBoolean 即不确定错误,也不确定是正确的,那么就需要实际的验证, //比如args(...)则验证方法的参数是否有指定的类型,@args则验证方法的参数是否标识了指定的注解 // 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)); } } public abstract class Pointcut extends PatternNode { public final FuzzyBoolean match(Shadow shadow) { if (shadow.shadowId == lastMatchedShadowId) { return lastMatchedShadowResult; } FuzzyBoolean ret; // this next test will prevent a lot of un-needed matching going on.... if (shadow.getKind().isSet(couldMatchKinds())) { //不同的Pointcut实例对此方法做了不同的实现,比如args,this,target等等, //不是实实在在的根据表达式去验证方法,而仅仅只是粗略的返回一个模糊的结果,比如可能为真,也可能为假 ret = matchInternal(shadow); } else { ret = FuzzyBoolean.NO; } lastMatchedShadowId = shadow.shadowId; lastMatchedShadowResult = ret; return ret; } } }
表达式形式的切入点对类的匹配验证:
代码块4
public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware { public boolean matches(Class<?> targetClass) { checkReadyToMatch(); //确保生成表达式解析的Context环境 try { try { //根据表达式的解析实例,验证此类是否匹配,代码解析看下一块代码(代码块6) 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 (Throwable ex) { logger.debug("PointcutExpression matching rejected target class", ex); } return false; } private void checkReadyToMatch() { if (getExpression() == null) { throw new IllegalStateException("Must set property 'expression' before attempting to match"); } if (this.pointcutExpression == null) { this.pointcutClassLoader = determinePointcutClassLoader(); //这一步很重要,根据切面注解的value属性,生成切入点表达式实例,代码解析看下一块代码(代码块5) this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader); 100f1 } } }
根据切面注解的value值,比如@After(“@args(….)”),生成不同实例的切入点表达式实例,即Pointcut实现类,切入点的实现类有很多,但Spring并不是每种都支持,支持的类型可以在AspectJExpressionPointcut的SUPPORTED_PRIMITIVES属性中看到。
代码块5
public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware { private void checkReadyToMatch() { if (getExpression() == null) { throw new IllegalStateException("Must set property 'expression' before attempting to match"); } if (this.pointcutExpression == null) { this.pointcutClassLoader = determinePointcutClassLoader(); //第一步 this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader); } } private PointcutExpression buildPointcutExpression(ClassLoader classLoader) { PointcutParser parser = initializePointcutParser(classLoader); PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length]; for (int i = 0; i < pointcutParameters.length; i++) { pointcutParameters[i] = parser.createPointcutParameter( this.pointcutParameterNames[i], this.pointcutParameterTypes[i]); } //第二步 return parser.parsePointcutExpression(replaceBooleanOperators(getExpression()), this.pointcutDeclarationScope, pointcutParameters); } } public class PointcutParser { public PointcutExpression parsePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters) throws UnsupportedPointcutPrimitiveException, IllegalArgumentException { PointcutExpressionImpl pcExpr = null; try { //第三步 Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters); pc = concretizePointcutExpression(pc, inScope, formalParameters); validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld()); } catch (ParserException pEx) { throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx)); } catch (ReflectionWorld.ReflectionWorldException rwEx) { throw new IllegalArgumentException(rwEx.getMessage()); } return pcExpr; } protected Pointcut resolvePointcutExpression(String expression, Class inScope, PointcutParameter[] formalParameters) { try { PatternParser parser = new PatternParser(expression); parser.setPointcutDesignatorHandlers(pointcutDesignators, world); Pointcut pc = parser.parsePointcut(); //第四步 validateAgainstSupportedPrimitives(pc, expression); IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters); pc = pc.resolve(resolutionScope); return pc; } catch (ParserException pEx) { throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx)); } } public Pointcut parsePointcut() { //第五步,最关键的一步 Pointcut p = parseAtomicPointcut(); if (maybeEat("&&")) { p = new AndPointcut(p, parseNotOrPointcut()); } if (maybeEat("||")) { p = new OrPointcut(p, parsePointcut()); } return p; } //根据切面注解的value属性的值上的特殊字符串,解析成不同的Pointcut的实例 private Pointcut parseAtomicPointcut() { if (maybeEat("!")) { //解析字符串以"!"开头 int startPos = tokenSource.peek(-1).getStart(); Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos); return p; } if (maybeEat("(")) { //解析value值以"("开头 Pointcut p = parsePointcut(); eat(")"); return p; } if (maybeEat("@")) { //解析value值以"@"开头 int startPos = tokenSource.peek().getStart(); Pointcut p = parseAnnotationPointcut(); int endPos = tokenSource.peek(-1).getEnd(); p.setLocation(sourceContext, startPos, endPos); return p; } int startPos = tokenSource.peek().getStart(); Pointcut p = parseSinglePointcut(); //如果均不是 int endPos = tokenSource.peek(-1).getEnd(); p.setLocation(sourceContext, startPos, endPos); return p; } //解析value值以"@"开头 public Pointcut parseAnnotationPointcut() { int start = tokenSource.getIndex(); IToken t = tokenSource.peek(); String kind = parseIdentifier(); IToken possibleTypeVariableToken = tokenSource.peek(); String[] typeVariables = maybeParseSimpleTypeVariableList(); if (typeVariables != null) { String message = "("; assertNoTypeVariables(typeVariables, message, possibleTypeVariableToken); } tokenSource.setIndex(start); if (kind.equals("annotation")) { return parseAtAnnotationPointcut(); } else if (kind.equals("args")) { return parseArgsAnnotationPointcut(); } else if (kind.equals("this") || kind.equals("target")) { return parseThisOrTargetAnnotationPointcut(); } else if (kind.equals("within")) { return parseWithinAnnotationPointcut(); } else if (kind.equals("withincode")) { return parseWithinCodeAnnotationPointcut(); } throw new ParserException("pointcut name", t); } //解析普通的单例的切入点实例 public Pointcut parseSinglePointcut() { int start = tokenSource.getIndex(); IToken t = tokenSource.peek(); Pointcut p = t.maybeGetParsedPointcut(); if (p != null) { tokenSource.next(); return p; } String kind = parseIdentifier(); // IToken possibleTypeVariableToken = tokenSource.peek(); // String[] typeVariables = maybeParseSimpleTypeVariableList(); if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) { p = parseKindedPointcut(kind); } else if (kind.equals("args")) { p = parseArgsPointcut(); } else if (kind.equals("this")) { p = parseThisOrTargetPointcut(kind); } else if (kind.equals("target")) { p = parseThisOrTargetPointcut(kind); } else if (kind.equals("within")) { p = parseWithinPointcut(); } else if (kind.equals("withincode")) { p = parseWithinCodePointcut(); } else if (kind.equals("cflow")) { p = parseCflowPointcut(false); } else if (kind.equals("cflowbelow")) { p = parseCflowPointcut(true); } else if (kind.equals("adviceexecution")) { eat("("); eat(")"); p = new KindedPointcut(Shadow.AdviceExecution, new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY, TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY, AnnotationTypePattern.ANY)); } else if (kind.equals("handler")) { eat("("); TypePattern typePat = parseTypePattern(false, false); eat(")"); p = new HandlerPointcut(typePat); } else if (kind.equals("lock") || kind.equals("unlock")) { p = parseMonitorPointcut(kind); } else if (kind.equals("initialization")) { eat("("); SignaturePattern sig = parseConstructorSignaturePattern(); eat(")"); p = new KindedPointcut(Shadow.Initialization, sig); } else if (kind.equals("staticinitialization")) { eat("("); TypePattern typePat = parseTypePattern(false, false); eat(")"); p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, ThrowsPattern.ANY, AnnotationTypePattern.ANY)); } else if (kind.equals("preinitialization")) { eat("("); SignaturePattern sig = parseConstructorSignaturePattern(); eat(")"); p = new KindedPointcut(Shadow.PreInitialization, sig); } else if (kind.equals("if")) { // - annotation style only allows if(), if(true) or if(false) // - if() means the body of the annotated method represents the if expression // - anything else is an error because code cannot be put into the if() // - code style will already have been processed and the call to maybeGetParsedPointcut() // at the top of this method will have succeeded. eat("("); if (maybeEatIdentifier("true")) { eat(")"); p = new IfPointcut.IfTruePointcut(); } else if (maybeEatIdentifier("false")) { eat(")"); p = new IfPointcut.IfFalsePointcut(); } else { if (!maybeEat(")")) { throw new ParserException( "in annotation style, if(...) pointcuts cannot contain code. Use if() and put the code in the annotated method", t); } // TODO - Alex has some token stuff going on here to get a readable name in place of ""... p = new IfPointcut(""); } } else { boolean matchedByExtensionDesignator = false; // see if a registered handler wants to parse it, otherwise // treat as a reference pointcut for (PointcutDesignatorHandler pcd : pointcutDesignatorHandlers) { if (pcd.getDesignatorName().equals(kind)) { p = parseDesignatorPointcut(pcd); matchedByExtensionDesignator = true; } } if (!matchedByExtensionDesignator) { tokenSource.setIndex(start); p = parseReferencePointcut(); } } return p; } }
切入点表达式实例即PointcutExpression验证一个类是否匹配表达式,主要是根据其内部持有的Pointcut实例来匹配验证,而Pointcut实例则根据切面注解的value值如@After(“@args(…..)”)来生成相应的Pointcut实现类,以这个实现类来验证:
代码块6
public class PointcutExpressionImpl implements PointcutExpression { private Pointcut pointcut; private String expression; public boolean couldMatchJoinPointsInType(Class aClass) { ResolvedType matchType = world.resolve(aClass.getName()); if (matchType.isMissing() && (world instanceof ReflectionWorld)) { // Class is a generated class that cannot be 'looked up' via getResource. // For example a proxy or lambda. // Use the class itself in this case matchType = ((ReflectionWorld)world).resolveUsingClass(aClass); } ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world); //关键看这步,不同的实现类返回不同的值,maybeTrue代表是可能为真,比如很多适配的原则是在方法上的,那么这步就会返回true //有些规则是要在类上做匹配的,则会在此步骤做验证,通过后在方法上的验证直接返回true boolean couldMatch = pointcut.fastMatch(info).maybeTrue(); if (MATCH_INFO) { System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': " + couldMatch); } return couldMatch; } }
相关文章推荐
- Spring基于注解形式的 AOP的原理流程及源码解析(一)
- Spring基于注解形式的 AOP的原理流程及源码解析(二)
- Spring基于注解形式的 AOP的原理流程及源码解析(四)
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- 深入剖析Spring Web源码(九) - 处理器映射,处理器适配器以及处理器的实现 - 基于注解控制器流程的实现
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- spring AOP 源码解析 及其实现原理
- Spring核心框架 - AOP的原理及源码解析
- Spring AOP源码解析——AOP动态代理原理和实现方式
- Spring IOC和Spring AOP的实现原理(源码主线流程)
- Spring源码解析之四 ------ AOP原理和源码分析
- Spring核心框架 - AOP的原理及源码解析
- (八)Spring核心框架 - AOP的原理及源码解析
- Spring源码解析-基于注解依赖注入
- spring源码解析-AOP原理
- 【Spring源码分析】AOP源码解析(下篇)
- Spring中基于注解的AOP
- 深入理解Spring 之 源码剖析AOP(注解方式)
- SpringAop的注解形式