当前位置:   article > 正文

Spring Aop 匹配源码解析_springaop 源码解析 (一) - aspect 切面方法的查找匹配过程

springaop 源码解析 (一) - aspect 切面方法的查找匹配过程

一、前言

AOP(Aspect Oriented Programming)称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。

AOP的相关概念:

(1)横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
(2)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(3)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用。被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
(4)Advice(通知):AOP在特定的切入点上执行的增强处理,有before(前置),after(后置),afterReturning(最终),afterThrowing(异常),around(环绕)
(5)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(6)weave(织入):将切面应用到目标对象并导致代理对象创建的过程
(7)introduction(引入):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
(8)AOP代理(AOP Proxy):AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
(9)目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO

二、源码解析

下面针对Spring Boot的AOP使用进行源码解析。Spring Boot 添加pom引入

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. <version>2.0.2.RELEASE</version>
  5. </dependency>

之后我们创建切面类

  1. @Aspect
  2. @Component
  3. @EnableAspectJAutoProxy
  4. public class ServiceAdvice {
  5. @Pointcut("@annotation(aoptest.Monitor)")
  6. public void annotation() {
  7. }
  8. @Pointcut("execution(public * aoptest.*.*(..))")
  9. public void webLog(){}
  10. @Before("webLog()")
  11. public void beforeMethodAdviceA(JoinPoint joinPoint){
  12. System.out.println("beforeMethodAdviceA");
  13. }
  14. @Before("annotation()")
  15. public void beforeMethodAdviceAnnotation(JoinPoint joinPoint){
  16. System.out.println("AdviceAnnotation");
  17. }
  18. @Before("annotation()")
  19. public void beforeMethodAdviceAnnotation2(JoinPoint joinPoint){
  20. System.out.println("AdviceAnnotation2");
  21. }
  22. @After("webLog()")
  23. public void afterMethodAdviceB(JoinPoint joinPoint){
  24. System.out.println("afterMethodAdviceB");
  25. }
  26. }

这样就会在对应的方法执行前,进行增强处理了。

首先进入@EnableAspectJAutoProxy注解。

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(AspectJAutoProxyRegistrar.class)
  5. public @interface EnableAspectJAutoProxy {
  6. //导入了AspectJAutoProxyRegistrar
  7. }

导入了AspectJAutoProxyRegistrar类。

  1. class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  2. public void registerBeanDefinitions(
  3. AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  4. AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  5. .........................
  6. }
  7. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
  8. return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  9. }
  10. public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
  11. BeanDefinitionRegistry registry, @Nullable Object source) {
  12. return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  13. }

通过AspectJAutoProxyRegistrar类导入了AnnotationAwareAspectJAutoProxyCreator对象。AnnotationAwareAspectJAutoProxyCreator对象实现了BeanPostProcessor接口。

在创建Bean对象的时候会执行AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization方法。

  1. public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
  2. if (bean != null) {
  3. Object cacheKey = getCacheKey(bean.getClass(), beanName);
  4. if (this.earlyProxyReferences.remove(cacheKey) != bean) {
  5. return wrapIfNecessary(bean, beanName, cacheKey);
  6. }
  7. }
  8. return bean;
  9. }
  10. protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  11. if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
  12. return bean;
  13. }
  14. if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
  15. return bean;
  16. }
  17. if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
  18. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  19. return bean;
  20. }
  21. // Create proxy if we have advice.
  22. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  23. if (specificInterceptors != DO_NOT_PROXY) {
  24. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  25. Object proxy = createProxy(
  26. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  27. this.proxyTypes.put(cacheKey, proxy.getClass());
  28. return proxy;
  29. }
  30. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  31. return bean;
  32. }

