在上篇文章 中咱們搭建了一個閱讀源碼的demo工程,而後簡單介紹了一下@EnableAspectJAutoProxy
註解,這個註解最重要的功能就是爲向Spring中注入了一個beanAnnotationAwareAspectJAutoProxyCreator
,本篇文章就繼續來擼AOP的源碼spring
前文已經簡單提到了這個類的功能,不過這裏仍是要先看一下這個類的繼承圖 觀察類圖可知,AnnotationAwareAspectJAutoProxyCreator這個類間接實現了BeanPostProcessor接口。還記得咱們以前在對SpringIOC的源碼進行解析時提到過,Spring在實例化Bean的先後會分別調用方法postProcessBeforeInstantiation
和postProcessAfterInstantiation
而AOP的總體邏輯就是經過這兩個方法來實現的express
postProcessBeforeInstantiation
首先看一下這個postProcessBeforeInstantiation
方法,它是在bean實例化以前調用的,主要是針對切面類。這個方法不在AnnotationAwareAspectJAutoProxyCreator這個類中,而是在其父類AbstractAutoProxyCreator中緩存
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } //加載全部加強 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } 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; }
上方代碼中最重要的一個方法就是shouldSkip方法了,這個方法被AspectJAwareAdvisorAutoProxyCreator所重載安全
protected boolean shouldSkip(Class<?> beanClass, String beanName) { //查找全部標識了@Aspect註解的類,這裏是重點,接着往下看 List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor) { if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { return true; } } } return super.shouldSkip(beanClass, beanName); } protected List<Advisor> findCandidateAdvisors() { return this.advisorRetrievalHelper.findAdvisorBeans(); } protected List<Advisor> findCandidateAdvisors() { List<Advisor> advisors = super.findCandidateAdvisors(); //buildAspectJAdvisors是重點 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
一個長方法buildAspectJAdvisorside
public List<Advisor> buildAspectJAdvisors() { //全部Aspect類的名稱集合 List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; //這個雙重檢查是否是在學習安全的單例模式的時候見過 if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); //獲取全部Bean名稱 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { //判斷是否符合條件,好比說有時會排除一些類,不讓這些類注入進Spring if (!isEligibleBean(beanName)) { continue; } Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //判斷Bean的Class上是否標識@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)) { //將解析的Bean名稱及類上的加強緩存起來,每一個Bean只解析一次 this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { 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>(); for (String aspectName : aspectNames) { //從緩存中獲取當前Bean的切面實例,若是不爲空,則指明當前Bean的Class標識了@Aspect,且有切面方法 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; }
advisorFactory.getAdvisors方法會從@Aspect標識的類上獲取@Before,@Pointcut等註解的信息及其標識的方法的信息,生成加強函數
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); //校驗類的合法性相關 validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList<Advisor>(); //獲取這個類全部的加強方法 for (Method method : getAdvisorMethods(aspectClass)) { //生成加強實例 Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; } //獲取類的的方法 private List<Method> getAdvisorMethods(Class<?> aspectClass) { final List<Method> methods = new LinkedList<Method>(); ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException { //在@Aspect標識的類內部排除@Pointcut標識以外的全部方法,獲得的方法集合包括繼承自父類的方法,包括繼承自Object的方法 if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { methods.add(method); } } }); //對獲得的全部方法排序, //若是方法標識了切面註解,則按@Around, @Before, @After, @AfterReturning, @AfterThrowing的順序排序 //若是沒有標識這些註解,則按方法名稱的字符串排序, //有註解的方法排在無註解的方法以前 //最後的排序應該是這樣的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class。。。 Collections.sort(methods, METHOD_COMPARATOR); return methods; }
調用生成加強實例的方法post
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { //再次校驗類的合法性 validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //切點表達式的包裝類裏面包含這些東西:execution(public * cn.shiyujun.service.IOCService.hollo(..)) AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } //根據方法、切點、AOP實例工廠、類名、序號生成切面實例,詳細代碼往下看 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); } private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { //查詢方法上的切面註解,根據註解生成相應類型的AspectJAnnotation,在調用AspectJAnnotation的構造函數的同時 //根據註解value或pointcut屬性獲得切點表達式,有argNames則設置參數名稱 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); //過濾那些不含@Before, @Around, @After, @AfterReturning, @AfterThrowing註解的方法 if (aspectJAnnotation == null) { return null; } //生成帶表達式的切面切入點,設置其切入點表達式 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); ajexp.setBeanFactory(this.beanFactory); return ajexp; }
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()) { Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { this.pointcut = this.declaredPointcut; this.lazy = false; //重點在這裏 this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } } 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); }
生成加強ui
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable { public 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 (!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; //根據註解類型生成不一樣的通知實例 switch (aspectJAnnotation.getAnnotationType()) { 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); } //設置通知方法所屬的類 springAdvice.setAspectName(aspectName); //設置通知的序號,同一個類中有多個切面註解標識的方法時,按上方說的排序規則來排序, //其序號就是此方法在列表中的序號,第一個就是0 springAdvice.setDeclarationOrder(declarationOrder); //獲取通知方法的全部參數 String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); //將通知方法上的參數設置到通知中 if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } //計算參數綁定工做,此方法詳解請接着往下看 springAdvice.calculateArgumentBindings(); return springAdvice; } }
校驗方法參數並綁定this
public synchronized final void calculateArgumentBindings() { if (this.argumentsIntrospected || this.parameterTypes.length == 0) { return; } int numUnboundArgs = this.parameterTypes.length; Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes(); //切面註解標識的方法第一個參數要求是JoinPoint,或StaticPart,如果@Around註解則也能夠是ProceedingJoinPoint if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) { numUnboundArgs--; } else if (maybeBindJoinPointStaticPart(parameterTypes[0])) { numUnboundArgs--; } if (numUnboundArgs > 0) { //綁定屬性 bindArgumentsByName(numUnboundArgs); } this.argumentsIntrospected = true; } private void bindArgumentsByName(int numArgumentsExpectingToBind) { if (this.argumentNames == null) { //獲取方法參數的名稱 this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod); } if (this.argumentNames != null) { // 往下看 bindExplicitArguments(numArgumentsExpectingToBind); } else { throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " + "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " + "the argument names were not specified and could not be discovered."); } } private void bindExplicitArguments(int numArgumentsLeftToBind) { //此屬性用來存儲方法未綁定的參數名稱,及參數的序號 this.argumentBindings = new HashMap<String, Integer>(); int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length; if (this.argumentNames.length != numExpectedArgumentNames) { throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames + " arguments to bind by name in advice, but actually found " + this.argumentNames.length + " arguments."); } // So we match in number...,argumentIndexOffset表明第一個未綁定參數的順序 int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind; for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) { //存儲未綁定的參數名稱及其順序的映射關係 this.argumentBindings.put(this.argumentNames[i], i); } // Check that returning and throwing were in the argument names list if // specified, and find the discovered argument types. //若是是@AfterReturning註解的returningName 有值,驗證,解析,同時獲得定義返回值的類型 if (this.returningName != null) { if (!this.argumentBindings.containsKey(this.returningName)) { throw new IllegalStateException("Returning argument name '" + this.returningName + "' was not bound in advice arguments"); } else { Integer index = this.argumentBindings.get(this.returningName); this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index]; this.discoveredReturningGenericType = this.aspectJAdviceMethod.getGenericParameterTypes()[index]; } } //若是是@AfterThrowing註解的throwingName 有值,驗證,解析,同時獲得拋出異常的類型 if (this.throwingName != null) { if (!this.argumentBindings.containsKey(this.throwingName)) { throw new IllegalStateException("Throwing argument name '" + this.throwingName + "' was not bound in advice arguments"); } else { Integer index = this.argumentBindings.get(this.throwingName); this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index]; } } // configure the pointcut expression accordingly. configurePointcutParameters(argumentIndexOffset); } private void configurePointcutParameters(int argumentIndexOffset) { int numParametersToRemove = argumentIndexOffset; if (this.returningName != null) { numParametersToRemove++; } if (this.throwingName != null) { numParametersToRemove++; } String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove]; Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length]; Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes(); int index = 0; for (int i = 0; i < this.argumentNames.length; i++) { if (i < argumentIndexOffset) { continue; } if (this.argumentNames[i].equals(this.returningName) || this.argumentNames[i].equals(this.throwingName)) { continue; } pointcutParameterNames[index] = this.argumentNames[i]; pointcutParameterTypes[index] = methodParameterTypes[i]; index++; } //剩餘的未綁定的參數會賦值給AspectJExpressionPointcut(表達式形式的切入點)的屬性,以備後續使用 this.pointcut.setParameterNames(pointcutParameterNames); this.pointcut.setParameterTypes(pointcutParameterTypes); }
未完待續 限於平臺字數限制,本篇文章就到這裏