經過註解的方式來實現AOP
1. @EnableAspectJAutoProxy經過@Import註解向容器中注入了AspectJAutoProxyRegistrar這個類,而它在容器中的名字是org.springframework.aop.config.internalAutoProxyCreator。
2. AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口,因此能夠向容器中註冊Bean的定義信息。
3. 經過跟蹤AspectJAutoProxyRegistrar,咱們發現它向容器中註冊了AnnotationAwareAspectJAutoProxyCreator的定義信息。
4. 觀察AnnotationAwareAspectJAutoProxyCreator的繼承結構圖,發現,它既是一個後置處理器,又是一個BeanFactoryAware的實現類。
因此咱們能夠分析:
1、 AnnotationAwareAspectJAutoProxyCreator做爲後置處理器作了什麼?
2、 做爲Aware作了什麼?
AnnotationAwareAspectJAutoProxyCreator的繼承結構圖,以下: AnnotationAwareAspectJAutoProxyCreator -> extends AspectJAwareAdvisorAutoProxyCreator -> extends AbstractAdvisorAutoProxyCreator -> extends AbstractAutoProxyCreator -> implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware 【可見AnnotationAwareAspectJAutoProxyCreator是一個後置處理器,也是一個Aware】 AbstractAutoProxyCreator做爲一個抽象類,實現了SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware 故,咱們分別在他們的實現方法上加斷點,好比:postProcessBeforeInstantiation()和setBeanFactory()
首先來到AbstractAutoProxyCreator的setBeanFactory(),查看IDE的調用棧,如圖:
1. 傳入配置類,建立IOC容器 2. 註冊配置類,調用refresh()刷新容器 3. registerBeanPostProcessors(beanFactory)註冊Bean的後置處理器,來攔截Bean的建立。 1) 先獲取IOC容器已經定義了的須要建立對象的全部BeanPostProcessor 2) 給容器中添加另外其餘的BeanPostProcessor 3) 優先註冊實現了PriorityOrdered接口的BeanPostProcessor 4) 再註冊實現Order接口的BeanPostProcessor 5) 最後註冊沒實現任何接口的BeanPostProcessor 6) 註冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,並保存在容器中 如何建立名字叫internalAutoProxyCreator【AnnotationAwareAspectJAutoProxyCreator】的後置處理器? 1) 先來建立Bean的實例 2) populateBean()給Bean的屬性賦值 3) initializeBean()初始化Bean 1) invokeAwareMethods(beanName, bean)處理Aware接口的方法回調 2) applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName) 拿到全部的BeanPostProcessor並執行postProcessBeforeInitialization 3) invokeInitMethods(beanName, wrappedBean, mbd)執行自定義的初始化方法,好比init()和destroy() 4) applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) 拿到全部的BeanPostProcessor並執行postProcessAfterInitialization 4) BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】建立成功 7) 把BeanPostProcessor註冊並添加到BeanFactory中 ==========以上是建立和註冊AnnotationAwareAspectJAutoProxyCreator的過程==========
4. finishBeanFactoryInitialization(beanFactory)完成BeanFactory的初始化工做,建立剩下的單實例Bean 1)遍歷獲取全部的Bean,依次建立對象getBean(beanName) getBean -> doGetBean() -> getSingleton() 2)如何建立Bean? 【首先說明:上面註冊過的後置處理器AnnotationAwareAspectJAutoProxyCreator會在全部Bean建立以前進行攔截調用,由於 AnnotationAwareAspectJAutoProxyCreator實現了InstantiationAwareBeanPostProcessor接口】 1)先從緩存中獲取當前Bean,若是能獲取到,說明Bean是以前被建立過了的,直接使用,不然再進行建立 只要被建立過的Bean都會被緩存起來 2)createBean()建立Bean的實例,過程以下: 1)resolveBeforeInstantiation(beanName, mbdToUse)這一步是嘗試返回Bean的代理對象 但願後置處理器在此能返回一個代理對象,若是不能就調用doCreateBean()建立對象 如何返回代理對象呢? if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } 【注意:這裏的applyBeanPostProcessorsBeforeInstantiation不一樣於BeanPostProcessor的postProcessBeforeInitialization】 【applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization屬於InstantiationAwareBeanPostProcessor的方法 而InstantiationAwareBeanPostProcessor是在建立Bean對象實例以前進行調用,目的是在建立Bean對象以前首先嚐試返回代理對象, 但BeanPostProcessor的兩個方法則是在Bean對象建立完成,進行初始化的先後才進行調用,他們兩個執行的時機不同BeanPostProcessor的執行稍微晚一點】 2)doCreateBean(beanName, mbdToUse, args)此方法纔是真正的建立一個Bean實例,建立實例的流程和上面同樣
AnnotationAwareAspectJAutoProxyCreator實現了InstantiationAwareBeanPostProcessor因此每個Bean在建立以前,都會通過 postProcessBeforeInstantiation()方法。固然也包括被切的實體。 1. 每一個Bean在建立以前都會通過postProcessBeforeInstantiation()過程分析: 1)判斷當前Bean是否在advisedBeans(裏面保存了須要加強的Bean)中。 this.advisedBeans.containsKey(cacheKey) 2)判斷當前Bean是不是基礎類型(Advice,Pointcut,Advisor,AopInfrastructureBean)。 isInfrastructureClass(beanClass) 3)是否須要跳過?(好像永遠要跳過^_^) shouldSkip(beanClass, beanName) 這個方法首先獲取候選的加強器List<Advisor> candidateAdvisors = findCandidateAdvisors(); 每個Advisor的類型是InstantiationModelAwarePointcutAdvisor,並非AspectJPointcutAdvisor 2. 通過postProcessBeforeInstantiation()嘗試建立對象出來之後,進入AbstractAutoProxyCreator的postProcessAfterInitialization方法 postProcessAfterInitialization方法中有一個wrapIfNecessary(bean, beanName, cacheKey)開始進行包裝Bean,點擊進入: 1)Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 找到全部的加強器,並獲取到能在該Bean使用的加強器,而後順便排序(目的是爲了有序的切入) 2)保存當前Bean到advisedBeans中 this.advisedBeans.put(cacheKey, Boolean.TRUE) 3)若是當前Bean須要加強,就建立當前Bean的代理對象 Object proxy = createProxy(...),如何建立?以下: 1. 獲取全部通知方法 2. 保存到proxyFactory中 3. 建立代理對象,Spring自動決定 new JdkDynamicAopProxy(config);實現接口 ObjenesisCglibAopProxy(config);沒有實現接口 4)經過以上三步,wrapIfNecessary()方法會返回一個代理Bean而且放到容器中,當調用目標方法的時候,其實是代理類在調用