spring源码分析——aop切面顺序实现原理

本文深入分析Spring AOP中切面方法的执行顺序。从spring上下文初始化时对切面方法的排序,到每次触发切面时的匹配和排序过程,详细解析了切面类和方法的执行控制。主要涉及order注解、方法名排序以及切面类的order属性比较。在执行时,先按切面注解顺序,再按字母序排序,最后在触发业务方法时,依据order属性进行排序确定切面执行顺序。
摘要由CSDN通过智能技术生成

使用spring版本为4.3.22

1. 简介

对于同一个目标方法而言,切面触发的顺序如下:

Around->Before->businessFun->Around后续->After->AfterReturing/AfterThrowing

aspect.jpg

下边通过spring源码分析一下,对于切面类和方法的执行顺序,spring是如何控制的。

2. spring上下文初始化的时候,第一次创建advisors的缓存时,对切面方法的排序过程

定位到目标类AnnotationAwareAspectJAutoProxyCreator,通过90行的断点,进一步说明。具体的调用栈情况如下:

findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
shouldSkip:103, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
postProcessBeforeInstantiation:248, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsBeforeInstantiation:1042, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
resolveBeforeInstantiation:1016, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:471, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:139, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:83, ClassPathXmlApplicationContext (org.springframework.context.support)
main:28, TestOrder (com.stpice.spring.demo.aop.order)
	@Override
	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.
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());//这里会构建所有的advisors,并添加到list里面
		return advisors;
	}

进入this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法。

buildAspectJAdvisors:85, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

BeanFactoryAspectJAdvisorsBuilder中的buildAspectJAdvisors方法是真正的构建advisors的方法。这个方法比较长,这里针对其中比较关键的部分代码进行注释说明。

	/**
	 * Look for AspectJ-annotated aspect beans in the current bean factory,
	 * and return to a list of Spring AOP Advisors representing them.
	 * <p>Creates a Spring Advisor for each AspectJ advice method.
	 * @return the list of {@link org.springframework.aop.Advisor} beans
	 * @see #isEligibleBean
	 */
	public List<Advisor> buildAspectJAdvisors() {
   
		List<String> aspectNames = this.aspectBeanNames;//因为是单例的,初始的时候,切面bean的名字为null

		if (aspectNames == null) {
   //第一次为null的时候,会进入这个分支构建切面bean
			synchronized (this) {
   //以单例为锁进行同步
				aspectNames = this.aspectBeanNames;//重新获取,防止并发时,其他线程已经进行过初始化
				if (aspectNames == null) {
   //尚未初始化
					List<Advisor> advisors = new LinkedList<Advisor>();//先构造一个空的链表
					aspectNames = new LinkedList<String>();//aspectNames是一个存放切面名字的临时列表
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);//从bean工厂中获取所有的bean名称
					for (String beanName : beanNames) {
   
						if (!isEligibleBean(beanName)) {
   //遍历判断是否该bean的类型是否合适自动代理,这里会调用BeanFactoryAspectJAdvisorsBuilder子类AnnotationAwareAspectJAutoProxyCreator中的isEligibleBean方法,如果不满足,则继续遍历
							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;
						}
						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);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);//从factory中获取advisors,这里涉及到初始获取各个切面实例中的切面方法时,每个方法的排列顺序,后边会具体进行分析
								if (this.beanFactory.isSingleton(beanName)) {
   
									this.advisorsCache.put(beanName, classAdvisors);//缓存单例的切面实例
								}
								else {
   
									this.aspectFactoryCache.put(beanName, factory);//多例对切面工厂进行缓存
								}
								advisors.addAll(classAdvisors);//添加到advisors列表中
							}
							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();
		}
		List<Advisor> advisors = new LinkedList<Advisor>();
		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;
	}

ReflectiveAspectJAdvisorFactory类中,会处理所有的advisors中的各个方法,并对方法进行排序包装。

getAdvisors:135, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		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<Advisor>();
		for (Method method : getAdvisorMethods(aspectClass)) {
   //这里获取所有advisors方法的时候,会对切面方法进行比较并排序
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);//包装advisor,并且将不是advisor的方法过滤掉
			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.
		for (Field field 
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值