从源码层面剖析SpringAOP原理(一)

1.AnnotationAwareAspectJAutoProxyCreator

@EnableAspectJAutoProxy注解中调用了@Import(AspectJAutoProxyRegistrar),而AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,学习IOC时我们知道该接口可以用于向IOC容器中添加组件,AspectJAutoProxyRegistrar也正是通过实现该接口向容器中注册了AnnotationAwareAspectJAutoProxyCreator组件

AnnotationAwareAspectJAutoProxyCreator本质就是一个后置处理器,其实现了接口SmartInstantiationAwareBeanPostProcessor,并实现了postProcessBeforeInstantiation和postProcessAfterInitialization方法。那么这两个方法的调用时机是什么呢

postProcessBeforeInstantiation

首先,在实例化bean时,执行doCreateBean()方法时,第一步就是

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
         if (bean != null) {
            return bean;
         }

也就是说,如果这一步返回了bean,后续的实例化、填充、初始化都不再进行,直接返回

resolveBeforeInstantiation的关键代码如下

if (targetType != null) {
		bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
		if (bean != null) {
		// 实例化后置处理
				bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
		}
}

其中applyBeanPostProcessorsBeforeInstantiation中的代码表明,只有targetSource != null才会返回bean,也就是说只有自定义了targetSource,从而导致后续短路操作。然而在一般情况下都不会这么做,所以绝大多数情况下都不会在该阶段直接返回AOP代理对象

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
      // 省略无关代码... 

      /**
       * 如果我们有自定义的TargetSource,在此处创建代理。
       * TargetSource将以自定义方式处理目标实例。
       */
      // 获取自定义TargetSource
      TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
      if (targetSource != null) {
         if (StringUtils.hasLength(beanName)) {
            this.targetSourcedBeans.add(beanName);
         }
         // 获取拦截器
         Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
         // 生成代理,跟之前说过的Proxy.getProxy一样的
         Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
         // 实在缓存
         this.proxyTypes.put(cacheKey, proxy.getClass());
         // 返回代理
         return proxy;
      }

      return null;
   }

postProcessAfterInitialization

因为一般不会在上面那个方法中返回,因此绝大部分的AOP代理都是在该阶段执行,其执行时机在bean初始化之后

到这一步可以得到AOP的代理时机

  1. 当用户自定义了targetSource时,AOP代理发生在bean实例化之前,且代理后直接返回bean,后续的实例化、填充、初始化操作都不再进行
  2. 而绝大多数的AOP代理时机发生在bean初始化之后

接下来来看postProcessAfterInitialization的具体实现

	// AbstractAutoProxyCreator.java
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 获取缓存key
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// bean如果没有被提前代理,则在该步进行AOP代理,关于提前的内容具体见循环依赖章节
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

关键一步就是wrapIfNecessary(bean, beanName, cacheKey);,也就是在这一步中对AOP进行了实现

wrapIfNecessary

接下来看看wrapIfNecessary()方法是怎么实现的

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 省略相对不重要的代码

		// Create proxy if we have advice.
		// 1. 获取增强拦截器
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 存在增强,则进行代理
		if (specificInterceptors != DO_NOT_PROXY) {
			// 缓存表明该bean需要被增强
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 2. 创建代理
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}
		// 缓存表明bean已经增强过
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

这个方法中有两个很重要的方法,一个是getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);获取拦截器链,一个是createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));创建代理对象,接下来分别对这两个方法进行解析

获取拦截器链

获取拦截器链主要分为两步:1. 获取所有Advisor 2. 在所有Advisor中挑选适用的Advisor

	// AbstractAdvisorAutoProxyCreator.java	
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
		// 1. 获取所有Advisor 2. 在所有Advisor中挑选适用的Advisor
		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
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 在所有Advisor中寻找适用于该bean的Advisor
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
      // 对所有Advisor进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
findCandidateAdvisors

用于获取所有Advisor ,其代码如下

	// AnnotationAwareAspectJAutoProxyCreator.java
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		// 适用注解方式配置AOP,但是可能也还存在xml配置的AOP,因此调用父类方法加载xml中的AOP声明
		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;
	}
// BeanFactoryAspectJAdvisorsBuilder.java
public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;//- 获取Aspect切面的beanName

		// 说明还没有缓存,需要从头遍历所有bean,找出注解了@Aspect的bean
		if (aspectNames == null) {
			//这里运用了双重锁机制,保证aspectBeanNames只被一个线程进行赋值
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					// 通过BeanFactory,也就是Ioc容器获取所有的beanName数组
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					// 循环所有beanName
					for (String beanName : beanNames) {
						// 不合法的bean直接跳过,规则由子类定义
						if (!isEligibleBean(beanName)) {
							continue;
						}
					
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						// 如果该bean被Aspect注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);//- 缓存被Aspect注解的beanName
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							/**
							 * singleton:即切面只会有一个实例;
							 * perthis:每个切入点表达式匹配的连接点对应的AOP对象(代理对象)都会创建一个新切面实例;
							 * pertarget:每个切入点表达式匹配的连接点对应的目标对象都会创建一个新的切面实例
							 */
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								// 解析增强方法
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									// 如果bean是单例,则直接缓存Advisor
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									// 不是单例的情况下,只能缓存工厂,每次都取增强都得新生产一个
									this.aspectFactoryCache.put(beanName, factory);
								}
								// 添加Advisor
								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();
		}
		
		//如果aspectNames已经创建好了,则遍历各个aspect切面获取advisor增强器并返回
		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;
	}

经历了这一步,就完成了xml中配置对切面和加了@Aspect的切面的解析,并返回了切面中的Advisor,接下来就要判断这些Advisor是否应该应用到这个方法上,并对方法进行增强

findAdvisorsThatCanApply

在这一步中主要就是获取Advisor的Pointcut,并判断Pointcut是否匹配当前方法,如果匹配则返回该Advisor

此外在这一步中也对引介增强进行了处理,这里就不进行讨论了

	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;
			// 获取Pointcut跟targetClass做匹配
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

这样一来,就成功获取了拦截器链,接下来就要进入代理对象的创建,在下一节进行讨论

参考文献:https://blog.csdn.net/chaitoudaren/article/details/105278868

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值