Spring Aop 匹配源码解析

一、前言

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引入

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
			<version>2.0.2.RELEASE</version>
		</dependency>

之后我们创建切面类

@Aspect
@Component
@EnableAspectJAutoProxy
public class ServiceAdvice {
    @Pointcut("@annotation(aoptest.Monitor)")
    public void annotation() {
    }


    @Pointcut("execution(public * aoptest.*.*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void beforeMethodAdviceA(JoinPoint joinPoint){
        System.out.println("beforeMethodAdviceA");
    }

    @Before("annotation()")
    public void beforeMethodAdviceAnnotation(JoinPoint joinPoint){
        System.out.println("AdviceAnnotation");
    }

    @Before("annotation()")
    public void beforeMethodAdviceAnnotation2(JoinPoint joinPoint){
        System.out.println("AdviceAnnotation2");
    }

    @After("webLog()")
    public void afterMethodAdviceB(JoinPoint joinPoint){
        System.out.println("afterMethodAdviceB");
    }
}

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

首先进入@EnableAspectJAutoProxy注解。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
       //导入了AspectJAutoProxyRegistrar
}

导入了AspectJAutoProxyRegistrar类。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {


	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
            .........................
        }
        
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
	}
    	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

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

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

	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && 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.
		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;
	}

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

	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable 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) {
                //找到实现了Advisor接口的类和标有@Aspect注解的类
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
                //判断当前的Bean是否有方法适配AOP
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

	protected List<Advisor> findCandidateAdvisors() {
		// 找到所有实现Advisor接口的类
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
                //找到所有标有@Aspect的类			
                advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}
	public List<Advisor> buildAspectJAdvisors() {
            .......................
            	String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
            ...............
            	if (this.advisorFactory.isAspect(beanType)) {
                    ...........................
                       //此方法将@Aspect类中的包含Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的增强方法找到
                    	List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                    ...........
                }
        }

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

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		for (Advisor candidate : candidateAdvisors) {
			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;
			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");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		MethodMatcher methodMatcher = pc.getMethodMatcher();
		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<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
				if (introductionAwareMethodMatcher != null ?
					//判断当前类是否有方法适配当前adviors
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

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

	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);
		boolean couldMatch = pointcut.fastMatch(info).maybeTrue();
		if (MATCH_INFO) {
			System.out.println("MATCHINFO: fast match for '" + this.expression + "' against '" + aClass.getName() + "': "
					+ couldMatch);
		}
		return couldMatch;
	}

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

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

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

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

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

进入匹配方法

	public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
		obtainPointcutExpression();
		ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);

		if (shadowMatch.alwaysMatches()) {
			return true;
		}
		else if (shadowMatch.neverMatches()) {
			return false;
		}
		else {
			// the maybe case
			if (hasIntroductions) {
				return true;
			}
			RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
			return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
		}
	}

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

	private PointcutExpression obtainPointcutExpression() {
		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);
		}
		return this.pointcutExpression;
	}
	private PointcutExpression buildPointcutExpression(@Nullable 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(resolveExpression()),
				this.pointcutDeclarationScope, pointcutParameters);
	}