getAdvicesAndAdvisorsForBean方法用于查找增强的方法和该Bean是否需要AOP处理。

  1. protected Object[] getAdvicesAndAdvisorsForBean(
  2. Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
  3. //找到增强集合
  4. List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  5. if (advisors.isEmpty()) {
  6. return DO_NOT_PROXY;
  7. }
  8. return advisors.toArray();
  9. }
  1. protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  2. //找到实现了Advisor接口的类和标有@Aspect注解的类
  3. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  4. //判断当前的Bean是否有方法适配AOP
  5. List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  6. extendAdvisors(eligibleAdvisors);
  7. if (!eligibleAdvisors.isEmpty()) {
  8. eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  9. }
  10. return eligibleAdvisors;
  11. }
  12. protected List<Advisor> findCandidateAdvisors() {
  13. // 找到所有实现Advisor接口的类
  14. List<Advisor> advisors = super.findCandidateAdvisors();
  15. // Build Advisors for all AspectJ aspects in the bean factory.
  16. if (this.aspectJAdvisorsBuilder != null) {
  17. //找到所有标有@Aspect的类
  18. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  19. }
  20. return advisors;
  21. }
  22. public List<Advisor> buildAspectJAdvisors() {
  23. .......................
  24. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  25. this.beanFactory, Object.class, true, false);
  26. ...............
  27. if (this.advisorFactory.isAspect(beanType)) {
  28. ...........................
  29. //此方法将@Aspect类中的包含Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的增强方法找到
  30. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  31. ...........
  32. }
  33. }

//判断当前的Bean是否有方法适配AOP
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

  1. protected List<Advisor> findAdvisorsThatCanApply(
  2. List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
  3. ProxyCreationContext.setCurrentProxiedBeanName(beanName);
  4. try {
  5. return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
  6. }
  7. finally {
  8. ProxyCreationContext.setCurrentProxiedBeanName(null);
  9. }
  10. }
  11. public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
  12. if (candidateAdvisors.isEmpty()) {
  13. return candidateAdvisors;
  14. }
  15. List<Advisor> eligibleAdvisors = new ArrayList<>();
  16. for (Advisor candidate : candidateAdvisors) {
  17. if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
  18. eligibleAdvisors.add(candidate);
  19. }
  20. }
  21. boolean hasIntroductions = !eligibleAdvisors.isEmpty();
  22. for (Advisor candidate : candidateAdvisors) {
  23. if (candidate instanceof IntroductionAdvisor) {
  24. // already processed
  25. continue;
  26. }
  27. //判断是否适配
  28. if (canApply(candidate, clazz, hasIntroductions)) {
  29. eligibleAdvisors.add(candidate);
  30. }
  31. }
  32. return eligibleAdvisors;
  33. }
  1. public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
  2. if (advisor instanceof IntroductionAdvisor) {
  3. return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
  4. }
  5. else if (advisor instanceof PointcutAdvisor) {
  6. PointcutAdvisor pca = (PointcutAdvisor) advisor;
  7. return canApply(pca.getPointcut(), targetClass, hasIntroductions);
  8. }
  9. else {
  10. // It doesn't have a pointcut so we assume it applies.
  11. return true;
  12. }
  13. }
  14. public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
  15. Assert.notNull(pc, "Pointcut must not be null");
  16. if (!pc.getClassFilter().matches(targetClass)) {
  17. return false;
  18. }
  19. MethodMatcher methodMatcher = pc.getMethodMatcher();
  20. if (methodMatcher == MethodMatcher.TRUE) {
  21. // No need to iterate the methods if we're matching any method anyway...
  22. return true;
  23. }
  24. IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
  25. if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
  26. introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
  27. }
  28. Set<Class<?>> classes = new LinkedHashSet<>();
  29. if (!Proxy.isProxyClass(targetClass)) {
  30. classes.add(ClassUtils.getUserClass(targetClass));
  31. }
  32. classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
  33. for (Class<?> clazz : classes) {
  34. Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
  35. for (Method method : methods) {
  36. if (introductionAwareMethodMatcher != null ?
  37. //判断当前类是否有方法适配当前adviors
  38. introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
  39. methodMatcher.matches(method, targetClass)) {
  40. return true;
  41. }
  42. }
  43. }
  44. return false;
  45. }

