阅读须知

  • Spring源码版本:4.3.8
  • 文章中使用/* */注释的方法会做深入分析

正文

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(), beanName, 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>();// 获取所有beanNameString[] 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官方文档进行了解,这里给出[链接地址](https:// www.eclipse.org/aspectj/doc/released/aspectj5rt-api/index.html)。
ReflectiveAspectJAdvisorFactory:

private List<Method> getAdvisorMethods(Class<?> aspectClass) {final List<Method> methods = new LinkedList<Method>();ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {@Overridepublic 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创建代理和执行流程的源码。

SpringAOP源码解析之aop:aspectj-autoproxy标签解析相关推荐

  1. Spring AOP源码(1)—<aop:config/>AOP配置标签解析【一万字】

      基于最新Spring 5.x,对Spring AOP中的<aop:config/>标签的解析源码进行了详细分析,这是Spring AOP源码的入口!   此前我们已经详细学习了Spri ...

  2. 子类重写方法aop切不到_SpringBoot源码之旅——AOP

    前提 本文代码基于SpringBoot的2.1.1.RELEASE版本,基于@AspectJ注解的AOP. 理解AOP,需要先搞懂Spring IoC容器,bin17:SpringBoot源码之旅-- ...

  3. 【源码】Spring AOP 4 Pointcut

    [源码]Spring AOP 4 Pointcut 前言 Pointcut ClassFilter AnnotationClassFilter AnnotationCandidateClassFilt ...

  4. SpringAop源码(六)- 标签aspectj-autoproxy实现分析

    目录 1.自定义标签.解析器的加载和调用时机 2.AspectJAutoProxyBeanDefinitionParser 3.总结 1.自定义标签.解析器的加载和调用时机 之前分析过EnableAs ...

  5. 老李推荐:第8章2节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-解析处理命令行参数...

    老李推荐:第8章2节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-解析处理命令行参数 MonkeyRunnerStarter是MonkeyRunner启动时的入 ...

  6. Spring3.0.5源码扩展支持AOP 获取HttpServletResponse

    Spring3.0.5源码扩展支持AOP 获取HttpServletResponse.老项目直接升级Spring版本风险无法评估,所以直接扩展Spring包支持低版本没有的功能. 目录 Spring扩 ...

  7. Spring源码分析之AOP源码分析

    文章目录 前言 一.AOP回顾 二.源码分析 EnableAspectJAutoProxy注解 AnnotationAwareAspectJAutoProxyCreator 前言 Spring框架的两 ...

  8. Postgresql源码(85)查询执行——表达式解析器分析(select 1+1如何执行)

    相关 <Postgresql源码(61)查询执行--最外层Portal模块> <Postgresql源码(62)查询执行--子模块ProcessUtility> <Pos ...

  9. 【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

    [Spring源码系列- IOC] 1 [Spring源码]0.安装Gradle环境 2 [Spring源码]1.下载与编译_pom relocation to an other version nu ...

  10. 死磕Spring系列:SpringAOP源码解析

    1. 术语 在SpringAOP中,有很多专业术语,已经了解的小伙伴可以略过,不了解的朋友就需要注意看一下啦,不然会很懵的哟. Aspect(切面) 跨多个类的关注点的模块化,与垂直调用的业务树不同, ...

最新文章

  1. 真相!30K拿到互联网大厂offer,网友:我服了!
  2. PingCode入选36氪「WISE 2021新经济之王」年度硬核、新势力企业
  3. 《数字视频和高清:算法和接口》一第2章 图像的采样和显示
  4. java中和char功能相反的是_JAVA基础语法
  5. 西湖大学最年轻博导来了丨93年出生的他,想创造属于中国的“追光”纪录
  6. 数据是如何被保护的?高质量存储告诉你
  7. WPF Image Source 设置相对路径图片
  8. java动态同步_java并发基础-Synchronized
  9. 【洛谷新手村】简单字符串 p1055 ISBN号码
  10. vue 数据劫持 响应式原理 Observer Dep Watcher
  11. Atitit.跨语言数据库db  api兼容性 jdbc odbc ado oledb 增强方案
  12. 简洁的表白java_java简短表白代码怎么写?实操讲解
  13. 以太坊公链节点连接节点超时问题排查
  14. Comet OJ C1964 I am Groot
  15. 窗口特征(Window Features)
  16. 《TCP/IP详解》读书笔记(18章)-TCP连接的建立与中止
  17. canvas 画布画太极图和钟表
  18. 编程难不难学?(3点解答你的疑惑)
  19. ZN-IRF03机器人RFID分拣实训系统
  20. a股用计算机模拟走势,A股竟用此走势将空方一网打尽

热门文章

  1. 谢烟客---------Linux之总结Linux基础
  2. “元宵”大师带你用Python量化交易
  3. Angular2 Directive讲解
  4. 北京计算机动漫游戏制作职高,北京的动漫学校(计算机动漫设计与制作)
  5. css画横线箭头_CSS绘制箭头
  6. Web基础(从零开始)——HTML文本域(textarea标签)
  7. 开发管理---项目的范围、时间与成本
  8. ul,li动态获取数据库数据并输出
  9. 色谱柱L分类保存与使用注意事项 【Chro】
  10. 【论文简述及翻译】A Large Dataset to Train Convolutional Networks for Disparity, Optical Flow, and SceneFlow