Spring系列(五):Spring AOP原始碼解析
一、@EnableAspectJAutoProxy註解
在主配置類中新增@EnableAspectJAutoProxy註解,開啟aop支援,那麼@EnableAspectJAutoProxy到底做了什麼?接下來分析下:
@EnableAspectJAutoProxy點進去如下:
此時看到了我們非常熟悉的@Import註解,@Import(AspectJAutoProxyRegistrar.class),進入到AspectJAutoProxyRegistrar發現實現了ImportBeanDefinitionRegistrar如下:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
會呼叫registerBeanDefinitions方法,跟進到這個方法裡面,主要作用就是往Spring容器中註冊AnnotationAwareAspectJAutoProxyCreator的Bean的定義資訊:
二、AnnotationAwareAspectJAutoProxyCreator繼承圖
三、AnnotationAwareAspectJAutoProxyCreator建立代理
首先AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了BeanFactoryAware介面:
所以在建立AnnotationAwareAspectJAutoProxyCreatorBean的過程中初始化方法裡面會呼叫setBeanFactory方法:
在setBeanFactory方法裡面呼叫initBeanFactory來初始化通知者檢索幫助類,後面檢索通知會用到。
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); }
其次AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了InstantiationAwareBeanPostProcessor介面:
該介面定義了2個方法:postProcessBeforeInstantiation和postProcessAfterInstantiation,所以AbstractAutoProxyCreator實現了這2個方法;還記得我們在Spring IoC原始碼解析篇分析到如下程式碼:
resolveBeforeInstantiation方法進去就會調到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法
/** * 在建立Bean的流程中還沒呼叫構造器來例項化Bean的時候進行呼叫(例項化前後) * AOP解析切面以及事務解析事務註解都是在這裡完成的 * @param beanClass 當前正在建立的Bean的Class物件 * @param beanName beanName * @return * @throws BeansException */ @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { //構建我們的快取key Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //如果被解析過直接返回 if (this.advisedBeans.containsKey(cacheKey)) { return null; } /** * 判斷是不是基礎的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)是就直接跳過 * 判斷是不是應該跳過 (AOP解析直接解析出我們的切面資訊(並且把我們的切面資訊進行快取),而事務在這裡是不會解析的) */ 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(beanClass, beanName)方法(很重要):
protected boolean shouldSkip(Class<?> beanClass, String beanName) { /** * 找到候選的Advisors(通知者或者增強器物件) */ List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } return super.shouldSkip(beanClass, beanName); }
接下來看如何找候選的Advisors,findCandidateAdvisors()方法如下:
@Override protected List<Advisor> findCandidateAdvisors() { //找出事務相關的advisor List<Advisor> advisors = super.findCandidateAdvisors(); //找出Aspect相關的資訊之後封裝為一個advisor if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } //返回我們所有的通知 return advisors; }
第一步找事務相關的Advisor:
protected List<Advisor> findCandidateAdvisors() { Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); /** * 通過通知者檢測幫助類來幫助我們找到通知 * */ return this.advisorRetrievalHelper.findAdvisorBeans(); }
第二步找構建AspectJAdvisors:
/** * 去容器中獲取到所有的切面資訊儲存到快取中 */ public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; //快取欄位aspectNames沒有值 注意例項化第一個單例項bean的時候就會觸發解析切面 if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { //用於儲存所有解析出來的Advisors集合物件 List<Advisor> advisors = new ArrayList<>(); //用於儲存切面的名稱的集合 aspectNames = new ArrayList<>(); /** * AOP功能中在這裡傳入的是Object物件,代表去容器中獲取到所有的元件的名稱,然後再 * 進行遍歷,這個過程是十分的消耗效能的,所以說Spring會再這裡加入了儲存切面資訊的快取。 * 但是事務功能不一樣,事務模組的功能是直接去容器中獲取Advisor型別的,選擇範圍小,且不消耗效能。 * 所以Spring在事務模組中沒有加入快取來儲存我們的事務相關的advisor */ String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); //遍歷我們從IOC容器中獲取處的所有Bean的名稱 for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } //通過beanName去容器中獲取到對應class物件 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } //根據class物件判斷是不是切面 @Aspect if (this.advisorFactory.isAspect(beanType)) { //是切面類 //加入到快取中 aspectNames.add(beanName); //把beanName和class物件構建成為一個AspectMetadata AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //構建切面註解的例項工廠 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); //真正的去獲取我們的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 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; }
① org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#isAspect:
② 真正的去獲取我們的Advisor,this.advisorFactory.getAdvisors(factory)方法如下:
@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { //獲取我們的標記為Aspect的類 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //獲取我們的切面類的名稱 String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); //校驗我們的切面類 validate(aspectClass); //我們使用的是包裝模式來包裝我們的MetadataAwareAspectInstanceFactory構建為MetadataAwareAspectInstanceFactory MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); //獲取到切面類中的所有方法,但是該方法不會解析到標註了@PointCut註解的方法 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; }
獲取切面上的通知方法,並按照規則排序,getAdvisorMethods(aspectClass):
private List<Method> getAdvisorMethods(Class<?> aspectClass) { final List<Method> methods = new ArrayList<>(); ReflectionUtils.doWithMethods(aspectClass, method -> { if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) { methods.add(method); } }); methods.sort(METHOD_COMPARATOR); return methods; }
排序(該順序在代理呼叫的時候會用到)規則如下:
根據通知的方法建立增強器:getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName)如下:
public 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; } //例項化我們的切面通知物件 return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
例項化我們的切面通知物件,new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName):
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { //當前的切點表示式 this.declaredPointcut = declaredPointcut; //切面的class物件 this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); //切面方法的名稱 this.methodName = aspectJAdviceMethod.getName(); //切面方法的引數型別 this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); //切面方法物件 this.aspectJAdviceMethod = aspectJAdviceMethod; //aspectj的通知工廠 this.aspectJAdvisorFactory = aspectJAdvisorFactory; //aspect的例項工廠 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; //將切面中的通知構造為advice通知物件 this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
將切面中的通知構造為advice通知物件,instantiateAdvice(this.declaredPointcut):
獲取通知getAdvice方法如下:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { //獲取我們的切面類的class物件 Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); //獲取切面方法上的註解 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); //解析出來的註解資訊是否為null 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()) { //是PointCut註解 那麼就丟擲異常 因為在外面傳遞進來的方法已經排除了Pointcut的方法 case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; //環繞通知 構建AspectJAroundAdvice case AtAround: springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //前置通知 構建AspectJMethodBeforeAdvice case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //後置通知 AspectJAfterAdvice case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //返回通知 AspectJAfterReturningAdvice case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; //異常通知 AspectJAfterThrowingAdvice 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); } //設定我們構建出來的通知物件的相關屬性比如DeclarationOrder,在代理呼叫的時候,責任鏈順序上會用到 springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
至此真正的去獲取我們的Advisor方法解析完成,List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
③ 如果該切面是單例項的就加入到快取中:
④ 遍歷所有的切面,將每個切面的所有的增強器新增在advisors中進行返回:
AbstractAutoProxyCreator.shouldSkip()方法中的List<Advisor> candidateAdvisors = findCandidateAdvisors();返回找到的候選的增強器,然後再呼叫父類的shouldSkip()返回false,就是不跳過的意思
執行完shouldSkip()返回到AbstractAutoProxyCreator.postProcessBeforeInstantiation的方法,至此postProcessBeforeInstantiation執行完成。
最後AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了Bean的後置處理器BeanPostProcessor介面:
該介面有2個方法:postProcessBeforeInitialization和postProcessAfterInitialization,其中在postProcessAfterInitialization方法主要就是通過前面建立的增強器來建立代理物件
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { //獲取快取key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { //如果有必要就代理 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
進入如果必要就代理方法,wrapIfNecessary(bean, beanName, cacheKey):
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //已經被處理過 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //不需要增強的 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是不是基礎的bean 是不是需要跳過的 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } //如果有匹配的通知,就建立代理物件 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; }
① 獲取匹配的通知方法,getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null):
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { //找合適的增強器物件 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); //若為空表示沒找到 if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
跟進到找合適的增強器物件方法,findEligibleAdvisors(beanClass, beanName):
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //找到Spring IoC容器中所有的候選通知 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //判斷找到的通知能不能作用到當前的類上 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); //對我們的advisor進行排序 if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
跟進到判斷找到的通知能不能作用到當前的類上方法,findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName):
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //從候選的通知器中找到合適正在建立的例項物件的通知器 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
跟進到從候選的通知器中找到合適正在建立的例項物件的通知器方法,AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass):
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { //若候選的增強器集合為空 直接返回 if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } //定義一個合適的增強器集合物件 List<Advisor> eligibleAdvisors = new ArrayList<>(); //迴圈我們候選的增強器物件 for (Advisor candidate : candidateAdvisors) { //判斷我們的增強器物件是不是實現了IntroductionAdvisor (很明顯我們事務的沒有實現 所以不會走下面的邏輯) if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } //不為空 boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { //判斷我們的增強器物件是不是實現了IntroductionAdvisor (很明顯我們事務的沒有實現 所以不會走下面的邏輯) if (candidate instanceof IntroductionAdvisor) { //在上面已經處理過 ,不需要處理 continue; } /** * 真正的判斷增強器是否合適當前型別 */ if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
跟進到是否能用方法,canApply(candidate, clazz, hasIntroductions):
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { //判斷我們的增強器是否是IntroductionAdvisor if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } //判斷我們事務的增強器BeanFactoryTransactionAttributeSourceAdvisor是否實現了PointcutAdvisor else if (advisor instanceof PointcutAdvisor) { //轉為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; } }
跟進到找到真正能用的增強器方法,canApply(pca.getPointcut(), targetClass, hasIntroductions):
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(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } //判斷匹配器是不是IntroductionAwareMethodMatcher IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } //建立一個集合用於儲存targetClass的class物件 Set<Class<?>> classes = new LinkedHashSet<>(); //判斷當前class是不是代理的class物件 if (!Proxy.isProxyClass(targetClass)) { //加入到集合中去 classes.add(ClassUtils.getUserClass(targetClass)); } //獲取到targetClass所實現的介面的class物件,然後加入到集合中 classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); //迴圈所有的class物件 for (Class<?> clazz : classes) { //通過class獲取到所有的方法 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); //迴圈我們的方法 for (Method method : methods) { //通過methodMatcher.matches來匹配我們的方法 if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : //通過方法匹配器進行匹配 methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
如果該方法返回true就表示匹配,就新增到合適的集合eligibleAdvisors中,遍歷完所有的候選增強器後,debug截圖如下:
返回到AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法中,然後擴充套件增強器,如果合適的增強器列表不是空的就排序。
返回到AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean,如果空就表示不需要代理,不為空就表示需要代理。
② 真正建立代理物件,Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)):
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } //建立一個代理物件工廠 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //為proxyFactory設定建立jdk還是cglib代理 if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } //把我們的specificInterceptors陣列中的Advisor轉化為陣列形式的 Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); //為我們的代理工加入通知器, proxyFactory.addAdvisors(advisors); //設定targetSource物件 proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } //真正建立代理物件 return proxyFactory.getProxy(getProxyClassLoader()); }
跟進到真正建立代理物件方法,proxyFactory.getProxy(getProxyClassLoader()):
public Object getProxy(@Nullable ClassLoader classLoader) { //createAopProxy() 用來建立我們的代理工廠 return createAopProxy().getProxy(classLoader); }
跟進到建立AOP代理方法,createAopProxy():
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
跟進到getAopProxyFactory().createAopProxy(this):
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //判斷我們是否指定使用cglib代理ProxyTargetClass =true 預設false if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { 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."); } //targetClass是介面使用的就是jdk代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //cglib代理 return new ObjenesisCglibAopProxy(config); } else { //jdk動態代理 return new JdkDynamicAopProxy(config); } }
跟進到建立動態代理(注意這個是jdk的,cglib同理)方法,getProxy(classLoader):
public Object getProxy(@Nullable 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); //建立jdk動態代理 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
有沒有眼前一亮:該方法用來建立我們的代理物件,如果proxyTargetClass = true,建立cglib代理 ,為false,如果代理類沒有實現介面也建立cglib代理,否則建立jdk代理
至此AnnotationAwareAspectJAutoProxyCreator建立動態代理完成!!
四、AOP動態代理invoke
以JdkDynamicAopProxy為例,CGLIB動態代理參照Jdk動態代理自行分析
根據到JdkDynamicAopProxy的invole方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; //獲取到我們的目標物件 TargetSource targetSource = this.advised.targetSource; Object target = null; try { //若是equals方法不需要代理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } //若是hashCode方法不需要代理 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } //若是DecoratingProxy也不要攔截器執行 else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; /** * 這個配置是暴露我們的代理物件到執行緒變數中,需要搭配@EnableAspectJAutoProxy(exposeProxy = true)一起使用
* 比如在目標物件方法中再次獲取代理物件可以使用這個AopContext.currentProxy() * 還有的就是事務方法呼叫事務方法的時候也是用到這個 */ if (this.advised.exposeProxy) { //把我們的代理物件暴露到執行緒變數中 oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } //獲取我們的目標物件 target = targetSource.getTarget(); //獲取我們目標物件的class Class<?> targetClass = (target != null ? target.getClass() : null); //把aop的advisor轉化為攔截器鏈 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //如果攔截器鏈為空 if (chain.isEmpty()) { //通過反射直接呼叫執行 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { //建立一個方法呼叫物件 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //呼叫執行 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
跟進到invocation.proceed()方法,該方法的呼叫用到了遞迴和責任鏈設計模式:
public Object proceed() throws Throwable { //從-1開始,下標=攔截器的長度-1的條件滿足表示執行到了最後一個攔截器的時候,此時執行目標方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //獲取第一個方法攔截器使用的是前++ Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
跟進到((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)方法,責任鏈模式,執行順序如下:
① ExposeInvocationInterceptor.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } }
② AspectJAfterThrowingAdvice.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { try { //執行下一個通知/攔截器 return mi.proceed(); } catch (Throwable ex) { //丟擲異常 if (shouldInvokeOnThrowing(ex)) { //執行異常通知 invokeAdviceMethod(getJoinPointMatch(), null, ex); } throw ex; } }
③ AfterReturningAdviceInterceptor.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { //執行下一個通知/攔截器 Object retVal = mi.proceed(); //返回通知方法 this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
④ AspectJAfterAdvice.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { try { //執行下一個通知/攔截器 return mi.proceed(); } finally { //後置通知的方法總是會被執行 原因就在這finally invokeAdviceMethod(getJoinPointMatch(), null, null); } }
⑤ AspectJAroundAdvice.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); } ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); JoinPointMatch jpm = getJoinPointMatch(pmi); return invokeAdviceMethod(pjp, jpm, null, null); }
⑥ MethodBeforeAdviceInterceptor.invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable { //執行前置通知的方法 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); //執行下一個通知/攔截器,但是該攔截器是最後一個了,所以會呼叫目標方法 return mi.proceed(); }
執行的執行順序如下:
總結:通過@EnableAspectJAutoProxy註解開啟AOP功能,該註解為我們Spring容器中註冊了AnnotationAwareAspectJAutoProxyCreator元件,AOP的準備和代理建立都在這個元件中完成,AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了InstantiationAwareBeanPostProcessor介面,在方法postProcessBeforeInstantiation中找到Spring容器中所有的增強器,為建立代理做準備;AnnotationAwareAspectJAutoProxyCreator繼承了AbstractAutoProxyCreator實現了BeanPostProcessor介面,在方法postProcessAfterInitialization中通過前面找到的候選增強器中找到合適的增強器來建立代理物件,最後呼叫目標方法,進去到代理物件的invoke方法中進行呼叫。
&n