Spring AOP 源碼解析系列,建議你們按順序閱讀,歡迎討論java
Spring AOP的實現已經臻於很是完善,而經過與AspectJ的整合使得AOP的使用簡單且靈活。不管是XML仍是註解,都實現了非侵入式的控制。而基於自動代理的基礎上,整合的AspectJ也經過BeanPostProcessor擴展的方式實現細粒度的切面控制。XML方式經過以aop:config標籤實現配置,註解方式則經過@Aspect聲明切面類。兩種方式底層的實現異曲同工,都是基於自動代理的基類AbstractAutoProxyCreator來完成。node
Spring的組件經過XML配置進行註冊以及初始化,其方式就是實現特定命名空間的NamespaceHandler接口,對於Spring+AspectJ的整合方式的XML配置,是從AopNamespaceHandler開始。其中註冊了兩個標籤,config和aspectj-autoproxy,分別爲XML配置的根標籤,和註解方式的啓用配置。spring
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
不一樣的解析器對應的處理最終實現了XML或註解方式的AspectJ AOP。chrome
先看一個XML配置的demoexpress
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 原始對象 --> <bean id="chromeBrowser" class="com.lcifn.spring.aop.bean.ChromeBrowser"/> <!-- 環繞加強對象 --> <bean id="aspectjBrowserAroundAdvice" class="com.lcifn.spring.aop.advice.AspectJBrowserAroundAdvice"></bean> <!-- aspectj aop 配置 --> <aop:config proxy-target-class="true"> <aop:pointcut id="browserPointcut" expression="execution(* com.lcifn.spring.aop.bean.*.*(..))"/> <aop:aspect ref="aspectjBrowserAroundAdvice"> <aop:around method="aroundIntercept" pointcut-ref="browserPointcut"/> </aop:aspect> </aop:config> </beans>
ConfigBeanDefinitionParser解析器用來處理XML配置,Spring的代碼大多使用命名清晰的子方法來描述主結構。數組
ConfigBeanDefinitionParser.java public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); // 配置自動代理建立,基於AbstractAutoProxyCreator實現切面的發現和匹配 configureAutoProxyCreator(parserContext, element); List<Element> childElts = DomUtils.getChildElements(element); for (Element elt: childElts) { String localName = parserContext.getDelegate().getLocalName(elt); // aop:pointcut標籤解析 if (POINTCUT.equals(localName)) { parsePointcut(elt, parserContext); } // aop:advisor標籤解析 else if (ADVISOR.equals(localName)) { parseAdvisor(elt, parserContext); } // aop:aspect標籤解析 else if (ASPECT.equals(localName)) { parseAspect(elt, parserContext); } } parserContext.popAndRegisterContainingComponent(); return null; }
parse方法的主要內容分爲兩部分,自動代理配置的建立以及代理XML配置的解析,能夠從上面代碼中很清晰的看出。緩存
自動代理配置是基類AbstractAutoProxyCreator的子類AspectJAwareAdvisorAutoProxyCreator,來實現AspectJ相關的AOP的實現。其主要的類結構以下:性能優化
而configureAutoProxyCreator方法則完成了自動代理配置的初始化。ide
private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); }
由工具類AopNamespaceUtils實現函數
AopNamespaceUtils.java public static void registerAspectJAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 註冊AspectJ自動代理建立類 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 設置proxyTargetClass和exposeProxy屬性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }
對於AspectJ自動代理建立類的註冊有一個優先級機制,即當前容器中已存在自動代理建立類的bean,則以優先級高的替換優先級低的。
AopConfigUtils.java public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) { return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); } private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); // 存在同名的AUTO_PROXY_CREATOR 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); // 傳入的優先級高於原有的,則替換BeanDefinition的className if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // 不存在同名,則建立新的BeanDefinition 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; }
對於自動代理建立類的優先級,在Spring中定義了三個
// 基礎版 APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); // XML配置 APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); // 註解配置 APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
於是同時存在XML和註解時,註解的自動代理建立類會覆蓋XML的。但AnnotationAwareAspectJAutoProxyCreator實際上是AspectJAwareAdvisorAutoProxyCreator的子類,在查詢候選Advisor時,會先調用父類的方法獲取XML配置中的Advisor。
另外aop:config能夠配置proxy-target-class和expose-proxy,經過useClassProxyingIfNecessary方法設置到AspectJAwareAdvisorAutoProxyCreator的BeanDefinition的屬性中。
AopNamespaceUtils.java private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
註冊完自動代理建立類,接下來就是aop的具體配置。經常使用的通常是aop:pointcut和aop:aspect兩個標籤,aop:advisor一般在外部aop:config外存在advice配置時使用。
對pointcut的解析比較簡單,就是獲取id及expression屬性,而後建立pointcut的BeanDefinition。
ConfigBeanDefinitionParser.java private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { String id = pointcutElement.getAttribute(ID); String expression = pointcutElement.getAttribute(EXPRESSION); AbstractBeanDefinition pointcutDefinition = null; try { this.parseState.push(new PointcutEntry(id)); pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; if (StringUtils.hasText(pointcutBeanName)) { parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); } finally { this.parseState.pop(); } return pointcutDefinition; }
主要來看下對aspect的解析,在aop:aspect中的有兩類子標籤,一種是pointcut切入點的配置,一種是advice加強的配置,而advice又分爲前置加強,後置加強,環繞加強等。
ConfigBeanDefinitionParser.java 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<BeanDefinition>(); List<BeanReference> beanReferences = new ArrayList<BeanReference>(); // 解析引入加強 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)); } // 解析advice加強,組裝BeanDefinition 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); // 解析pointcut標籤 List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } parserContext.popAndRegisterContainingComponent(); } finally { this.parseState.pop(); } }
對advice加強的解析parseAdvice方法是核心部分,而其返回的是組裝好的Advisor切面BeanDefinition
ConfigBeanDefinitionParser.java private AbstractBeanDefinition parseAdvice( String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { try { this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement))); // create the method factory bean // 用來獲取切面類中的加強方法Method對象的工廠bean RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); methodDefinition.getPropertyValues().add("targetBeanName", aspectName); methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method")); methodDefinition.setSynthetic(true); // create instance factory definition // 用來獲取切面類對象的工廠bean RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class); aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName); aspectFactoryDef.setSynthetic(true); // register the pointcut // 根據不一樣的加強標籤建立不一樣的加強BeanDefinition AbstractBeanDefinition adviceDef = createAdviceDefinition( adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef, beanDefinitions, beanReferences); // configure the advisor // 建立AspectJPointcutAdvisor,封裝上面建立的AdviceBeanDefinition RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class); advisorDefinition.setSource(parserContext.extractSource(adviceElement)); advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef); if (aspectElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); } // register the final advisor parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition; } finally { this.parseState.pop(); } }
此方法中先建立了兩個合成的BeanDefinition,一個爲加強方法的工廠,一個爲切面對象的工廠,用來最終經過反射調用時使用。然後根據不一樣的advice標籤(aop:before,aop:after-returning等)建立相應的加強BeanDefinition,最後使用AspectJPointcutAdvisor封裝加強BeanDefinition而後返回。
再來看看對advice標籤的解析createAdviceDefinition方法
private AbstractBeanDefinition createAdviceDefinition( Element adviceElement, ParserContext parserContext, String aspectName, int order, RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef, List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) { // 建立advice的BeanDefinition,獲取advice對應的Class對象 RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext)); adviceDefinition.setSource(parserContext.extractSource(adviceElement)); adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName); adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order); // after-returning的returning屬性解析 if (adviceElement.hasAttribute(RETURNING)) { adviceDefinition.getPropertyValues().add( RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING)); } // after-throwing的throwing屬性解析 if (adviceElement.hasAttribute(THROWING)) { adviceDefinition.getPropertyValues().add( THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); } // arg-names參數暱稱屬性解析 if (adviceElement.hasAttribute(ARG_NAMES)) { adviceDefinition.getPropertyValues().add( ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); } // 建立AdviceBeanDefinition構造函數 ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); // 構造函數設置加強方法工廠 cav.addIndexedArgumentValue(METHOD_INDEX, methodDef); // 構造函數設置pointcut Object pointcut = parsePointcutProperty(adviceElement, parserContext); if (pointcut instanceof BeanDefinition) { cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); beanDefinitions.add((BeanDefinition) pointcut); } else if (pointcut instanceof String) { RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); beanReferences.add(pointcutRef); } // 構造函數設置切面對象工廠 cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); return adviceDefinition; }
不一樣的Advice標籤對應不一樣的Advice類,但都繼承同一個基類AbstractAspectJAdvice。AbstractAspectJAdvice定義了構造函數
public AbstractAspectJAdvice( Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) { }
建立Advice的BeanDefinition時,即按照此構造函數組裝BeanDefinition中的ConstructorArgumentValues屬性。
而對於不一樣的advice則經過getAdviceClass方法匹配對應的Class
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) { String elementName = parserContext.getDelegate().getLocalName(adviceElement); if (BEFORE.equals(elementName)) { return AspectJMethodBeforeAdvice.class; } else if (AFTER.equals(elementName)) { return AspectJAfterAdvice.class; } else if (AFTER_RETURNING_ELEMENT.equals(elementName)) { return AspectJAfterReturningAdvice.class; } else if (AFTER_THROWING_ELEMENT.equals(elementName)) { return AspectJAfterThrowingAdvice.class; } else if (AROUND.equals(elementName)) { return AspectJAroundAdvice.class; } else { throw new IllegalArgumentException("Unknown advice kind [" + elementName + "]."); } }
至此,每一個Advice都設置了切入點,切面類以及加強方法,再由AspectJPointcutAdvisor對Advice進行封裝,在每一個bean初始化以後,AspectJAwareAdvisorAutoProxyCreator的基類AbstractAutoProxyCreator實現了BeanPostProcessor擴展,查詢全部的匹配bean的Advisor,並建立bean對應的Proxy代理,在方法真正執行時,觸發其相應的Advice執行。
不管是經過<aop:aspectj-autoproxy/>
仍是@EnableAspectJAutoProxy
配置的AspectJ註解支持,都是經過AnnotationAwareAspectJAutoProxyCreator支撐對AspectJ相關注解的解析和註冊。AnnotationAwareAspectJAutoProxyCreator繼承AnnotationAwareAspectJAutoProxyCreator,並覆蓋了查詢全部候選Advisor的方法findCandidateAdvisors。基於此方法對@Aspect的切面類進行解析,並生成相應Advisor對象返回。
AnnotationAwareAspectJAutoProxyCreator.java protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 調用父類方法,兼容XML和註解並存 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. // 解析註解方式的切面 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
核心操做交由BeanFactoryAspectJAdvisorsBuilder類的buildAspectJAdvisors方法實現
BeanFactoryAspectJAdvisorsBuilder.java public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = null; synchronized (this) { // 緩存aspectName aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); // 獲取全部spring容器中的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); 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) { // 建立Aspect實例工廠 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 根據Aspect實例工廠獲取全部Advisor對象 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 { // 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; } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new LinkedList<Advisor>(); // 若是aspectNames不爲空,則從緩存中獲取對應的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; }
核心方法是根據Aspect實例工廠獲取全部Advisor對象
ReflectiveAspectJAdvisorFactory.java public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass(); final String aspectName = maaif.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. // 懶加載裝飾類封裝Aspect實例工廠 final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif); final List<Advisor> advisors = new LinkedList<Advisor>(); for (Method method : getAdvisorMethods(aspectClass)) { // 返回有Advice類型(@Before,@AfterReturning等)的註解方法生成的Advisor Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), 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鏈最前增長一個前置攔截器,用來初始化切面類 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方法執行具體的操做
ReflectiveAspectJAdvisorFactory.java public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { validate(aif.getAspectMetadata().getAspectClass()); // 獲取pointcut切入點expression表達式對象 AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass()); if (ajexp == null) { return null; } // 實例化Advisor對象,支持懶加載策略 return new InstantiationModelAwarePointcutAdvisorImpl( this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName); }
Advisor對應的Advice對象的實例化實際發生在InstantiationModelAwarePointcutAdvisorImpl的構造方法中
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) { this.declaredPointcut = ajexp; this.method = method; this.atAspectJAdvisorFactory = af; this.aspectInstanceFactory = aif; this.declarationOrder = declarationOrderInAspect; this.aspectName = aspectName; if (aif.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union(aif.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, aif); this.lazy = true; } else { // A singleton aspect. // 實例化Advice this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); this.pointcut = declaredPointcut; this.lazy = false; } } private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { return this.atAspectJAdvisorFactory.getAdvice( this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); }
經過ReflectiveAspectJAdvisorFactory工廠類完成
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { Class<?> candidateAspectClass = aif.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); // 獲取方法上的AspectJ註解 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); } AbstractAspectJAdvice springAdvice; // 根據不一樣AspectJ註解生成對應的Advice對象 switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfter: springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif); 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... // 配置Advice對象 springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrderInAspect); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
至此,註解方式的切面類中的每一個Advice方法生成對應的Advice對象,並被InstantiationModelAwarePointcutAdvisor實現類封裝而後返回。
相比於XML配置的方式,註解方式的Advisor不會生成BeanDefinition註冊到Spring容器中,而是直接返回到Advisor集合中,並以aspectName的方式進行緩存防止重複生成及性能優化。
對於Spring+AspectJ的方式,其主要操做都在於Advisor的解析和生產,底層經過Spring自動代理的方式被Spring容器初始化bean時調用。而AOP代理則是使用ProxyFactory,根據不一樣配置決定JDK或CGLIB的方式來生成。
Spring AOP的四種實現中四種方式,其實也是Sping AOP的演進的過程,而對這四種方式源碼的解析,也證實了高級特性都是基於基礎功能實現的。但願藉由這四種方式的源碼解析,可以對Spring AOP的原理可以有深刻的理解,期待你們的交流!