canApply方法中,pc.getClassFilter().matches(targetClass)方法会进行一次快速匹配(只看类是否匹配)。会调用PointcutExpressionImpl类的couldMatchJoinPointsInType方法。

  1. public boolean couldMatchJoinPointsInType(Class aClass) {
  2. ResolvedType matchType = world.resolve(aClass.getName());
  3. if (matchType.isMissing() && (world instanceof ReflectionWorld)) {
  4. // Class is a generated class that cannot be 'looked up' via getResource.
  5. // For example a proxy or lambda.
  6. // Use the class itself in this case
  7. matchType = ((ReflectionWorld)world).resolveUsingClass(aClass);
  8. }
  9. ReflectionFastMatchInfo info = new ReflectionFastMatchInfo(matchType, null, this.matchContext, world);
  10. boolean couldMatch = pointcut.fastMatch(info).maybeTrue();
  11. if (MATCH_INFO) {
  12. System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': "
  13. + couldMatch);
  14. }
  15. return couldMatch;
  16. }

通过具体的pointcut调用fastMatch方法。例如AnnotationPointcut会判断方法是否有对应注解,通常采用最多的execution表达式的则会进入KindedPointcut的fastMatch方法。

方法会先对@Pointcut进行解析,看是适配接口还是适配为实体类。判断Bean对象是否适配,表达式如果不适配,有两种情况:

1、如果切点为实体类,则先判断Bean类是否与切点类相同,如不同,则会看父类是否适配。

2、如果切点为接口,则先判断Bean类是否与切点类相同,如不同,则看接口类是否为切面适配的类。

也就是说,如果一个子类A,父类SuperA,如果切点定义的是父类A @Pointcut("execution(public * aoptest.SuperA.*(..))"),这时切点调用的是子类A的任意方法,那么也会进行AOP增强。

进入匹配方法

  1. public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
  2. obtainPointcutExpression();
  3. ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
  4. if (shadowMatch.alwaysMatches()) {
  5. return true;
  6. }
  7. else if (shadowMatch.neverMatches()) {
  8. return false;
  9. }
  10. else {
  11. // the maybe case
  12. if (hasIntroductions) {
  13. return true;
  14. }
  15. RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
  16. return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
  17. }
  18. }

obtainPointcutExpression方法用于获取切点对应的解析类。

  1. private PointcutExpression obtainPointcutExpression() {
  2. if (getExpression() == null) {
  3. throw new IllegalStateException("Must set property 'expression' before attempting to match");
  4. }
  5. if (this.pointcutExpression == null) {
  6. this.pointcutClassLoader = determinePointcutClassLoader();
  7. this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
  8. }
  9. return this.pointcutExpression;
  10. }
  1. private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
  2. PointcutParser parser = initializePointcutParser(classLoader);
  3. PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
  4. for (int i = 0; i < pointcutParameters.length; i++) {
  5. pointcutParameters[i] = parser.createPointcutParameter(
  6. this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
  7. }
  8. return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
  9. this.pointcutDeclarationScope, pointcutParameters);
  10. }

initializePointcutParser初始化切点类解析对象

  1. private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
  2. PointcutParser parser = PointcutParser
  3. .getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
  4. SUPPORTED_PRIMITIVES, classLoader);
  5. parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
  6. return parser;
  7. }
  8. //其中SUPPORTED_PRIMITIVES包含各种pointcut类型,如EXECUTION、annotation等
  9. private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
  10. static {
  11. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
  12. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
  13. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
  14. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
  15. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
  16. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
  17. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
  18. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
  19. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
  20. SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
  21. }

parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()), this.pointcutDeclarationScope, pointcutParameters)用于创建当前adviors对应的PointCut解析类。

  1. public PointcutExpression parsePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters)
  2. throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
  3. PointcutExpressionImpl pcExpr = null;
  4. try {
  5. //解析切点表达式,用于创建对应的PointCut解析类
  6. Pointcut pc = resolvePointcutExpression(expression, inScope, formalParameters);
  7. pc = concretizePointcutExpression(pc, inScope, formalParameters);
  8. validateAgainstSupportedPrimitives(pc, expression); // again, because we have now followed any ref'd pcuts
  9. pcExpr = new PointcutExpressionImpl(pc, expression, formalParameters, getWorld());
  10. } catch (ParserException pEx) {
  11. throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
  12. } catch (ReflectionWorld.ReflectionWorldException rwEx) {
  13. throw new IllegalArgumentException(rwEx.getMessage());
  14. }
  15. return pcExpr;
  16. }
  1. protected Pointcut resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) {
  2. try {
  3. PatternParser parser = new PatternParser(expression);
  4. parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
  5. //创建PointCut实现类
  6. Pointcut pc = parser.parsePointcut(); // more correctly: parsePointcut(true)
  7. validateAgainstSupportedPrimitives(pc, expression);
  8. IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
  9. pc = pc.resolve(resolutionScope);
  10. return pc;
  11. } catch (ParserException pEx) {
  12. throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
  13. }
  14. }

