java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE, JavaME, JavaSE)的总称。本站提供基于Java框架struts,spring,hibernate等的桌面应用、web交互及移动终端的开发技巧与资料

保持永久学习的心态,将成就一个优秀的你,来 继续搞起java知识。

在上一章节中,我们已经知道了如何获取增强器,但是我们还一件事还未做,那就是寻找匹配的增强器。下面我们来看这个功能的时序图。

1. AbstractAdvisorAutoProxyCreator

在AbstractAdvisorAutoProxyCreator的类,重点实现寻找匹配的增强器是在方法findAdvisorsThatCanApply中。

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

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

2. AopUtils

我们继续跟踪代码的findAdvisorsThatCanApply的方法,进入代码可以看到,这里主要做的事情是处理引介增强、对于普通bean的处理。

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && <strong>canApply(candidate, clazz)</strong>) {
				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;
	}

findAdvisorsThatCanApply函数的主要功能是寻找所有增强器中适用于当前class的增强器。而对于正确的匹配就是由canApply方法来实现。

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;
			return <strong>canApply(pca.getPointcut(), targetClass, hasIntroductions)</strong>;
		}
		else {
			// It doesn&#39;t have a pointcut so we assume it applies.
			return true;
		}
	}

上面的return canApply(pca.getPointcut(),targetClass,hasIntroductions)的方法其实是调用下面的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();
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<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;
	}

3.总结

SpringAOP代理,其中所要做的事情无非就是两步:获取增强方法或者增强器,和根据获取的增强进行代理。当然,对于获取增强方法或增强器,思路如下:

1) 获取所有beanName,这一步骤所有在beanFactory中注册的Bean都会被提取出来。

2) 遍历所有beanName,并找出声明AspectJ注解的类,进行进一步的处理

3) 对标记为AspectJ注解的类进行增强的提取

4) 将提取结果加入缓存

源码aopjavaspring

因为水平有限,难免有疏忽或者不准确的地方,希望大家能够直接指出来,我会及时改正。一切为了知识的分享。

后续会有更多的精彩的内容分享给大家。