Spring源碼分析十二:@AspectJ方式的AOP 之 getAdvicesAndAdvisorsForBean

一、前言

本文是筆者閱讀Spring源碼的記錄文章,由於本人技術水平有限,在文章中難免出現錯誤,如有發現,感謝各位指正。在閱讀過程中也創建了一些衍生文章,衍生文章的意義是因爲自己在看源碼的過程中,部分知識點並不瞭解或者對某些知識點產生了興趣,所以爲了更好的閱讀源碼,所以開設了衍生篇的文章來更好的對這些知識點進行進一步的學習。

全集目錄:Spring源碼分析:全集整理


本文前篇:
Spring源碼分析十一:@AspectJ方式的AOP


這個方法的實現在 AbstractAdvisorAutoProxyCreator 類中。getAdvicesAndAdvisorsForBean 的作用是獲取所有適用於當前Bean 的 Advisors 。因爲並不是所有的規則都適用於當前bean,所有會有一個篩選的過程。

這個方法的邏輯分爲兩步:

  1. 尋找所有的顧問(Advisors), 這個方法在Aop中被重寫了,爲了可以的動態生成 Advisor – findCandidateAdvisors
  2. 尋找所有顧問(Advisors) 中適用於bean 的增強並應用 – findAdvisorsThatCanApply
	@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 主要邏輯還是在 findEligibleAdvisors 中完成。
		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();
		// 尋找所有增強中適用於bean 的增強並應用
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

可以看到兩個核心方法 findCandidateAdvisorsfindAdvisorsThatCanApply 。下面我們一個一個來分析。

二、尋找所有Advisors - findCandidateAdvisors

前文講過,Spring aop 注入的自動代理創建器是 AnnotationAwareAspectJAutoProxyCreator,所以AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 的代碼如下:

	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		// 1. 這裏是從BeanFactory 中找出來 所有 Advisor 類型的bean。即找到所有配置的Advisor。
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			// 2. buildAspectJAdvisors() 從代碼中動態找到了需要的增強點
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

這裏來解釋一下這兩個方法的區別:

  • super.findCandidateAdvisors(); : 一般獲取的都是通過直接註冊的 Advisors。比如事務的顧問,直接通過 @Bean 注入到Spring容器中。
    在這裏插入圖片描述
  • this.aspectJAdvisorsBuilder.buildAspectJAdvisors() : 主要獲取我們通過註解方式動態註冊的 Advisors。比如 在 Aop 中根據不同的表達式,需要攔截的切面也不同,那就需要爲這些切面動態生成 Advisors。而不能直接注入。

1. super.findCandidateAdvisors();

super.findCandidateAdvisors(); 這裏調用的實際上是AbstractAdvisorAutoProxyCreator 中的findCandidateAdvisors 方法。這一步最終會調用如下的findAdvisorBeans 方法。其作用根據註釋也能明白。獲取所有合格的 Advisor Bean(合格並不代表適用當前bean),忽略了FactoryBean 和創建中的bean。

	/**
	 * Find all eligible Advisor beans in the current bean factory,
	 * ignoring FactoryBeans and excluding beans that are currently in creation.
	 * @return the list of {@link org.springframework.aop.Advisor} beans
	 * @see #isEligibleBean
	 */
	public List<Advisor> findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		// 從緩存中獲取 advisorNames 
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the auto-proxy creator apply to them!
			// 從 Spring 中獲取 Advisor 類型的 beanname 。這裏獲取到的一般都是硬編碼注入的 Advisors 
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		// 如果沒有獲取到 Advisors  ,直接返回
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}
		// 到這一步必定有Advisors ,我們需要通過name來獲取到bean的實例 
		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						// 根據name 和 類型獲取到 Advisor
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						Throwable rootCause = ex.getMostSpecificCause();
						if (rootCause instanceof BeanCurrentlyInCreationException) {
							BeanCreationException bce = (BeanCreationException) rootCause;
							String bceBeanName = bce.getBeanName();
							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
								if (logger.isTraceEnabled()) {
									logger.trace("Skipping advisor '" + name +
											"' with dependency on currently created bean: " + ex.getMessage());
								}
								// Ignore: indicates a reference back to the bean we're trying to advise.
								// We want to find advisors other than the currently created bean itself.
								continue;
							}
						}
						throw ex;
					}
				}
			}
		}
		return advisors;
	}

2. this.aspectJAdvisorsBuilder.buildAspectJAdvisors()

this.aspectJAdvisorsBuilder.buildAspectJAdvisors() 的作用就是 在當前的bean工廠中查找帶有AspectJ註解的 Aspect bean,並封裝成代表他們的Spring Aop Advisor,注入到Spring 中