通过parser.parsePointcut()创建PointCut实现类

  1. public Pointcut parsePointcut() {
  2. Pointcut p = parseAtomicPointcut();
  3. if (maybeEat("&&")) {
  4. p = new AndPointcut(p, parseNotOrPointcut());
  5. }
  6. if (maybeEat("||")) {
  7. p = new OrPointcut(p, parsePointcut());
  8. }
  9. return p;
  10. }
  11. private Pointcut parseAtomicPointcut() {
  12. if (maybeEat("!")) {
  13. int startPos = tokenSource.peek(-1).getStart();
  14. Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
  15. return p;
  16. }
  17. if (maybeEat("(")) {
  18. Pointcut p = parsePointcut();
  19. eat(")");
  20. return p;
  21. }
  22. //如果Adviors的表达式是@开头,则创建AnnotationPointcut类
  23. if (maybeEat("@")) {
  24. int startPos = tokenSource.peek().getStart();
  25. Pointcut p = parseAnnotationPointcut();
  26. int endPos = tokenSource.peek(-1).getEnd();
  27. p.setLocation(sourceContext, startPos, endPos);
  28. return p;
  29. }
  30. int startPos = tokenSource.peek().getStart();
  31. //之前实例类创建的是 @Before("annotation()") 和 @Before("webLog()")会进入parseSinglePointcut方法寻找
  32. Pointcut p = parseSinglePointcut();
  33. int endPos = tokenSource.peek(-1).getEnd();
  34. p.setLocation(sourceContext, startPos, endPos);
  35. return p;
  36. }
  37. public Pointcut parseSinglePointcut() {
  38. int start = tokenSource.getIndex();
  39. IToken t = tokenSource.peek();
  40. Pointcut p = t.maybeGetParsedPointcut();
  41. if (p != null) {
  42. tokenSource.next();
  43. return p;
  44. }
  45. String kind = parseIdentifier();
  46. //这里也没有适配的,我们传入的是annotation() 和 webLog()
  47. if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) {
  48. p = parseKindedPointcut(kind);
  49. } else if (kind.equals("args")) {
  50. p = parseArgsPointcut();
  51. } else if (kind.equals("this")) {
  52. p = parseThisOrTargetPointcut(kind);
  53. } else if (kind.equals("target")) {
  54. p = parseThisOrTargetPointcut(kind);
  55. } else if (kind.equals("within")) {
  56. p = parseWithinPointcut();
  57. } else if (kind.equals("withincode")) {
  58. p = parseWithinCodePointcut();
  59. } else if (kind.equals("cflow")) {
  60. p = parseCflowPointcut(false);
  61. } else if (kind.equals("cflowbelow")) {
  62. p = parseCflowPointcut(true);
  63. } else if (kind.equals("adviceexecution")) {
  64. eat("(");
  65. eat(")");
  66. p = new KindedPointcut(Shadow.AdviceExecution, new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY,
  67. TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, ThrowsPattern.ANY,
  68. AnnotationTypePattern.ANY));
  69. } else if (kind.equals("handler")) {
  70. eat("(");
  71. TypePattern typePat = parseTypePattern(false, false);
  72. eat(")");
  73. p = new HandlerPointcut(typePat);
  74. } else if (kind.equals("lock") || kind.equals("unlock")) {
  75. p = parseMonitorPointcut(kind);
  76. } else if (kind.equals("initialization")) {
  77. eat("(");
  78. SignaturePattern sig = parseConstructorSignaturePattern();
  79. eat(")");
  80. p = new KindedPointcut(Shadow.Initialization, sig);
  81. } else if (kind.equals("staticinitialization")) {
  82. eat("(");
  83. TypePattern typePat = parseTypePattern(false, false);
  84. eat(")");
  85. p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION,
  86. ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, ThrowsPattern.ANY,
  87. AnnotationTypePattern.ANY));
  88. } else if (kind.equals("preinitialization")) {
  89. eat("(");
  90. SignaturePattern sig = parseConstructorSignaturePattern();
  91. eat(")");
  92. p = new KindedPointcut(Shadow.PreInitialization, sig);
  93. } else if (kind.equals("if")) {
  94. // - annotation style only allows if(), if(true) or if(false)
  95. // - if() means the body of the annotated method represents the if expression
  96. // - anything else is an error because code cannot be put into the if()
  97. // - code style will already have been processed and the call to maybeGetParsedPointcut()
  98. // at the top of this method will have succeeded.
  99. eat("(");
  100. if (maybeEatIdentifier("true")) {
  101. eat(")");
  102. p = new IfPointcut.IfTruePointcut();
  103. } else if (maybeEatIdentifier("false")) {
  104. eat(")");
  105. p = new IfPointcut.IfFalsePointcut();
  106. } else {
  107. if (!maybeEat(")")) {
  108. throw new ParserException(
  109. "in annotation style, if(...) pointcuts cannot contain code. Use if() and put the code in the annotated method",
  110. t);
  111. }
  112. // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
  113. p = new IfPointcut("");
  114. }
  115. } else {
  116. boolean matchedByExtensionDesignator = false;
  117. // see if a registered handler wants to parse it, otherwise
  118. // treat as a reference pointcut
  119. for (PointcutDesignatorHandler pcd : pointcutDesignatorHandlers) {
  120. if (pcd.getDesignatorName().equals(kind)) {
  121. p = parseDesignatorPointcut(pcd);
  122. matchedByExtensionDesignator = true;
  123. }
  124. }
  125. if (!matchedByExtensionDesignator) {
  126. tokenSource.setIndex(start);
  127. //annotation() 和 webLog() 会进入这里
  128. p = parseReferencePointcut();
  129. }
  130. }
  131. return p;
  132. }

