梳理 Spring AOP
元数据注解定义
连接点:PointCut
增强通知
-
Around
-
Befroe
-
After
-
AfterReturning
-
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
-
查找切面元数据配置类
-
解决切面元数据配置类并将增强通知转化成AbstractAspectJAdvice子类。
-
保存到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;}