源碼分析基於spring 4.3.x
本文經過閱讀Spring源碼,分析Spring AOP的功能是如何實現的。
關於閱讀源碼的思路,可參考 -- 如何閱讀java源碼java
首先,明確幾個概念
pointcut:切入點,根據方法名或者正則表達式去攔截一個方法。
advice:通知,在攔截到方法執行前或執行後的加強操做。
aspect:切面,一個切面能夠包括多個切入點和通知,spring內部的切入點和通知是無序的。
advisor:只有一個通知和一個切入點的單元切面,能夠看作一種特殊的aspect。正則表達式
開始閱讀源碼前,本文主要關注的幾個問題:spring
<aop:aspectj-autoproxy/>
元素的做用<aop:aspectj-autoproxy/>
的做用aspectj-autoproxy是spring內部定義的標籤。
前面解析Spring讀取bean元數據的文章說過,在spring中除了<beans>標籤,其餘標籤須要編寫一個NamespaceHandlerSupport實現類來完成標籤解析工做。
在spring源碼中搜索一下,就能夠發現aspectj-autoproxy的解析類AopNamespaceHandlerexpress
public void init() { this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser()); this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator()); this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); }
而AspectJAutoProxyBeanDefinitionParser類負責對aspectj-autoproxy標籤進行解析:
AspectJAutoProxyBeanDefinitionParser#parse緩存
public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null; }
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary -> AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary微信
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
這裏將AnnotationAwareAspectJAutoProxyCreator注入到spring上下文環境中。
AnnotationAwareAspectJAutoProxyCreator是一個關鍵的類,繼承了BeanPostProcessor接口,它負責完成建立切面工做。源碼分析
AbstractAutoProxyCreator#postProcessAfterInitialization -> AbstractAutoProxyCreator#wrapIfNecessary
(AbstractAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator的父類)post
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { ... Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // #1 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // #2 this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
#1
根據bean元數據構造通知和單元切面#2
建立代理對象ui
getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean -> AbstractAdvisorAutoProxyCreator#findEligibleAdvisorsthis
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); // #1 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // #2 extendAdvisors(eligibleAdvisors); // #3 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); // #4 } return eligibleAdvisors; }
這是一個很是重要的方法,實現了幾個關鍵步驟#1
findCandidateAdvisors -- 查找全部的單元切面(第一次會建立)#2
findAdvisorsThatCanApply -- 根據目標bean的class過濾一部分的單元切面#3
extendAdvisors -- 擴充單元切面列表,spring會根據須要添加一些內部使用的單元切面#4
sortAdvisors -- 對單元切面排序
findCandidateAdvisors -> AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors -> BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { // #1 List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { // #2 if (!isEligibleBean(beanName)) { // #3 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); if (beanType == null) { continue; } if (this.advisorFactory.isAspect(beanType)) { // #4 aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); // #5 if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); // #6 if (this.beanFactory.isSingleton(beanName)) { // #7 this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); // #8 } 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); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } ... #9 }
#1
典型的double check#2
遍歷全部的bean#3
判斷是否爲合格的切面類#4
是否爲切面類(是否有Aspect註解)#5
獲取切面信息#6
構建一系列的單元切面#7
加入緩存#8
加入結果#9
緩存不爲空,從緩存中獲取數據返回
步驟#6
調用ReflectiveAspectJAdvisorFactory.getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); // #1 List<Advisor> advisors = new LinkedList<Advisor>(); for (Method method : getAdvisorMethods(aspectClass)) { // #2 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); // #3 if (advisor != null) { advisors.add(advisor); } } ... return advisors; }
#1
lazySingletonAspectInstanceFactory對getAspectInstance進行了緩存,保證getAspectInstance方法返回單例#2
getAdvisorMethods獲取全部沒有Pointcut註解的方法(有Pointcut註解的方法不多是Advisor)#3
使用方法元數據構造單元切面
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); // #1 if (expressionPointcut == null) { return null; } return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); // #2 }
#1
獲取切入點Pointcut,並構建了AspectJExpressionPointcut#2
建立單元切面InstantiationModelAwarePointcutAdvisorImpl,該類中包含屬性 --
被攔截類declaringClass,被攔截方法aspectJAdviceMethod,切入點declaredPointcut和通知instantiatedAdvice。
InstantiationModelAwarePointcutAdvisorImpl#構造方法 -> InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice -> ReflectiveAspectJAdvisorFactory#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { ... // #1 AbstractAspectJAdvice springAdvice; switch (aspectJAnnotation.getAnnotationType()) { // #2 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); } // 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; }
#1
aspectInstanceFactory#getAspectMetadata獲取切面信息,再獲取對應的aspectJAnnotation#2
根據切面類型,構建不一樣的通知實現類
@After對應AspectJAfterAdvice
@Around對應AspectJAroundAdvice
@Before對應AspectJMethodBeforeAdvice
@AfterReturning對應AspectJAfterReturningAdvice
@AfterThrowing對應AspectJAfterThrowingAdvice
除了AspectJAroundAdvice,這些通知實現類都實現了MethodInterceptor(方法攔截器接口)。
這裏會遍歷全部的單元切面,檢查bean的class和class中是否有方法能夠匹配對應的單元切面,若是沒有則過濾該單元切面。代碼比較繁瑣,不展開了。
AspectJAwareAdvisorAutoProxyCreator.extendAdvisors -> AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary
spring會在advisors列表開始位置添加ExposeInvocationInterceptor。
ExposeInvocationInterceptor是一個特殊的MethodInterceptor,它將當前方法攔截器調用鏈放置到線程上下文中,以便有須要時使用。
咱們知道,spring經過動態代理類實現aop,有jdk動態代理和cglib兩種方法。
若是要使用jdk動態代理,被代理類必須實現一個接口。
這裏只關注jdk動態代理如何實現aop。
AbstractAutoProxyCreator#wrapIfNecessary方法#2
步驟 -> AbstractAutoProxyCreator.createProxy(第三個參數就是Advices)
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ... Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // #1 for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); // #2 } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); // #3 }
#1
類型檢查及轉化,如將Advices轉換成Advisor#2
將Advisor添加到proxyFactory中#3
構造代理對象
proxyFactory.getProxy -> ProxyCreatorSupport.createAopProxy
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); // #1 }
#1
構造代理對象,createAopProxy方法參數是this,將proxyFactory將自身做爲參數,
DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // #1 Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { // #2 return new JdkDynamicAopProxy(config); } }
#1
根據用戶配置和目標bean是否有實現接口,判斷是否須要使用ObjenesisCglibAopProxy#2
使用JDK動態代理
來看看JdkDynamicAopProxy#getProxy
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); // #1 }
#1
這裏構造了jdk的動態代理對象,注意newProxyInstance方法第三個參數是this,即JdkDynamicAopProxy,JdkDynamicAopProxy實現了InvocationHandler。
Spring AOP源碼解析內容過長,關於多個通知鏈式調用的解析留到下一篇文章解析
若是您以爲本文不錯,歡迎關注個人微信公衆號,您的關注是我堅持的動力!