由于我们的Adviors创建的都是@Before("webLog()")和@Before("annotation()"),所以会走到最后parseReferencePointcut创建引用类型的PointCut。

继续回到之前的resolvePointcutExpression方法

  1. protected Pointcut resolvePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters) {
  2. try {
  3. PatternParser parser = new PatternParser(expression);
  4. parser.setPointcutDesignatorHandlers(pointcutDesignators, world);
  5. //创建完ReferencePointcut类后
  6. Pointcut pc = parser.parsePointcut(); // more correctly: parsePointcut(true)
  7. validateAgainstSupportedPrimitives(pc, expression);
  8. IScope resolutionScope = buildResolutionScope((inScope == null ? Object.class : inScope), formalParameters);
  9. //这里会解析ReferencePointcut这正的对应@PointCut的方法,找到真正的Pointcut解析类
  10. pc = pc.resolve(resolutionScope);
  11. return pc;
  12. } catch (ParserException pEx) {
  13. throw new IllegalArgumentException(buildUserMessageFromParserException(expression, pEx));
  14. }
  15. }

这里会解析ReferencePointcut这正的对应@PointCut的方法,找到真正的Pointcut解析类。

  1. public final Pointcut resolve(IScope scope) {
  2. assertState(SYMBOLIC);
  3. Bindings bindingTable = new Bindings(scope.getFormalCount());
  4. IScope bindingResolutionScope = scope;
  5. if (typeVariablesInScope.length > 0) {
  6. bindingResolutionScope = new ScopeWithTypeVariables(typeVariablesInScope, scope);
  7. }
  8. //根据引用切点方法名称,找到对应的point里真正的要创建的PointCut
  9. this.resolveBindings(bindingResolutionScope, bindingTable);
  10. bindingTable.checkAllBound(bindingResolutionScope);
  11. this.state = RESOLVED;
  12. return this;
  13. }
  14. public void resolveBindings(IScope scope, Bindings bindings) {
  15. //找到对应名字的pointCut
  16. ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
  17. ............
  18. }
  19. public ResolvedPointcutDefinition findPointcut(String name) {
  20. for (Iterator<ResolvedMember> i = getPointcuts(); i.hasNext();) {
  21. ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
  22. // the ResolvedPointcutDefinition can be null if there are other problems that prevented its resolution
  23. if (f != null && name.equals(f.getName())) {
  24. return f;
  25. }
  26. }
  27. }
  28. //getPointcuts()方法会调用PointcutGetter.get 方法,会调用getDeclaredPointcuts()
  29. private static class PointcutGetter implements Iterators.Getter<ResolvedType, ResolvedMember> {
  30. @Override
  31. public Iterator<ResolvedMember> get(ResolvedType o) {
  32. return Iterators.array(o.getDeclaredPointcuts());
  33. }
  34. }

