> 文章列表 > 梳理 Spring AOP

梳理 Spring AOP

梳理 Spring AOP

元数据注解定义

连接点:PointCut

增强通知

  1. Around

  1. Befroe

  1. After

  1. AfterReturning

  1. AfterThrowing

工具类

BeanFactoryAspectJAdvisorsBuilder

ReflectiveAspectJAdvisorFactory

增强通知类

  • AsepctJAroundAdvice

  • AsepctJMethodBeforeAdvice

  • AsepctJAfterAdvice

  • AsepctJAfterReturningAdvice

  • AsepctJAfterThrowingAdvice

AdviceAdpater

适配转化成MethodInterceptor

由于AsepctJAroundAdvice和AsepctJAfterAdvice已经实现了MethodInterceptor接口不需要再做适配

  • MethodBeforeAdviceAdapter

  • AfterReturningAdeviceAdapter

  • ThrowingAdapter

AdvisorAdapterRegistry

DefaultAdvisorAdapterRegistry

GlobalAdvisorAdpatorRegistry

MethodMatcher

方法匹配器

AspectJExpressionPointcut 连接点拦截

MethodInterceptor

AsepctJAroundAdvice和AsepctJAfterAdvice已经实现了MethodInterceptor接口

  • MethodBeforeAdviceInterceptor

  • AfterReturningAdviceInterceptor

  • ThrowsAdviceInterceptor

  • ReflectiveMethodInvocation

AopProxy

  • CglibAopProxy

  • JdkDynamicAopProxy

AnnotationAwareAspectJAutoProxyCreator

重点方法

buildAspectJAdvisors 查询切面配置类和收集切面信息。

findCandidateAdvisors 查找可用的切面

流程图

缓存切面配置信息

实例前处理器

AbstractAutoProxyCreator#postProcessBeforeInstantiation

  1. 查找切面元数据配置类

  1. 解决切面元数据配置类并将增强通知转化成AbstractAspectJAdvice子类。

  1. 保存到BeanFactoryAspectJAdvisorBuilder.aspectJFactoryCache


初始化后处理器

AbstractAutoProxyCreator#postProcessAfterInitialization

核心逻辑是:创建代理若匹配条件。 AbstractAutoProxyCreator#wrapIfNecessary

AnnotationAwareApsectJAutoProxyCreator#findCandidateAdvisors

    @Overrideprotected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}

BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvsiors

查询切面配置类缓存到内部advisorsCache

    private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();public List<Advisor> buildAspectJAdvisors() {List<String> aspectNames = this.aspectBeanNames;if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();aspectNames = new ArrayList<>();//遍历所有的bean。String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}// We must be careful not to instantiate beans eagerly as in this case they// would be cached by the Spring container but would not have been weaved.Class<?> beanType = this.beanFactory.getType(beanName, false);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 {//...}}}}}}//.....return advisors;}

ReflectiveAspectJAdvisorsFactory.getAdvice

将注解转化成增强通知类Advice

@Override@Nullablepublic Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}AbstractAspectJAdvice springAdvice;switch (aspectJAnnotation.getAnnotationType()) {case AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;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;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// Now to configure the advice...springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}