前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。@pdai
Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现
- 引入
aop配置标签的解析
- config配置标签的解析
- aspectj-autoproxy配置标签的解析
注解切面代理创立类(AnnotationAwareAspectJAutoProxyCreator)
postProcessBeforeInstantiation
- 判断是否是aop根底类
- 是否应该跳过shouldSkip
- 切面办法转成Advisor
- 获取表达式的切点
- 封装成Advisor
- 小结
- postProcessAfterInitialization
- 总结
- 更多文章
引入
咱们应该从哪里开始着手看Spring AOP的源码呢?和咱们上文剖析的IOC源码实现有什么关系呢?
- 前文中咱们写了AOP的Demo,依据其XML配置咱们不难发现AOP是基于IOC的Bean加载来实现的;这便使咱们的次要入口
所以了解Spring AOP的初始化必须要先了解Spring IOC的初始化。
- 而后咱们就能找到如下初始化的流程和aop对应的handler类
即parseCustomElement办法找到parse aop:aspectj-autoproxy
的handler(org.springframework.aop.config.AopNamespaceHandler)
(PS:其实你会发现,最重要的是知识点的关联关系,而不是知识点自身,就后续代码而言不就是打个断点缓缓看的事了么。)
aop配置标签的解析
上文中,咱们找到了AopNamespaceHandler,其实就是注册BeanDefinition的解析器BeanDefinitionParser,将aop:xxxxxx
配置标签交给指定的parser来解决。
public class AopNamespaceHandler extends NamespaceHandlerSupport { /** * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}' * and '{@code scoped-proxy}' tags. */ @Override public void init() { // In 2.0 XSD as well as in 2.5+ XSDs // 注册解析<aop:config> 配置 registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); // 注册解析<aop:aspectj-autoproxy> 配置 registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); // Only in 2.0 XSD: moved to context namespace in 2.5+ registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }}
config配置标签的解析
<aop:config/>
由ConfigBeanDefinitionParser这个类解决,作为parser类最重要的就是parse办法
@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); configureAutoProxyCreator(parserContext, element); List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { String localName = parserContext.getDelegate().getLocalName(elt); if (POINTCUT.equals(localName)) { parsePointcut(elt, parserContext); } else if (ADVISOR.equals(localName)) { parseAdvisor(elt, parserContext); } else if (ASPECT.equals(localName)) { parseAspect(elt, parserContext); } } parserContext.popAndRegisterContainingComponent(); return null;}
打个断点看下
parseAspect的办法如下, 解决办法不难,我这里就不开展了
private void parseAspect(Element aspectElement, ParserContext parserContext) { String aspectId = aspectElement.getAttribute(ID); String aspectName = aspectElement.getAttribute(REF); try { this.parseState.push(new AspectEntry(aspectId, aspectName)); List<BeanDefinition> beanDefinitions = new ArrayList<>(); List<BeanReference> beanReferences = new ArrayList<>(); List<Element> declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); for (int i = METHOD_INDEX; i < declareParents.size(); i++) { Element declareParentsElement = declareParents.get(i); beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext)); } // We have to parse "advice" and all the advice kinds in one loop, to get the // ordering semantics right. NodeList nodeList = aspectElement.getChildNodes(); boolean adviceFoundAlready = false; for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (isAdviceNode(node, parserContext)) { if (!adviceFoundAlready) { adviceFoundAlready = true; if (!StringUtils.hasText(aspectName)) { parserContext.getReaderContext().error( "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.", aspectElement, this.parseState.snapshot()); return; } beanReferences.add(new RuntimeBeanReference(aspectName)); } AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); beanDefinitions.add(advisorDefinition); } } AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); parserContext.pushContainingComponent(aspectComponentDefinition); List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } parserContext.popAndRegisterContainingComponent(); } finally { this.parseState.pop(); }}
aspectj-autoproxy配置标签的解析
<aop:aspectj-autoproxy/>
则由AspectJAutoProxyBeanDefinitionParser这个类解决的,咱们看下parse 办法
@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) { // 注册AspectJAnnotationAutoProxyCreator AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); // 拓展BeanDefinition extendBeanDefinition(element, parserContext); return null;}
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary办法对应如下
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext);}
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary对应如下
@Nullablepublic static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}
到这里,咱们发现AOP的创立工作是交给AnnotationAwareAspectJAutoProxyCreator来实现的。
注解切面代理创立类(AnnotationAwareAspectJAutoProxyCreator)
AnnotationAwareAspectJAutoProxyCreator是如何工作的呢?这时候咱们就要看AnnotationAwareAspectJAutoProxyCreator类构造关系了。
如下是类构造关系
它实现了两类接口:
- BeanFactoryAware属于Bean级生命周期接口办法
- InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,个别称它们的实现类为“后处理器”,是容器级生命周期接口办法;
联合前文Spring Bean生命周期的流程
咱们就能够定位到外围的初始化办法必定在postProcessBeforeInstantiation和postProcessAfterInitialization中。
postProcessBeforeInstantiation
如下是上述类构造中postProcessBeforeInstantiation的办法,读者在本人看代码的时候倡议打个断点看,能够不便了解
@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { // 如果曾经在缓存中,则疏忽 if (this.advisedBeans.containsKey(cacheKey)) { return null; } // 是否是aop根底类?是否跳过? if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null;}
判断是否是aop根底类
是否是aop根底类的判断办法 isInfrastructureClass 如下
@Overrideprotected boolean isInfrastructureClass(Class<?> beanClass) { // Previously we setProxyTargetClass(true) in the constructor, but that has too // broad an impact. Instead we now override isInfrastructureClass to avoid proxying // aspects. I'm not entirely happy with that as there is no good reason not // to advise aspects, except that it causes advice invocation to go through a // proxy, and if the aspect implements e.g the Ordered interface it will be // proxied by that interface and fail at runtime as the advice method is not // defined on the interface. We could potentially relax the restriction about // not advising aspects in the future. // 父类判断它是aop根底类 or 应用@Aspect注解 return (super.isInfrastructureClass(beanClass) || (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));}
父类判断它是否是aop根底类的办法 super.isInfrastructureClass(beanClass), 实质上就是判断该类是否实现了Advice, Pointcut, Advisor或者AopInfrastructureBean接口。
protected boolean isInfrastructureClass(Class<?> beanClass) { // 该类是否实现了Advice, Pointcut, Advisor或者AopInfrastructureBean接口 boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); if (retVal && logger.isTraceEnabled()) { logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); } return retVal;}
是否应该跳过shouldSkip
通过断点辅助,candidateAdvisors是就是xml配置的告诉是对应的
@Overrideprotected boolean shouldSkip(Class<?> beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } return super.shouldSkip(beanClass, beanName);}
切面办法转成Advisor
findCandidateAdvisors办法如下:
@Overrideprotected List<Advisor> findCandidateAdvisors() { // 在父类中找到所有的advisor:基于xml配置的<aop:before/>生成的 List<Advisor> advisors = super.findCandidateAdvisors(); // 为bean Factory中AspectJ切面构建advistor:通过AspectJ注解的形式生成Advisor类 if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors;}
在以后的bean Factory中通过AspectJ注解的形式生成Advisor类,buildAspectJAdvisors办法如下
/** * Look for AspectJ-annotated aspect beans in the current bean factory, * and return to a list of Spring AOP Advisors representing them. * <p>Creates a Spring Advisor for each AspectJ advice method. * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */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<>(); 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; } 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); // 单例加到advisorsCache, 非单例加到aspectFactoryCache if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. 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); // advisorFactory工厂获取advisors advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new ArrayList<>(); 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;}
上述办法实质上的思路是:用DCL双重锁的单例实现形式,拿到切面类里的切面办法,将其转换成advisor(并放入缓存中)。
转换的成advisor的办法是:this.advisorFactory.getAdvisors
@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); for (Method method : getAdvisorMethods(aspectClass)) { // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect // to getAdvisor(...) to represent the "current position" in the declared methods list. // However, since Java 7 the "current position" is not valid since the JDK no longer // returns declared methods in the order in which they are declared in the source code. // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods // discovered via reflection in order to support reliable advice ordering across JVM launches. // Specifically, a value of 0 aligns with the default value used in // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor). Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors;}
getAdvisor办法如下
@Override@Nullablepublic 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; } // 封装成advisor return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}
获取表达式的切点
获取表达式的切点的办法getPointcut如下:
@Nullableprivate 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()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp;}
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod的办法如下
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] { Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};/** * Find and return the first AspectJ annotation on the given method * (there <i>should</i> only be one anyway...). */@SuppressWarnings("unchecked")@Nullableprotected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) { AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz); if (foundAnnotation != null) { return foundAnnotation; } } return null;}
findAnnotation办法如下
@Nullableprivate static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { A result = AnnotationUtils.findAnnotation(method, toLookFor); if (result != null) { return new AspectJAnnotation<>(result); } else { return null; }}
AnnotationUtils.findAnnotation 获取注解办法如下
/** * Find a single {@link Annotation} of {@code annotationType} on the supplied * {@link Method}, traversing its super methods (i.e. from superclasses and * interfaces) if the annotation is not <em>directly present</em> on the given * method itself. * <p>Correctly handles bridge {@link Method Methods} generated by the compiler. * <p>Meta-annotations will be searched if the annotation is not * <em>directly present</em> on the method. * <p>Annotations on methods are not inherited by default, so we need to handle * this explicitly. * @param method the method to look for annotations on * @param annotationType the annotation type to look for * @return the first matching annotation, or {@code null} if not found * @see #getAnnotation(Method, Class) */@Nullablepublic static <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType) { if (annotationType == null) { return null; } // Shortcut: directly present on the element, with no merging needed? if (AnnotationFilter.PLAIN.matches(annotationType) || AnnotationsScanner.hasPlainJavaAnnotationsOnly(method)) { return method.getDeclaredAnnotation(annotationType); } // Exhaustive retrieval of merged annotations... return MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY, RepeatableContainers.none()) .get(annotationType).withNonMergedAttributes() .synthesize(MergedAnnotation::isPresent).orElse(null);}
封装成Advisor
注:Advisor 是 advice的包装器,蕴含了advice及其它信息
由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()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); }}
通过pointcut获取advice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) { Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); return (advice != null ? advice : EMPTY_ADVICE);}
交给aspectJAdvisorFactory获取
@Override@Nullablepublic 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 we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class 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); } // 切面注解转换成advice AbstractAspectJAdvice springAdvice; switch (aspectJAnnotation.getAnnotationType()) { case AtPointcut: // 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); } // 最初将其它切面信息配置到advice springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice;}
小结
回头看,次要是解决应用了@Aspect注解的切面类,而后将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor的过程。
postProcessAfterInitialization
有了Adisor, 注入到适合的地位并交给代理(cglib和jdk)实现了。
/*** Create a proxy with the configured interceptors if the bean is* identified as one to proxy by the subclass.* @see #getAdvicesAndAdvisorsForBean*/@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean;}
后文中将别离介绍代理的创立和实现:
- Spring进阶 - Spring AOP实现原理详解之AOP代理的创立
- Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
- Spring进阶 - Spring AOP实现原理详解之JDK代理实现
总结
通过上文的剖析,咱们做下小结:
- 由IOC Bean加载办法栈中找到parseCustomElement办法,找到parse
aop:aspectj-autoproxy
的handler(org.springframework.aop.config.AopNamespaceHandler) - AopNamespaceHandler注册了
<aop:aspectj-autoproxy/>
的解析类是AspectJAutoProxyBeanDefinitionParser - AspectJAutoProxyBeanDefinitionParser的parse 办法 通过AspectJAwareAdvisorAutoProxyCreator类去创立
AspectJAwareAdvisorAutoProxyCreator实现了两类接口,BeanFactoryAware和BeanPostProcessor;依据Bean生命周期办法找到两个外围办法:postProcessBeforeInstantiation和postProcessAfterInitialization
- postProcessBeforeInstantiation:次要是解决应用了@Aspect注解的切面类,而后将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor
- postProcessAfterInitialization:次要负责将Advisor注入到适合的地位,创立代理(cglib或jdk),为前面给代理进行加强实现做筹备。
更多文章
首先, 从Spring框架的整体架构和组成对整体框架有个认知。
Spring根底 - Spring和Spring框架组成
- Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
Spring根底 - Spring简略例子引入Spring的外围
- 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
Spring根底 - Spring外围之管制反转(IOC)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
Spring根底 - Spring外围之面向切面编程(AOP)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
Spring根底 - SpringMVC申请流程和案例
- 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计
- 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
Spring进阶 - Spring IOC实现原理详解之IOC初始化流程
- 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
Spring进阶 - Spring AOP实现原理详解之切面实现
- 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
Spring进阶 - Spring AOP实现原理详解之AOP代理
- 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
- 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
Spring进阶 - Spring AOP实现原理详解之JDK代理实现
- 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。