上文講了spring是如何開啓AOP的,簡單點說就是將AnnotationAwareAspectJAutoProxyCreator這個類註冊到容器中,由於這個類最終實現了BeanPostProcessor接口,並且在其postProcessAfterInitialization()方法中完成了AOP代理對象的建立,建立時機則是在bean的init方法被執行以後即bean初始化完成以後。postProcessAfterInitialization()方法是重點,本文及下一篇文章都是圍繞着這個方法來的。html
該方法是實如今其父類中的AbstractAutoProxyCreator,咱們先來看一下其實現:spring
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { // 根據給定的bean的class和name構件key,格式:beanClassName_beanName Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.containsKey(cacheKey)) { // 若是它適合被代理,則在這裏面生成代理類 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 若是已經處理過則再也不處理 if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) { return bean; } // 無需加強則直接返回 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 指定的bean類是否表明一個基礎設施類,基礎設施類不該被代理,或者配置了指定bean也不須要自動代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 若是存在Advice則建立代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // 若是獲取到了加強則須要針對加強建立代理 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 建立代理 Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }
在上面的函數中咱們已經能夠看到代理建立的雛形,固然,在真正開始以前還須要通過一系列判斷,好比是否已經處理過或者是不是須要跳過的bean,而真正建立代理是從getAdvicesAndAdvisorsForBean開始的。
建立代理主要包含了兩個步驟:express
這裏雖然看起來只有簡單的兩步,可是每一步中都有着大量複雜的邏輯。本文先來看看獲取加強方法的實現邏輯。緩存
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) { List advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
對於某個bean的加強方法的獲取也是包含兩個步驟的,獲取全部的加強以及尋找全部加強中適用於bean的加強並應用,而findCandidateAdvisors()與findAdvisorsThatCanApply()即是作了這兩件事情。這裏若是沒法找到對應的加強器則直接返回DO_NOT_PROXY,也就是null。app
這裏咱們分析的是註解方式的AOP,對於findCandidateAdvisors的實現實際上是由AnnotationAwareAspectJAutoProxyCreator類來完成的,繼續跟蹤:ide
protected List<Advisor> findCandidateAdvisors() { // 使用註解方式配置AOP的時候並不會丟棄對XML配置的支持,在這裏會調用父類方法去加載配置文件中的AOP聲明 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
AnnotationAwareAspectJAutoProxyCreator間接繼承了AbstractAdvisorAutoProxyCreator,在實現獲取加強的方法中除了保留父類的獲取配置文件中定義的加強外,同時增長了獲取Bean的註解加強的功能,這部分實現是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()來完成的。函數
這裏其實能夠本身先嚐試想象一下解析思路,看看本身的實現與Spring是否有差異?咱們能夠先在本身頭腦中嘗試實現一下獲取加強這個功能點,看看是否有思路。實際上,Spring在實現的時候主要分紅了四步:post
咱們來看看Spring如何實現對全部的類進行分析並提取Advisor:學習
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = null; synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<Advisor>(); aspectNames = new LinkedList<String>(); // 獲取全部的beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); // 遍歷全部的beanName找出對應的加強方法 for (String beanName : beanNames) { // 不合法的bean則略過,由子類定義規則,默認返回true if (!isEligibleBean(beanName)) { continue; } // 獲取對應的bean的類型 Class beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 若是該bean上存在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 { // 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.EMPTY_LIST; } // 記錄緩存 List<Advisor> advisors = new LinkedList<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; }
到這裏已經完成了Advisor的提取,在上面步驟中最爲重要也最爲複雜的就是加強器的獲取,這一功能是委託給getAdvisors方法來實現(this.advisorFactory.getAdvisors(factory))。 ui
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) { // 獲取標記爲AspectJ的類及其名字,並驗證 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. final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(maaif); final 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 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; }
上面函數中首先完成了對加強器的獲取,包括獲取註解以及根據註解生成加強的步驟,而後考慮到在配置中可能會將加強配置成延遲初始化,那麼須要在首位加入同步實例化加強器以保證加強使用以前的實例化,最後是對DeclareParents註解的獲取,這裏着重分析對加強器的獲取。
對普通加強器的獲取邏輯是實如今getAdvisor方法中的,實現步驟包括對切點的註解的獲取以及根據註解信息生成加強。
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { validate(aif.getAspectMetadata().getAspectClass()); // 切點信息的獲取 AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass()); if (ajexp == null) { return null; } // 根據切點信息生成加強器 return new InstantiationModelAwarePointcutAdvisorImpl( this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName); }
所謂獲取切點信息就是指定註解的表達式信息的獲取,如@Before("test()")。
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 獲取方法上的註解 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 使用AspectJExpressionPointcut實例封裝獲取的信息 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]); // 提取獲得的註解中的表達式,如: // @Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))") ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); return ajexp; } protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) { // 設置敏感的註解類 Class<? extends Annotation>[] classesToLookFor = new Class[] { Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class}; for (Class<? extends Annotation> c : classesToLookFor) { AspectJAnnotation foundAnnotation = findAnnotation(method, c); if (foundAnnotation != null) { return foundAnnotation; } } return null; } // 獲取指定方法上的註解並使用AspectJAnnotation封裝 private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { A result = AnnotationUtils.findAnnotation(method, toLookFor); if (result != null) { return new AspectJAnnotation<A>(result); } else { return null; } }
全部的加強都是由Advisor的實現類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. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); this.pointcut = declaredPointcut; this.lazy = false; } }
在封裝過程當中只是簡單地將信息封裝在類的實例中,全部的信息單純地賦值,在實例初始化的過程當中還完成了對於加強器的初始化。由於不一樣的加強所體現的邏輯是不一樣的,好比@Before("test()")與@After("test()")標籤的區別就是加強器加強的位置不一樣,因此就須要不一樣的加強器來完成不一樣的邏輯,而根據註解中的信息初始化對應的加強器就是在instantiateAdvice函數中實現的。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { return this.atAspectJAdvisorFactory.getAdvice( this.method, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); } public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName) { Class<?> candidateAspectClass = aif.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); } AbstractAspectJAdvice springAdvice; // 根據不一樣的註解類型封裝不一樣的加強器 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... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrderInAspect); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
從上面能夠看到,Spring會根據不一樣的註解生成不一樣的加強器,例如AtBefore會對應AspectJMethodBeforeAdvice,在AspectJMethodBeforeAdvice中完成了加強方法的邏輯。本文嘗試分析幾個經常使用的加強器實現。
這是前置加強器,在Spring中,它會封裝到MethodBeforeAdviceInterceptor類的內部,這個是一個攔截器,會被放在攔截器鏈中,在建立代理bean時會用到:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { private MethodBeforeAdvice advice; /** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); } }
其中的屬性MethodBeforeAdvicce就表明着前置加強的AspectJMethodBeforeAdvice,跟蹤其before()方法:
public void before(Method method, Object[] args, Object target) throws Throwable { invokeAdviceMethod(getJoinPointMatch(), null, null); } protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable { return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex)); } protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable { Object[] actualArgs = args; if (this.aspectJAdviceMethod.getParameterTypes().length == 0) { actualArgs = null; } try { ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); // 激活加強方法 return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); } catch (IllegalArgumentException ex) { throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", ex); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } }
invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是對應於前置加強的方法,在這裏實現了調用。
後置加強與前置加強有稍許不一致的地方。回顧上面講過的前置加強,大體的結構是在攔截器鏈中放置MethodBeforeAdviceInterceptor,並在MethodBeforeAdviceInterceptor中又放置了AspectJMethodBeforeAdvice,在調用inovke時首先串聯調用。可是在後置加強的時候倒是不同的,沒有提供如MethodBeforeAdviceInterceptor的中間類,而是直接實現MethodInterceptor接口,並在攔截器鏈中使用了中間的AspectAfterAdvice。
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice { public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { // 激活加強方法 invokeAdviceMethod(getJoinPointMatch(), null, null); } } }
前面已經把全部加強器的獲取分析完了,可是對於全部加強來講,並不必定都適用於當前的Bean,還要挑選出適合的加強器,也就是知足咱們配置的通配符的加強器。這部分的具體實如今findAdvisorsThatCanApply中。
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 過濾已經獲得的advisors return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<Advisor>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
findAdvisorsThatCanApply函數的主要功能是尋找全部加強器中適用於當前class的加強器,而對於真正的匹配實際上是在canApply中實現的。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { Method[] methods = clazz.getMethods(); for (Method method : methods) { if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
這裏的邏輯也不是很複雜,無非就是根據advisor中封裝的classFilter來判斷是否match對應的類。
本文主要學習了Spring AOP核心實現原理中的對加強方法的獲取,主要包含兩個步驟:
下文會聚焦在AOP核心實現原理的另外一部分--代理的建立。