Spring AOP的实现原理之获取增强器Adivors

在讲解<aop>自定义标签时,提到了AspectJAwareAdvisorAutoProxyCreator的注册,对于AOP的实现基本就靠这个类实现。

AspectJAwareAdvisorAutoProxyCreator的层次结构如图所示,该类实现了BeanPostProcessor与SmartInstantiationAwareBeanPostProcessor这两个接口

ApplicationContext实现的默认行为就是会将所有的单例bean提前进行实例化,即会调用getBean(name),跟踪代码到AbstractAutowireCapableBeanFactory中createBean

此时 resolveBeforeInstantiation(beanName, mbd)就是给实现了SmartInstantiationAwareBeanPostProcessor接口的类的机会去改变bean

AbstractAutowireCapableBeanFactory
	protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
		...
		...
		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbd);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbd, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
		}

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
如最上面的类层次结构图,此时会调用AbstractAutoProxyCreator中的postProcessBeforeInstantiation以及postProcessAfterInstantiation方法
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
			throws BeansException {

		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}
注意shouldSkip(beanClass, beanName),该方法其实已经找到所有的标有@AspectJ类中的增加方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !this.targetSourcedBeans.containsKey(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				this.targetSourcedBeans.put(beanName, Boolean.TRUE);
				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
				Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
				this.proxyTypes.put(cacheKey, proxy.getClass());
				return proxy;
			}
		}

		return null;
	}

	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}


AspectJAwareAdvisorAutoProxyCreator
	@Override
	protected boolean shouldSkip(Class beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor) {
				if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
					return true;
				}
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}

findCadidateAdvisors()即是寻找所有的增加方法,即标有@Before,@After,@AfterReturning,@Around等注解的方法,一个增强方法对应Advisor.

下面来看看findCadidateAdvisors()的逻辑

	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// 这个是寻找xml配置文件的advisors
		List<Advisor> advisors = super.findCandidateAdvisors();
		// 寻找标有注解的advisors,
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}

如上所示,spring把寻找标有注解的advisor委托给了BeanFactoryAspectJAdvisorsBuilder

	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = null;
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				....
				//获取所有注册的beanName
				String[] beanNames =
						BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					....
					//判断beanType是否存在AspectJ注解
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						//AspectMetadata代表标有@AspectJ的类
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							....
							//获取标记AspectJ注解中的增强方法
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							....
						}
						....
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
		....
	}

重点在this.advisorFactory.getAdvisors(factory)

	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
		final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
		final String aspectName = maaif.getAspectMetadata().getAspectName();
		...
		final List<Advisor> advisors = new LinkedList<Advisor>();
		//getAdvisorMethods()寻找增强方法,即标有注解的方法不过排出了@Poincut
		//并且是有序的集合,顺序分别是Around, Before, After, AfterReturning, AfterThrowing
		//这也是5种通知在AOP中的拦截顺序
		for (Method method : getAdvisorMethods(aspectClass)) {
			//全部以InstantiationModelAwarePointcutAdvisorImpl返回
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}
		...
		return advisors;
	}

回到文章最开始,AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口,那么这个接口的方法在哪儿实现呢?答案在AbstractAutowireCapableBeanFactory类的initializeBean方法中,该方法调用applyBeanPostProcessorsAfterInitialization方法,即是BeanPostProcessor接口方法的调用之处

	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		...
		...
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			//BeanPostProcessor接口postProcessBeforeInitialization实现
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//initMethod方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
	
		if (mbd == null || !mbd.isSynthetic()) {
			//BeanPostProcessor接口postProcessAfterInitialization实现
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}


AspectJAwareAdvisorAutoProxyCreator看看是如何实现postProcessAfterInitialization方法的
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.containsKey(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
接下来看看wrapIfNecessary方法,该方法就是创建代理的地方了,匹配切点表达式的增强器就是getAdvicesAndAdvisorsForBean这个方法得来的

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		...
		// 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方法

	protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
		//该句代码在上面已做了分析
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//在candidateAdvisors中寻找匹配目标类的增加器
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
跟踪findAdvisorsThatCanApply方法,其逻辑委托给了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		...
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			...
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

当前循环的增强器是否匹配目标类是由canApply()方法判断的。放在编码阶段,就是目标类是否满足切点表达式,比如:execution(* com.uestc.test.aop.*.*(..)),即com.uestc.test.aop包下类的任何方法都应进行增强。

跟踪canApply方法,可以看到是通过MethodMatcher.match()方法来匹配的

	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();
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);
		for (Class<?> clazz : classes) {
			Method[] methods = clazz.getMethods();
			for (Method method : methods) {
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

其匹配过程大致是通过提取切入点表达式,根据切入点表达式来判断是否匹配,但是前面分析寻找增强方法时对于标有@Poincut注解的方法排除了,也没有看到切点表达式的提取。

我们来看看getClassFilter()

	public ClassFilter getClassFilter() {
		checkReadyToMatch();
		return this;
	}
对,切入点表达式的提取就在checkReadyToMacth()方法中

private void checkReadyToMatch() {
		if (getExpression() == null) {
			throw new IllegalStateException("Must set property 'expression' before attempting to match");
		}
		if (this.pointcutExpression == null) {
			this.pointcutExpression = buildPointcutExpression();
		}
	}
buildPointCutExpression()即是提取切入点表达式,返回的类型是PointcutExpressionImpl,简单描述spring的做法就是通过反射来提取,但是spring的做法远比这复杂的多,这里暂不做分析。

由此,我们就找到了匹配目标类的增强器。




 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值