会调用Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts方法。

  1. public ResolvedMember[] getDeclaredPointcuts() {
  2. if (pointcuts == null) {
  3. Pointcut[] pcs = this.myType.getDeclaredPointcuts();
  4. ......
  5. }
  6. for (int i = 0; i < pcs.length; i++) {
  7. String pcExpr = pcs[i].getPointcutExpression().toString();
  8. org.aspectj.weaver.patterns.Pointcut pc = parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]);
  9. ((ResolvedPointcutDefinition) pointcuts[i]).setParameterNames(pnames);
  10. ((ResolvedPointcutDefinition) pointcuts[i]).setPointcut(pc);
  11. }
  12. }
  13. public Pointcut[] getDeclaredPointcuts() {
  14. if (declaredPointcuts != null) return declaredPointcuts;
  15. List<Pointcut> pointcuts = new ArrayList<Pointcut>();
  16. Method[] methods = clazz.getDeclaredMethods();
  17. for (Method method : methods) {
  18. Pointcut pc = asPointcut(method);
  19. if (pc != null) pointcuts.add(pc);
  20. }
  21. Pointcut[] ret = new Pointcut[pointcuts.size()];
  22. pointcuts.toArray(ret);
  23. declaredPointcuts = ret;
  24. return ret;
  25. }
  26. private Pointcut asPointcut(Method method) {
  27. org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
  28. if (pcAnn != null) {
  29. String name = method.getName();
  30. if (name.startsWith(ajcMagic)) {
  31. // extract real name
  32. int nameStart = name.indexOf("$$");
  33. name = name.substring(nameStart +2,name.length());
  34. int nextDollar = name.indexOf("$");
  35. if (nextDollar != -1) name = name.substring(0,nextDollar);
  36. }
  37. return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
  38. } else {
  39. return null;
  40. }
  41. }

通过Java15ReflectionBasedReferenceTypeDelegate找到Adviors方法所对应的Aspect类中有@Pointcut注解的方法。之后对这些方法再次执行parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]),进行解析。创建这正对应的PointCut类。

继续回到匹配方法

  1. public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
  2. obtainPointcutExpression();
  3. ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
  4. if (shadowMatch.alwaysMatches()) {
  5. return true;
  6. }
  7. else if (shadowMatch.neverMatches()) {
  8. return false;
  9. }
  10. else {
  11. // the maybe case
  12. if (hasIntroductions) {
  13. return true;
  14. }
  15. RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
  16. return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
  17. }
  18. }

执行getTargetShadowMatch方法。该方法的作用主要是用来判断该Bean是否有方法匹配这些Adviors。

  1. private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
  2. ..............
  3. try {
  4. shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
  5. }
  6. }
  7. public ShadowMatch matchesMethodExecution(Method aMethod) {
  8. ShadowMatch match = matchesExecution(aMethod);
  9. if (MATCH_INFO && match.maybeMatches()) {
  10. System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
  11. + (match.alwaysMatches() ? "YES" : "MAYBE"));
  12. }
  13. return match;
  14. }
  15. private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
  16. //之前创建的对应PointCut进行匹配判断
  17. org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
  18. Test residueTest = Literal.TRUE;
  19. ExposedState state = getExposedState();
  20. if (match.maybeTrue()) {
  21. residueTest = pointcut.findResidue(forShadow, state);
  22. }
  23. ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);
  24. sm.setMatchingContext(this.matchContext);
  25. return sm;
  26. }