initializePointcutParser初始化切点类解析对象

	private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
		PointcutParser parser = PointcutParser
				.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
						SUPPORTED_PRIMITIVES, classLoader);
		parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
		return parser;
	}
        //其中SUPPORTED_PRIMITIVES包含各种pointcut类型,如EXECUTION、annotation等
    	private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();

	static {
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
		SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
	}

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

	public PointcutExpression parsePointcutExpression(String expression, Class<?> inScope, PointcutParameter[] formalParameters)
			throws UnsupportedPointcutPrimitiveException, IllegalArgumentException {
		PointcutExpressionImpl pcExpr = null;
		try {
                        //解析切点表达式,用于创建对应的PointCut解析类
			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实现类
			Pointcut pc = parser.parsePointcut(); // more correctly: parsePointcut(true)
			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));
		}
	}

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

	public Pointcut parsePointcut() {
		Pointcut p = parseAtomicPointcut();
		if (maybeEat("&&")) {
			p = new AndPointcut(p, parseNotOrPointcut());
		}

		if (maybeEat("||")) {
			p = new OrPointcut(p, parsePointcut());
		}

		return p;
	}

    	private Pointcut parseAtomicPointcut() {
		if (maybeEat("!")) {
			int startPos = tokenSource.peek(-1).getStart();
			Pointcut p = new NotPointcut(parseAtomicPointcut(), startPos);
			return p;
		}
		if (maybeEat("(")) {
			Pointcut p = parsePointcut();
			eat(")");
			return p;
		}
                //如果Adviors的表达式是@开头,则创建AnnotationPointcut类
		if (maybeEat("@")) {
			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();
                //之前实例类创建的是  @Before("annotation()") 和   @Before("webLog()")会进入parseSinglePointcut方法寻找
		Pointcut p = parseSinglePointcut();
		int endPos = tokenSource.peek(-1).getEnd();
		p.setLocation(sourceContext, startPos, endPos);
		return p;
	}
        
	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();
	        //这里也没有适配的,我们传入的是annotation() 和 webLog()
		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);
                                //annotation() 和  webLog() 会进入这里
				p = parseReferencePointcut();
			}
		}
		return p;
	}
        

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

继续回到之前的resolvePointcutExpression方法

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

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

	public final Pointcut resolve(IScope scope) {
		assertState(SYMBOLIC);
		Bindings bindingTable = new Bindings(scope.getFormalCount());
		IScope bindingResolutionScope = scope;
		if (typeVariablesInScope.length > 0) {
			bindingResolutionScope = new ScopeWithTypeVariables(typeVariablesInScope, scope);
		}
                //根据引用切点方法名称,找到对应的point里真正的要创建的PointCut
		this.resolveBindings(bindingResolutionScope, bindingTable);
		bindingTable.checkAllBound(bindingResolutionScope);
		this.state = RESOLVED;
		return this;
	}
        
	public void resolveBindings(IScope scope, Bindings bindings) {
		//找到对应名字的pointCut
		ResolvedPointcutDefinition pointcutDef = searchType.findPointcut(name);
                ............
        }

	public ResolvedPointcutDefinition findPointcut(String name) {
		for (Iterator<ResolvedMember> i = getPointcuts(); i.hasNext();) {
			ResolvedPointcutDefinition f = (ResolvedPointcutDefinition) i.next();
			// the ResolvedPointcutDefinition can be null if there are other problems that prevented its resolution
			if (f != null && name.equals(f.getName())) {
				return f;
			}
		}
        }
        
        //getPointcuts()方法会调用PointcutGetter.get 方法,会调用getDeclaredPointcuts()
	private static class PointcutGetter implements Iterators.Getter<ResolvedType, ResolvedMember> {
		@Override
		public Iterator<ResolvedMember> get(ResolvedType o) {
			return Iterators.array(o.getDeclaredPointcuts());
		}
	}

会调用Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts方法。

	public ResolvedMember[] getDeclaredPointcuts() {
		if (pointcuts == null) {
			Pointcut[] pcs = this.myType.getDeclaredPointcuts();
                    ......
                }
			for (int i = 0; i < pcs.length; i++) {
				String pcExpr = pcs[i].getPointcutExpression().toString();
				org.aspectj.weaver.patterns.Pointcut pc = parser.resolvePointcutExpression(pcExpr, getBaseClass(), parameters[i]);
				((ResolvedPointcutDefinition) pointcuts[i]).setParameterNames(pnames);
				((ResolvedPointcutDefinition) pointcuts[i]).setPointcut(pc);
			}
        }

	public Pointcut[] getDeclaredPointcuts() {
		if (declaredPointcuts != null) return declaredPointcuts;
		List<Pointcut> pointcuts = new ArrayList<Pointcut>();
		Method[] methods = clazz.getDeclaredMethods();
		for (Method method : methods) {
			Pointcut pc = asPointcut(method);
			if (pc != null) pointcuts.add(pc);
		}
		Pointcut[] ret = new Pointcut[pointcuts.size()];
		pointcuts.toArray(ret);
		declaredPointcuts = ret;
		return ret;
	}

	private Pointcut asPointcut(Method method) {
		org.aspectj.lang.annotation.Pointcut pcAnn = method.getAnnotation(org.aspectj.lang.annotation.Pointcut.class);
		if (pcAnn != null) {
			String name = method.getName();
			if (name.startsWith(ajcMagic)) {
				// extract real name
				int nameStart = name.indexOf("$$");
				name = name.substring(nameStart +2,name.length());
				int nextDollar = name.indexOf("$");
				if (nextDollar != -1) name = name.substring(0,nextDollar);
			}
			return new PointcutImpl(name,pcAnn.value(),method,AjTypeSystem.getAjType(method.getDeclaringClass()),pcAnn.argNames());
		} else {
			return null;
		}
	}

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

