Spring中AOP相关源码解析 (2)

}

而```aspect,beforeAdvice,pointcutA,advisor```都是我们在配置文件中配置过的,是切点,切面和处理方法的实现类。```org.springframework.aop.config.internalAutoProxyCreator```是上面分析过的用于创建aop代理的实现类。 而后面的以```org.springframework.aop.aspectj.AspectJPointcutAdvisor```开头的几个类实际上就是包含了切点和通知的一个切面的实现类,也就是它来决定哪些类需要被增强。 ![增强实现类](https://user-gold-cdn.xitu.io/2019/7/5/16bc0e4a582a62c7?w=785&h=223&f=png&s=15964) ### 功能增强 #### 增强时机 如果看过前面手写aop文章的同学应该知道当时我们分析aop增强时机时有说过aop的增强功能实际上是依赖于动态代理实现的。而动态代理如果要对一个对象进行增强那么首先需要持有该对象才行。 所以我们在对对象进行增强的前提是该对象已经被创建完成之后。而且我们要清楚的是一个类对象被增强后我们所有需要使用该对象的地方都应该使用该对象,这样就确定了类增强的时机一定是在类对象创建之后并且在完成注入之前。 #### AspectJAwareAdvisorAutoProxyCreator 前面有说过创建代理对象实际上是通过```AspectJAwareAdvisorAutoProxyCreator```来完成,先来了解一下该类,查看该类的继承体系。 ![继承体系](https://user-gold-cdn.xitu.io/2019/7/5/16bc0e4a5a031b8b?w=639&h=215&f=png&s=21661) 可以看到实际上该类本身还是一个BeanPostProcessor,那么可以肯定的是我们只要找到执行BeanPostProcessor的地方并且是在实例化后执行的地方即可。经过调试后定位到```AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization```方法。 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; } 这里是对后置处理器进行遍历,对于aop我们需要关注的是```AspectJAwareAdvisorAutoProxyCreator```这一个处理器。 ##### wrapIfNecessary protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //more code // 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方法是用来获取和当前对象匹配的切面。这里获取相匹配的切面类是通过```AbstractAdvisorAutoProxyCreator```来实现。 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { //根据在配置文件中配置的order属性或者注解@order()进行从小到大的排序 //order的值越小其优先级越高 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } 首先获取到所有的切面类,然后通过```AopUtils.findAdvisorsThatCanApply```方法来确定哪些类能够匹配。 ##### AopUtils.findAdvisorsThatCanApply 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 && canApply(candidate, clazz)) { 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; } 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 canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } 实现逻辑很简单,遍历所有的advisor调用canApply确定是否匹配。 切面是有切入点和通知组成,切入点用来确定哪些对象需要被增强,而通知决定如何进行增强。所以很明显这里确定类对象是否匹配是由切入点(pointCut)决定的。 我们先来看一下切入点是什么。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wppyfg.html