Spring源码之创建AOP代理(补)
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'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.总结
Spring的AOP代理,其中所要做的事情无非就是两步:获取增强方法或者增强器,和根据获取的增强进行代理。当然,对于获取增强方法或增强器,思路如下:
1) 获取所有beanName,这一步骤所有在beanFactory中注册的Bean都会被提取出来。
2) 遍历所有beanName,并找出声明AspectJ注解的类,进行进一步的处理
3) 对标记为AspectJ注解的类进行增强的提取
4) 将提取结果加入缓存
源码aopjavaspring
因为水平有限,难免有疏忽或者不准确的地方,希望大家能够直接指出来,我会及时改正。一切为了知识的分享。
后续会有更多的精彩的内容分享给大家。