继续回到匹配方法

	public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
		obtainPointcutExpression();
		ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);

		if (shadowMatch.alwaysMatches()) {
			return true;
		}
		else if (shadowMatch.neverMatches()) {
			return false;
		}
		else {
			// the maybe case
			if (hasIntroductions) {
				return true;
			}
			RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
			return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
		}
	}

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

	private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
		..............
		try {
		    shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
                }
        }
	public ShadowMatch matchesMethodExecution(Method aMethod) {
		ShadowMatch match = matchesExecution(aMethod);
		if (MATCH_INFO && match.maybeMatches()) {
			System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "
					+ (match.alwaysMatches() ? "YES" : "MAYBE"));
		}
		return match;
	}
	private ShadowMatchImpl getShadowMatch(Shadow forShadow) {
                //之前创建的对应PointCut进行匹配判断
		org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);
		Test residueTest = Literal.TRUE;
		ExposedState state = getExposedState();
		if (match.maybeTrue()) {
			residueTest = pointcut.findResidue(forShadow, state);
		}
		ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);
		sm.setMatchingContext(this.matchContext);
		return sm;
	}
            

进入匹配方法matchInternal

	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())) {
			ret = matchInternal(shadow);
		} else {
			ret = FuzzyBoolean.NO;
		}
		lastMatchedShadowId = shadow.shadowId;
		lastMatchedShadowResult = ret;
		return ret;
	}

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

        protected FuzzyBoolean matchInternal(Shadow shadow) {
		AnnotatedElement toMatchAgainst = null;
		Member member = shadow.getSignature();
		ResolvedMember rMember = member.resolve(shadow.getIWorld());

		...................

		annotationTypePattern.resolve(shadow.getIWorld());
		return annotationTypePattern.matches(toMatchAgainst);
	}

	public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
		if (!isForParameterAnnotationMatch()) {
			boolean checkSupers = false;
			if (getResolvedAnnotationType().isInheritedAnnotation()) {
				if (annotated instanceof ResolvedType) {
					checkSupers = true;
				}
			}

			if (annotated.hasAnnotation(annotationType)) {
				if (annotationType instanceof ReferenceType) {
					ReferenceType rt = (ReferenceType) annotationType;
					if (rt.getRetentionPolicy() != null && rt.getRetentionPolicy().equals("SOURCE")) {
						rt.getWorld()
								.getMessageHandler()
								.handleMessage(
										MessageUtil.warn(WeaverMessages.format(WeaverMessages.NO_MATCH_BECAUSE_SOURCE_RETENTION,
												annotationType, annotated), getSourceLocation()));
						return FuzzyBoolean.NO;
					}
				}
                ................
        }

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

	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {

		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;
	}

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

在postProcessAfterInitialization方法中

		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;
		}

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

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

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

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            ..........................
	    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            ..........................
        }

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						match = mm.matches(method, actualClass);
					}
					if (match) {
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

因为之前校验的是如果该类中有任一方法符合@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的增强和对应方法,放入缓存中

猜你喜欢

转载自blog.csdn.net/yytree123/article/details/109317709