基本的思路如下:

  1. 獲取所有beanName,這一步所有在beanFactory中註冊的bean都會被提取出來
  2. 遍歷所有的beanName, 找出聲明AspectJ註解的類,進行進一步處理
  3. 對標記爲AspectJ註解的類進行Advisors 提取
  4. 將提取的結果保存到緩存中。
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					// 1. 獲取所有的beanName。
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					// 遍歷beanname, 找出對應的增強方法
					for (String beanName : beanNames) {
						// 不合法的bean略過,由子類定義規則,默認true
						if (!isEligibleBean(beanName)) {
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						// 獲取對應bean 的類型
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						// 2. 如果存在AspectJ 註解,進一步處理
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								// 3. 解析標記AspectJ註解中的增強方法,也就是被 @Before、@Around 等註解修飾的方法,並將其封裝成 Advisor
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		// 4. 將所有的增強方法保存到緩存中。
		List<Advisor> advisors = new ArrayList<>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

2.1. this.advisorFactory.getAdvisors(factory);

在上述代碼中,最爲複雜的就是增強器(Advisors)獲取,也就是 this.advisorFactory.getAdvisors(factory); 這一步,
具體的實現是在 ReflectiveAspectJAdvisorFactory#getAdvisors中。下面我們具體來看代碼

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// 獲取標記爲 AspectJ 的類
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		// 獲取標記爲 AspectJ 的名字
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		// 進行驗證
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
		// 獲取 aspectClass 的所有方法,過濾掉了聲明爲 PointCut 的方法以及 !method.isBridge() && !method.isSynthetic() 的方法
		for (Method method : getAdvisorMethods(aspectClass)) {
			// 將方法封裝成 Advisor 。如果不滿足封裝條件,即沒有被 AspectJ 系列註解
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		// 如果尋找的增強器不爲空而且有配置了增強延遲初始化,則需要在首位加入同步實例化增強器
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		// 獲取 DeclaredParents 註解並處理。@DeclaredParents  註解可以實現指定某些代理類是某些接口的實現。
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

...
	// 篩選出合適的方法,並封裝成 Advisor 。這裏返回的都是 InstantiationModelAwarePointcutAdvisorImpl
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		// 1. 切點信息的獲取
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		// 2. 根據切點信息封裝成增強器
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

這裏根據 切點信息來動態生成了增強器,也就是 Advisor。是根據AOP 的註解解析來的動態生成的。 可以看到,封裝的關鍵的操作還是在 getAdvisor 方法 中,下面我們來詳細分析:

2.1.1. 切點信息的獲取 - getPointcut

getPointcut 方法的實現很簡單,就是判斷方法上是否有 AspectJ系列的註解,有則封裝。

	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		// 獲取方法上的註解,包括 Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		// 到這裏必然有 AspectJ系列的註解了
		// 使用 AspectJExpressionPointcut 實例封裝獲取的信息
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		// 提取出的得到的註解中的表達式
		// 如  @Pointcut("execution(* com.kingfish.aopdemo.controller.AopController.hello(String))") 中的 execution(* com.kingfish.aopdemo.controller.AopController.hello(String))
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

其中 AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); 方法如下:

	private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
	
	// 獲取指定方法上的註解並使用  AspectJAnnotation 封裝
	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}

2.1.2. 根據切點信息封裝成增強器 - InstantiationModelAwarePointcutAdvisorImpl

在 Aop 中所有的增強都由 Advisor 的實現類 InstantiationModelAwarePointcutAdvisorImpl 統一封裝。

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		this.declaredPointcut = declaredPointcut;
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

	...
	
	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

在封裝過程中只是簡單的將信息封裝在類的實例中,所有的信息只是單純的賦值,在實例化過程中還完成了對於增強器的處理。因爲不同的增強體現的邏輯是不同的,簡單來說就是不同的切點信息的動作是不同的,比如 @Before@After 註解的動作就不同, @Before 需要在切點方法前調用, @After 需要在切點方法後調用 。而根據註解中的信息初始化對應的增強器就是在instantiateAdvice 中實現。而instantiateAdvice 中主要還是調用了 this.aspectJAdvisorFactory.getAdvice,因此我們來看 this.aspectJAdvisorFactory.getAdvice 的代碼:

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;
		// 根據不同的註解生成不同的通知(增強)
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

可以看到,Spring會根據不同的註解生成不同的增強器(通知)。比如 AspectJAroundAdviceAspectJMethodBeforeAdvice 等,從而完成不同的註解所需的動作。


二、篩選合適的Advisors - findAdvisorsThatCanApply

經歷了第一步,也僅僅是將所有的顧問(Advisors),也就是增強器,全部查找出來。但是並非所有的Advisors 都適用於當前bean。所以這一步的目的是爲了過濾出適合當前bean的增強器。

	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

可以看到關鍵內容還是在 AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
所以我們繼續往下看。AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); 的代碼如下:

	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;
			}
			// 對於普通bean 的處理
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

引介增強和普通的增強處理是不同的,所以需要分開處理。而通過上面的代碼,我們可以看到關鍵邏輯在 canApply函數中,因此我們直接看這個函數。

	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) {
			// 獲取當前bean的所有方法
			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;
	}


以上:內容部分參考
《Spring實戰》
《Spring源碼深度解析》
https://www.cnblogs.com/cheng21553516/p/12190008.html
https://blog.csdn.net/wyl6019/article/details/80136000
如有侵擾,聯繫刪除。 內容僅用於自我記錄學習使用。如有錯誤,歡迎指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章