SpringAOP源码解析之配置解析篇
2018-01-11 19:33
495 查看
阅读须知
Spring源码版本:4.3.8注释规则:
//单行注释做普通注释
/**/多行注释做深入分析
建议配合Spring源码阅读
正文
Spring AOP是我们日常开发中经常使用的工具,常被用来做统一的日志、异常处理、监控等功能,使用方法在此不多赘述,有兴趣的读者可以自行去网上查阅资料进行学习,我们以注解的使用方式为例,分析其相关源码,其他方式大同小异。开启Spring AOP注解方式首先要配置
<aop:aspectj-autoproxy/>标签,我们就以这个标签的解析作为入口来分析,这里需要读者对Spring自定义标签解析的过程有一定的了解,请参考笔者Spring源码解析之标签的解析下篇这篇文章来学习Spring自定义标签解析的过程。锁定AopNamespaceHandler:
public void init() { registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); //注册aspectj-autoproxy标签解析器 registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }
当Spring遇到
<aop:aspectj-autoproxy/>标签时会调用AspectJAutoProxyBeanDefinitionParser的parse来解析:
public BeanDefinition parse(Element element, ParserContext parserContext) { /*注册AspectJAnnotationAutoProxyCreator*/ AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); //对子标签<aop:include/>的解析 extendBeanDefinition(element, parserContext); return null; }
AopNamespaceUtils:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { /*注册AspectJAnnotationAutoProxyCreator*/ BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); //设置proxy-target-class和expose-proxy属性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }
这里提到了proxy-target-class和expose-proxy两个属性,简单介绍一下,Spring提供了JDK动态代理和CGLIB代理两种方式为目标类创建代理,默认情况下,如果目标类实现了一个以上的用户自定义的接口或者目标类本身就是接口,就会使用JDK动态代理,如果目标类本身不是接口并且没有实现任何接口,就会使用CGLIB代理,如果想强制使用CGLIB代理,则可以将proxy-target-class设置true,这两种代理方式在使用的时候有一些需要注意的事项,JDK动态代理是基于实现目标类的接口来创建代理类的,所以只有接口方法会被代理,其他方法不会被代理,而CGLIB代理是基于继承目标类实现的,所以不能被继承的方法(例如final修饰的方法、private修饰的方法等)是不能被代理的,建议尽量使用JDK动态代理的方式创建代理类。expose-proxy用来解决对象内部this调用无法被切面增强的问题,例如我们在A类的对象内部x方法中调用另外一个内部方法y时,y方法不会被切面增强,这时可以配置expose-proxy为true并将this.y()改为((A)AopContext.currentProxy()).y(),即可让y方法被切面增强。下面让我们来看本篇文章的主角AnnotationAwareAspectJAutoProxyCreator的注册过程:
AopConfigUtils:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { /*注册AspectJAnnotationAutoProxyCreator*/ return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
AopConfigUtils:
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { //如果已经存在代理创建器 BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); //判断已存在的代理创建器和本次要注册的代理创建器是否是相同的 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { /*获取已经存在的代理创建器的优先级*/ int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); /*获取本次要创建的代理创建器的优先级*/ int requiredPriority = findPriorityForClass(cls); //判断优先级,使用优先级高的代理创建器 if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; //如果是相同的直接返回无需再次注册 } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); //注册代理创建器 return beanDefinition; }
AopConfigUtils:
private static int findPriorityForClass(Class<?> clazz) { return APC_PRIORITY_LIST.indexOf(clazz); } private static int findPriorityForClass(String className) { for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) { Class<?> clazz = APC_PRIORITY_LIST.get(i); if (clazz.getName().equals(className)) { return i; } } throw new IllegalArgumentException( "Class name [" + className + "] is not a known auto-proxy creator class"); }
我们发现优先级的判断就是根据类在APC_PRIORITY_LIST中的索引值来判断的,索引值越小的优先级越高,我们看一下APC_PRIORITY_LIST的内容:
AopConfigUtils:
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>(); static { APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); }
我们发现它是一个ArrayList,并且在静态块中为其add了三个类,也就是这三个类的优先级依次降低。注册完AnnotationAwareAspectJAutoProxyCreator之后,要怎么使用这个bean呢,我们看一下它的层次结构:
我们发现这个类间接实现了BeanPostProcessor接口,我们知道,Spring会保证所有bean在实例化的时候都会调用其postProcessAfterInitialization方法,我们可以使用这个方法包装和改变bean,而真正实现这个方法是在其父类AbstractAutoProxyCreator类中:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { /*如果需要则代理*/ return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
AbstractAutoProxyCreator:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; //如果已经处理过,直接返回 } //如果是aop的基础类不需要代理,或者配置了bean不需要代理,直接返回 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } /*获取bean匹配的增强器*/ Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); /*创建代理*/ Object proxy = createProxy( bean.getClass(), be 13e01 anName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
AbstractAdvisorAutoProxyCreator:
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { /*寻找合适的增强器*/ List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
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()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
AnnotationAwareAspectJAutoProxyCreator:
protected List<Advisor> findCandidateAdvisors() { /*获取父类中的其他aop配置声明*/ List<Advisor> advisors = super.findCandidateAdvisors(); /*获取注解方式配置的aop信息*/ advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
AbstractAdvisorAutoProxyCreator:
protected List<Advisor> findCandidateAdvisors() { /*获取增强器bean*/ return this.advisorRetrievalHelper.findAdvisorBeans(); }
BeanFactoryAdvisorRetrievalHelper:
public List<Advisor> findAdvisorBeans() { String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { //获取所有Advisor类型的bean的名称 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { //创建bean并添加到增强器集合中返回 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } continue; } } throw ex; } } } } return advisors; }
上面这个方法相信大家已经看出了它的目的,先找出所有对应Advisor的类的beanName,再通过beanFactory.getBean方法获取这些bean并返回,这里就是通过父类获取其他aop配置信息。下面我们来看注解aop配置信息的获取:
BeanFactoryAspectJAdvisorsBuilder:
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); //获取所有beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { /*判断是否满足子标签<aop:include/>的配置条件*/ if (!isEligibleBean(beanName)) { continue; } Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } /*判断是否存在@Aspect注解*/ if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); //单例 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)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { //原型 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(); } List<Advisor> advisors = new LinkedList<Advisor>(); 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; }
方法很长,不过逻辑很清晰,首先获取所有bean,然后过滤掉不满足子标签配置过滤条件的bean,接着判断bean是否有@Aspect注解,最后解析注解的配置内容并放入缓存中,我们分步来看:
AnnotationAwareAspectJAutoProxyCreator.BeanFactoryAspectJAdvisorsBuilderAdapter:
protected boolean isEligibleBean(String beanName) { /*是否是合适的被代理bean*/ return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName); }
AnnotationAwareAspectJAutoProxyCreator:
protected boolean isEligibleAspectBean(String beanName) { if (this.includePatterns == null) { return true; } else { for (Pattern pattern : this.includePatterns) { if (pattern.matcher(beanName).matches()) { return true; } } return false; } }
这里的includePatterns就是文章开始解析
<aop:aspectj-autoproxy/>子标签
<aop:include/>的配置时织入的,有兴趣的读者可以了解一下具体用法,这里不多赘述。
AbstractAspectJAdvisorFactory:
public boolean isAspect(Class<?> clazz) { /*是否有@Aspect注解*/ return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz)); }
AbstractAspectJAdvisorFactory:
private boolean hasAspectAnnotation(Class<?> clazz) { return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null); }
ReflectiveAspectJAdvisorFactory:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList<Advisor>(); /*获取增强器方法*/ for (Method method : getAdvisorMethods(aspectClass)) { /*获取增强器*/ Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //如果增强器不为空并且aspect的初始化模式为延迟初始化则需要在增强器集合首位加入同步实例化增强器 Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } for (Field field : aspectClass.getDeclaredFields()) { //@Declare标签的解析 Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
这里提到了aspect的初始化模式,目前一共有6种,对应PerClauseKind这个枚举,这里不做详细说明,大家可以到aspect官方文档进行了解,这里给出链接地址。
ReflectiveAspectJAdvisorFactory:
private List<Method> getAdvisorMethods(Class<?> aspectClass) { final List<Method> methods = new LinkedList<Method>(); ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException { //过滤掉@PointCut注解的方法 if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { methods.add(method); } } }); Collections.sort(methods, METHOD_COMPARATOR); return methods; }
ReflectiveAspectJAdvisorFactory:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); /*切入点信息的获取*/ AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } /*初始化增强器*/ return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
ReflectiveAspectJAdvisorFactory:
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { /*获取方法上的注解*/ AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); //设置execution表达式 ajexp.setBeanFactory(this.beanFactory); return ajexp; }
AbstractAspectJAdvisorFactory:
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { Class<?>[] classesToLookFor = new Class<?>[] { Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class}; for (Class<?> c : classesToLookFor) { AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c); if (foundAnnotation != null) { return foundAnnotation; } } return null; }
这里我们看到aop相关的一些注解的提取,下面就是初始化过程了:
InstantiationModelAwarePointcutAdvisorImpl:
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { this.declaredPointcut = declaredPointcut; this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); this.methodName = aspectJAdviceMethod.getName(); this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); this.aspectJAdviceMethod = aspectJAdviceMethod; this.aspectJAdvisorFactory = aspectJAdvisorFactory; this.aspectInstanceFactory = aspectInstanceFactory; this.declarationOrder = declarationOrder; this.aspectName = aspectName; //判断是否配置了延迟初始化 if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { this.pointcut = this.declaredPointcut; this.lazy = false; /*初始化增强*/ this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
InstantiationModelAwarePointcutAdvisorImpl:
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { /*获取增强器*/ return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); }
ReflectiveAspectJAdvisorFactory:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; //根据不同的注解匹配不同的增强器 switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
到这里整个aop注解方式的初始化工作就完成了,不知道大家是否还记得我们是怎么一步一步的走到这里的,到这里获取到了所有的候选增强器,下面要匹配适用于当前bean的增强器:
AbstractAdvisorAutoProxyCreator:
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { /*匹配适用于当前bean的增强器*/ return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
AopUtils:
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) { /*判断当前增强是否可以应用在当前bean上*/ if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { //引介增强已经处理过了,无需再次处理 if (candidate instanceof IntroductionAdvisor) { continue; } /*判断当前增强是否可以应用在当前bean上*/ if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
上面的方法中提到引介增强的概念,在此做简要说明,引介增强是一种比较特殊的增强类型,它不是在目标方法周围织入增强,而是为目标类创建新的方法和属性,所以引介增强的连接点是类级别的,而非方法级别的。通过引介增强,我们可以为目标类添加一个接口的实现,即原来目标类未实现某个接口,通过引介增强可以为目标类创建实现该接口的代理。另外这个方法用两个重载的canApply方法为目标类寻找匹配的增强器,其中第一个canApply方法会调用第二个canApply方法并将第三个参数传为false:
AopUtils:
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; /*判断当前增强是否可以应用在当前bean上*/ return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { return true; } }
我们来看一下前面初始化的InstantiationModelAwarePointcutAdvisorImpl类的层次结构:
我们看到它实现了PointcutAdvisor接口,所以会调用第二个分支条件中的canApply方法进行判断,第一个参数pca.getPointcut()也就是调用InstantiationModelAwarePointcutAdvisorImpl的getPointcut方法,这个方法的返回值就是我们看到的在InstantiationModelAwarePointcutAdvisorImpl初始化时传入的AspectJExpressionPointcut,我们以AspectJExpressionPointcut作为第一个参数继续跟踪canApply方法:
AopUtils:
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(); if (methodMatcher == MethodMatcher.TRUE) { return true; } 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 = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { /*匹配判断*/ if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
我们跟踪pc.getMethodMatcher()方法也就是AspectJExpressionPointcut的getMethodMatcher方法:
public MethodMatcher getMethodMatcher() { checkReadyToMatch(); return this; }
发现方法直接返回this,也就是下面methodMatcher.matches方法就是调用AspectJExpressionPointcut的matches方法:
public boolean matches(Method method, Class<?> targetClass) { /*匹配判断*/ return matches(method, targetClass, false); }
AspectJExpressionPointcut:
public boolean matches(Method method, Class<?> targetClass, boolean beanHasIntroductions) { checkReadyToMatch(); Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); ShadowMatch shadowMatch = getShadowMatch(targetMethod, method); if (shadowMatch.alwaysMatches()) { return true; } else if (shadowMatch.neverMatches()) { return false; } else { if (beanHasIntroductions) { return true; } RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch); return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass)); } }
getShadowMatch方法里面就是调用aspect提供的api来判断当前类是否满足execution表达式的规则,有兴趣的读者可以查阅aspect的相关资料进行学习。配置解析流程的源码分析到这里就结束了,我们将在下篇文章中分析Spring AOP创建代理和执行流程的源码。
相关文章推荐
- spring aop自动配置源码解析
- Spring核心框架 - AOP的原理及源码解析
- Spring源码阅读之-自定义配置的解析
- spring boot 源码解析22-spring boot jdbc自动化配置
- Spring基于注解形式的 AOP的原理流程及源码解析(一)
- spring AOP 源码解析 及其实现原理
- spring 源码探索 -- aop 标签解析和创建代理
- Spring基于注解形式的 AOP的原理流程及源码解析(二)
- mybatis源码解析-启动配置&使用spring启动配置(一)
- spring源码(3)之解析配置文件的过程
- [Spring3.x源码]AOP(二)组装配置信息
- spring源码解析之默认配置文件名/WEB-INF/applicationContext.xml
- Spring源码分析:AOP源码解析(上篇)
- Spring基于注解形式的 AOP的原理流程及源码解析(三)
- Spring对注解(Annotation)处理源码分析2——解析和注入注解配置的资源
- spring源码解析-从xml配置文件中获取bean
- spring源码解析-Aop
- Spring源码分析:AOP源码解析(下篇)
- Spring3.2 中 Bean 定义之基于 XML 配置方式的源码解析
- Spring源码学习--Spring配置文件解析BeanDefinitionReader(二)