进入匹配方法matchInternal

  1. public final FuzzyBoolean match(Shadow shadow) {
  2. if (shadow.shadowId == lastMatchedShadowId) {
  3. return lastMatchedShadowResult;
  4. }
  5. FuzzyBoolean ret;
  6. // this next test will prevent a lot of un-needed matching going on....
  7. if (shadow.getKind().isSet(couldMatchKinds())) {
  8. ret = matchInternal(shadow);
  9. } else {
  10. ret = FuzzyBoolean.NO;
  11. }
  12. lastMatchedShadowId = shadow.shadowId;
  13. lastMatchedShadowResult = ret;
  14. return ret;
  15. }

这里以@annotation注解为例,其余的类似。

  1. protected FuzzyBoolean matchInternal(Shadow shadow) {
  2. AnnotatedElement toMatchAgainst = null;
  3. Member member = shadow.getSignature();
  4. ResolvedMember rMember = member.resolve(shadow.getIWorld());
  5. ...................
  6. annotationTypePattern.resolve(shadow.getIWorld());
  7. return annotationTypePattern.matches(toMatchAgainst);
  8. }
  9. public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
  10. if (!isForParameterAnnotationMatch()) {
  11. boolean checkSupers = false;
  12. if (getResolvedAnnotationType().isInheritedAnnotation()) {
  13. if (annotated instanceof ResolvedType) {
  14. checkSupers = true;
  15. }
  16. }
  17. if (annotated.hasAnnotation(annotationType)) {
  18. if (annotationType instanceof ReferenceType) {
  19. ReferenceType rt = (ReferenceType) annotationType;
  20. if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
  21. rt.getWorld()
  22. .getMessageHandler()
  23. .handleMessage(
  24. MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
  25. annotationType, annotated), getSourceLocation()));
  26. return FuzzyBoolean.NO;
  27. }
  28. }
  29. ................
  30. }

会调用ExactAnnotationTypePattern.matches方法,就是判断注解和方法上的注解是否一致,如果一样,则该方法需要进行AOP增强。

  1. public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
  2. for (Class<?> clazz : classes) {
  3. Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
  4. for (Method method : methods) {
  5. if (introductionAwareMethodMatcher != null ?
  6. introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
  7. methodMatcher.matches(method, targetClass)) {
  8. return true;
  9. }
  10. }
  11. }
  12. return false;
  13. }

由canApply可知,如果一个Bean中的任何一个方法满足了Advoirs,那么直接返回true。这是因为即使有一个方法匹配成功,该类也需要创建动态代理,所以该Bean中的其他方法暂时就没必要在循环判断了。

在postProcessAfterInitialization方法中

  1. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  2. if (specificInterceptors != DO_NOT_PROXY) {
  3. this.advisedBeans.put(cacheKey, Boolean.TRUE);
  4. Object proxy = createProxy(
  5. bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
  6. this.proxyTypes.put(cacheKey, proxy.getClass());
  7. return proxy;
  8. }

通过createProxy创建的动态代理,会再次判断具体方法是否适配Adviors,并放到缓存中。

  1. protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
  2. @Nullable Object[] specificInterceptors, TargetSource targetSource) {
  3. if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
  4. AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
  5. }
  6. ProxyFactory proxyFactory = new ProxyFactory();
  7. proxyFactory.copyFrom(this);
  8. if (!proxyFactory.isProxyTargetClass()) {
  9. if (shouldProxyTargetClass(beanClass, beanName)) {
  10. proxyFactory.setProxyTargetClass(true);
  11. }
  12. else {
  13. evaluateProxyInterfaces(beanClass, proxyFactory);
  14. }
  15. }
  16. Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
  17. proxyFactory.addAdvisors(advisors);
  18. proxyFactory.setTargetSource(targetSource);
  19. customizeProxyFactory(proxyFactory);
  20. proxyFactory.setFrozen(this.freezeProxy);
  21. if (advisorsPreFiltered()) {
  22. proxyFactory.setPreFiltered(true);
  23. }
  24. return proxyFactory.getProxy(getProxyClassLoader());
  25. }

