Spring-AOP源码探讨-匹配bean通知

说明使用<aop:aspectj-autoproxy />声明式注解风格配置切面,其自动为spirng容器中符合条件的bean创建代理对象匹配通知(Advisor)内部流程。

配置:

<aop:aspectj-autoproxy />

aop命名空间中aspectj-autoproxy的解析类是AspectJAutoProxyBeanDefinitionParser。
其解析方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {
		//向spring容器中注入代理对象构造器
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		extendBeanDefinition(element, parserContext);
		return null;
	}

AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary方法:

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {

		BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}

再看看AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary方法:

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
			@Nullable Object source) {

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

由此可知,容器中代理对象构造器是AnnotationAwareAspectJAutoProxyCreator类。
AnnotationAwareAspectJAutoProxyCreator是AbstractAutoProxyCreator类的子类,改类实现了BeanPostProcessor接口,是bean后置处理类,当容器完成bean的初始化后,调用后置处理器的postProcessAfterInitialization,此时构造器根据切点定义判断bean是否需要创建代理对象,是则创建,否则返回。

所以,先从AbstractAutoProxyCreator类入手,看看其postProcessAfterInitialization方法:

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			//决定是否创建代理类
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

再看看wrapIfNecessary方法,省略一些无关代码:

/**
 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
 * @param bean the raw bean instance
 * @param beanName the name of the bean
 * @param cacheKey the cache key for metadata access
 * @return a proxy wrapping the bean, or the raw bean instance as-is
 */
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	...
	// Create proxy if we have advice.
	//获取目标bean的各种增强
	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方法在AbstractAdvisorAutoProxyCreator中实现:

protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	//查找匹配的Advisor
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

findEligibleAdvisors方法包含了3个方法,分别是查找、过滤、排序:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	//查找候选的增强
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	//匹配候选增强
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		//对匹配增强进行排序
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

AnnotationAwareAspectJAutoProxyCreator类重写了父类的findCandidateAdvisors方法:

protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	List<Advisor> advisors = super.findCandidateAdvisors();
	// Build Advisors for all AspectJ aspects in the bean factory.
	if (this.aspectJAdvisorsBuilder != null) {
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

先调用父类AbstractAdvisorAutoProxyCreator的findCandidateAdvisors方法:

protected List<Advisor> findCandidateAdvisors() {
	Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
	return this.advisorRetrievalHelper.findAdvisorBeans();
}

其通过BeanFactoryAdvisorRetrievalHelper类查找容器中Advisor接口类型的实现类(省略无关代码):

public List<Advisor> findAdvisorBeans() {
	// Determine list of advisor bean names, if not cached already.
	String[] advisorNames = null;
	synchronized (this) {
		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!
			//查找容器中Advisor的实现类
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
	}
	if (advisorNames.length == 0) {
		return new LinkedList<>();
	}

	List<Advisor> advisors = new LinkedList<>();
	for (String name : advisorNames) {
		if (isEligibleBean(name)) {
			if (this.beanFactory.isCurrentlyInCreation(name)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping currently created advisor '" + name + "'");
				}
			}
			else {
				try {
					//添加到集合后返回
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
				}
				catch (BeanCreationException ex) {
					...
					throw ex;
				}
			}
		}
	}
	return advisors;
}

AnnotationAwareAspectJAutoProxyCreator类调用完父类的findCandidateAdvisors方法后,再通过BeanFactoryAspectJAdvisorsBuilderAdapter类构建匹配的Advisor类,实际上就是解析容器中标记@Aspect的类,将类中@Before、@After等注解的方法包装成相应的InstantiationModelAwarePointcutAdvisorImpl类实例:

public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;

	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new LinkedList<>();
				aspectNames = new LinkedList<>();
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					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.
					Class<?> beanType = this.beanFactory.getType(beanName);
					if (beanType == null) {
						continue;
					}
					//判断类是否有@Aspect注解
					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);
							//将类中@Before、@After等注解的方法包装成相应的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;
			}
		}
	}


	return advisors;
}

this.advisorFactory.getAdvisors(factory)如下:

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
	final List<Method> methods = new LinkedList<>();
	ReflectionUtils.doWithMethods(aspectClass, method -> {
		// Exclude pointcuts
		if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
			methods.add(method);
		}
	});
	//排序,按照方法名进行自然排序
	methods.sort(METHOD_COMPARATOR);
	return methods;
}

查找完候选的Advisor后,接着匹配合适的Advisor:

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):

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new LinkedList<>();
	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;
}

再看看canApply(candidate, clazz, hasIntroductions)方法:

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) {
		//InstantiationModelAwarePointcutAdvisorImpl是其子类
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		// It doesn't have a pointcut so we assume it applies.
		return true;
	}
}

再看看canApply(pca.getPointcut(), targetClass, hasIntroductions)方法:

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 ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

切点如何匹配以后有找时间再深入。

匹配完成后,将Advisor进行排序:

/**
 * Sort the rest by AspectJ precedence. If two pieces of advice have
 * come from the same aspect they will have the same order.
 * Advice from the same aspect is then further ordered according to the
 * following rules:
 * <ul>
 * <li>if either of the pair is after advice, then the advice declared
 * last gets highest precedence (runs last)</li>
 * <li>otherwise the advice declared first gets highest precedence (runs first)</li>
 * </ul>
 * <p><b>Important:</b> Advisors are sorted in precedence order, from highest
 * precedence to lowest. "On the way in" to a join point, the highest precedence
 * advisor should run first. "On the way out" of a join point, the highest precedence
 * advisor should run last.
 */
@Override
@SuppressWarnings("unchecked")
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
	List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
	for (Advisor element : advisors) {
		partiallyComparableAdvisors.add(
				new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
	}
	List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
	if (sorted != null) {
		List<Advisor> result = new ArrayList<>(advisors.size());
		for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
			result.add(pcAdvisor.getAdvisor());
		}
		return result;
	}
	else {
		return super.sortAdvisors(advisors);
	}
}

注:在前一步解析@Before、@After时,同类的Advisor按照方法名进行自然排序,这里排序是将后置通知排到集合前,例如After排到Before前面。

参考

https://www.imooc.com/article/43378

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值