创建的代理主要有JdkDynamicAopProxy和CglibAopProxy两种,以JdkDynamicAopProxy的invoke方法为例。

  1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  2. ..........................
  3. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  4. ..........................
  5. }
  6. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
  7. MethodCacheKey cacheKey = new MethodCacheKey(method);
  8. List<Object> cached = this.methodCache.get(cacheKey);
  9. if (cached == null) {
  10. cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
  11. this, method, targetClass);
  12. this.methodCache.put(cacheKey, cached);
  13. }
  14. return cached;
  15. }
  16. public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
  17. Advised config, Method method, @Nullable Class<?> targetClass) {
  18. // This is somewhat tricky... We have to process introductions first,
  19. // but we need to preserve order in the ultimate list.
  20. AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  21. Advisor[] advisors = config.getAdvisors();
  22. List<Object> interceptorList = new ArrayList<>(advisors.length);
  23. Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
  24. Boolean hasIntroductions = null;
  25. for (Advisor advisor : advisors) {
  26. if (advisor instanceof PointcutAdvisor) {
  27. // Add it conditionally.
  28. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
  29. if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
  30. MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
  31. boolean match;
  32. if (mm instanceof IntroductionAwareMethodMatcher) {
  33. if (hasIntroductions == null) {
  34. hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
  35. }
  36. match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
  37. }
  38. else {
  39. match = mm.matches(method, actualClass);
  40. }
  41. if (match) {
  42. MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
  43. if (mm.isRuntime()) {
  44. // Creating a new object instance in the getInterceptors() method
  45. // isn't a problem as we normally cache created chains.
  46. for (MethodInterceptor interceptor : interceptors) {
  47. interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
  48. }
  49. }
  50. else {
  51. interceptorList.addAll(Arrays.asList(interceptors));
  52. }
  53. }
  54. }
  55. }
  56. else if (advisor instanceof IntroductionAdvisor) {
  57. IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
  58. if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
  59. Interceptor[] interceptors = registry.getInterceptors(advisor);
  60. interceptorList.addAll(Arrays.asList(interceptors));
  61. }
  62. }
  63. else {
  64. Interceptor[] interceptors = registry.getInterceptors(advisor);
  65. interceptorList.addAll(Arrays.asList(interceptors));
  66. }
  67. }
  68. return interceptorList;
  69. }

因为之前校验的是如果该类中有任一方法符合@Apsect,则直接创建动态代理。这里判断的是具体调用方法是否需要进行增强。并把需要增加AOP的增强和对应方法,放入缓存中。

以上就是AOP匹配源码解析。

AOP匹配源码解析总结:

1、通过@EnableAspectJAutoProxy注解,导入AnnotationAwareAspectJAutoProxyCreator类,AnnotationAwareAspectJAutoProxyCreator类实现了BeanPostProcessor接口。在postProcessAfterInitialization方法中,查找包含@Apsect和实现Adviors接口的类。查找所有包含@Around,@Before,@After,@AfterReturning,@AfterThrowing的增强方法。

 

2、通过AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply方法进行匹配。匹配步骤如下:

  1)进入AspectJExpressionPointcut.matches方法进行匹配。调用AspectJExpressionPointcut.buildPointcutExpression方法创建解析表达式。首先针对@Aound,@Before,@After等引用的pointcut方法名解析,如@Before("webLog()")和@Before("annotation()")等,都会首先创建一个ReferencePointcut类。

  2)之后调用ReferencePointcut.resolveBindings方法,找到这些引用名字为webLog()和annotation()的@PointCut方法。并通过最终调用Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts方法,将找到的@PointCut进行再次解析,获得真正的Pointcut解析类。

  3)之前创建的ReferencePointcut会再次调用concretize1方法,找到真正的Pointcut解析类。之后进行匹配。

3、如果一个Bean中的任何一个方法满足了Advoirs,那么直接返回true。这是因为即使有一个方法匹配成功,该类也需要创建动态代理。

4、最后通过动态代理判断具体的调用方法是否需要进行增强。并把需要增加AOP的增强和对应方法,放入缓存中

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/988252
推荐阅读
相关标签
  

闽ICP备14008679号