SpringAop源碼分析:需要關聯SpringBean的生命週期
思考:
1.什麼時候創建代理類對象
2.SpringAop中如何綜合運用CGLIB和JDK動態代理
@EnableAspectJAutoProxy:開啓AOP的權限
注入到Spring容器中
ImportBeanDefinitionRegistrar手動註冊Bean對象
在前幾章中提過,實現ImportBeanDefinitionRegistrar這個接口,可以自己手動註冊一些Bean到Spring容器中
AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar就可以手動註冊Bean對象
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //這裏手動註冊Bean 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); } } } }
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null); }
註冊或者升級AnnotationAwareAspectJAutoProxyCreator
對於AOP的實現,基本上都是靠AnnotationAwareAspectJAutoProxyCreator去完成的,它可以根據@Point註解定義的切點來自動代理相匹配的bean。
但是爲了配置簡便,Spring使用了自定義配置來幫助我們自動註冊AnnotationAwareAspectJAutoProxyCreator,其註冊過程就是在這裏實現的。
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) { return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); }
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); //如果已經存在了自動代理創建器且存在的自動代理創建器與現在的不一致,那麼需要根據優先級來判斷到底使用哪一個 if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) { BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator"); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { //改變Bean最重要的就是改變bean所對應的屬性className屬性 apcDefinition.setBeanClassName(cls.getName()); } } //如果已經存在自動代理創建器並且與將要創建的一致,那麼無須再次創建 return null; } else { RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", -2147483648); beanDefinition.setRole(2); registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition); return beanDefinition; } }
以上代碼實現了自動註冊AnnotationAwareAspectJAutoProxyCreator類的功能,同時這裏還涉及到了一個優先級的問題,
如果已經存在了自動代理創建器,而且存在的自動代理創建器與現在的不一致,那麼需要根據優先級來判斷到底使用哪一個。
綜上:總結下
1.@EnableAspectJAutoProxy:開啓AOP的權限
2.@Import(AspectJAutoProxyRegistrar.class)注入到容器中,手動註冊切面類
3.AnnotationAwareAspectJAutoProxyCreator需要將這個類注入到IOC容器中
4.registerBeanDefinition註冊Bean信息內容:
##BeanId=org.springframework.aop.config.internalAutoProxyCreator
##class:AnnotationAwareAspectJAutoProxyCreator
我們打印下注冊的Bean
1無參構造函數....說明對象初開始始化了
2執行自定義bean的init方法
beanDefinitionNames[i]:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
beanDefinitionNames[i]:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
beanDefinitionNames[i]:org.springframework.context.annotation.internalRequiredAnnotationProcessor
beanDefinitionNames[i]:org.springframework.context.annotation.internalCommonAnnotationProcessor
beanDefinitionNames[i]:org.springframework.context.event.internalEventListenerProcessor
beanDefinitionNames[i]:org.springframework.context.event.internalEventListenerFactory
beanDefinitionNames[i]:myConfig
beanDefinitionNames[i]:memberServiceImpl
beanDefinitionNames[i]:payService
beanDefinitionNames[i]:loginAop
beanDefinitionNames[i]:org.springframework.aop.config.internalAutoProxyCreator //這個就是我們分析注入的Bean
AnnotationAwareAspectJAutoProxyCreator
後面我們需要了解SpringAOP底層是如何實現的 離不開AnnotationAwareAspectJAutoProxyCreator
下面看看AnnotationAwareAspectJAutoProxyCreator類圖結構
在類圖中,我們看到:AnnotationAwareAspectJAutoProxyCreator的祖宗是BeanPostProcessors接口,而實現BeanPostProcessor後,當Spring加載這個Bean時會在實例化前調用其postProcessorAfterInitialization方法。
BeanPostProcessors是對我們的Bean的初始化方法實現增強。由Java多態,可知AnnotationAwareAspectJAutoProxyCreator也是可以實現對Bean初始化方法增強。
所以AnnotationAwareAspectJAutoProxyCreator本質就是對init方法實現增強
public interface BeanPostProcessor { @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {//init方法前置處理 return bean; } @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {//init方法後置處理 return bean; } }
AnnotationAwareAspectJAutoProxyCreator的前置和後置在AbstractAutoProxyCreator實現類中實現
AbstractAutoProxyCreator的BeanPostProcessor後置處理器的前置處理器:沒做任何事
public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; }
AbstractAutoProxyCreator的BeanPostProcessor後置處理器的後置處理器:具體做事情,使用後置處理器實現代理對象的創建
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { //根據給定的bean的class和name構建出一個key,格式:beanClassName_beanName Object cacheKey = this.getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { //如果它適合被代理,則需要封裝指定的Bean return this.wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { //如果已經處理過 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; //無需增強 } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; //給定的bean類是否代表一個基礎設施類,基礎設施類不應被代理,或者配置了指定bean不需要自動代理 } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) { //如果存在增強方法則創建代理 Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null); //如果獲取到了增強則需要針對增強創建代理 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //創建代理 Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }
函數中我們已經看到了代理創建的雛形。當然真正開始之前還需要經過一些判斷,比如是否已經處理過或者是否是需要跳過的bean,而真正創建代理的代碼是從getAdvicesAndAdvisorsForBean開始的。
創建代理主要包含兩個步驟:
1.獲取增強方法或者增強器
2.根據獲取的增強進行代理
雖然看似簡單,但是每個步驟中都經歷了大量複雜的邏輯。首先來看看獲取增強方法的實現邏輯
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName); return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray(); }
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = this.findCandidateAdvisors();//獲取所有的增強 List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//尋找所有增強中適用於bean的增強並應用 this.extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = this.sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
對於指定bean的增強方法的獲取一定是包含兩個步驟的,獲取所有的增強以及尋找所有增強中適用於bean的增強並應用,那麼findCandidateAdvisors與findAdvisorsThatCanApply便是做了這兩件事情。
當然如果無法找到對應的增強器便返回DO_NOT_PROXY,其中DO_NOT_PROXY=null
獲取增強器
由於我們分析的是使用註解進行的AOP,所以對於findCandidateAdvisors的實現其實是由AnnotationAwareAspectJAutoProxyCreator類完成 的,
我們繼續跟蹤AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法。
protected List<Advisor> findCandidateAdvisors() { //當使用註解方式配置AOP的時候並不是丟棄了對XML配置的支持 //這裏調用父類方法加載配置文件中的AOP聲明 List<Advisor> advisors = super.findCandidateAdvisors(); if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
在真正研究代碼之前可以自己嘗試去想想解析思路,看看自己的實現與Spring的實現是否有差別?我們先看看函數提供的大概功能框架,讀者可以嘗試實現這些功能點,看看是否有思路
1、獲取所有beanName,,這一步驟中所有在beanFactory中註冊的bean都會被提起出來。
2、遍歷所有beanName,並找出聲明AspectJ註解的類,進行進一步的處理
3、對標記爲AspectJ註解的類進行增強器的提取
4、將提取結果加入緩存
現在我們進入buildAspectJAdvisors函數實現,對Spring中所有類進行分析,提取Advisor
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized(this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList(); List<String> aspectNames = new LinkedList(); //獲取所有的beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false); String[] var18 = beanNames; int var19 = beanNames.length; //循環所有的beanName找出對應的增強方法 for(int var7 = 0; var7 < var19; ++var7) { String beanName = var18[var7]; //不合法的bean則略過,由子類定義規則,默認返回true if (this.isEligibleBean(beanName)) { Class<?> beanType = this.beanFactory.getType(beanName); //如果存在Aspect註解 if (beanType != null && 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); //解析標記爲AspectJ註解中增強的方法 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); .... } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } else { //記錄在緩存中 List<Advisor> advisors = new LinkedList(); .... } }
至此我們已經完成看Advisor的提取,在上面的步驟中最爲重要的也最爲繁雜的就是增強的獲取。而這一功能委託給了this.advisorFactory.getAdvisors(factory);方法去實現
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { //獲取標記爲AspectJ的類 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //獲取標記爲AspectJ的name String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); //驗證 this.validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList(); Iterator var6 = this.getAdvisorMethods(aspectClass).iterator(); while(var6.hasNext()) { Method method = (Method)var6.next(); Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //如果尋找的增強器不爲空而且配置了增強延遲初始化,那麼需要在首位加入同步實例化增強器 Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } Field[] var12 = aspectClass.getDeclaredFields(); int var13 = var12.length; for(int var14 = 0; var14 < var13; ++var14) { Field field = var12[var14]; //獲取DeclareParents註解 Advisor advisor = this.getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
函數中首先完成了對增強器的獲取,包括獲取註解以及根據註解生成增強的步驟,然後考慮到在配置中可能會將增強配置成延遲初始化,那麼需要在首位加入同步實例化增強器以保證增強使用之前的實例化,
最後是對DeclareParents註解的獲取,下面詳細介紹下每個步驟:
1.普通增強器的獲取
實現步驟包括對切點的註解的獲取以及根據註解信息生成增強
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { this.validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //切點信息的獲取 AspectJExpressionPointcut expressionPointcut = this.getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); //根據切點信息生成增強器 return expressionPointcut == null ? null : new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); }
切點信息的獲取。所謂獲取切點信息就是指定註解的表達式信息的獲取,如:@Around("loginAop()")
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { //獲取方法上的註解 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } else { //使用AspectJExpressionPointcut實例封裝獲取的信息 AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]); //提取得到的註解中的表達式,如: @Pointcut("execution (* com.mayikt.service..*.*(..))")中的execution (* com.mayikt.service..*.*(..)) ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; } }
protected static AbstractAspectJAdvisorFactory.AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) { //設置敏感的註解類 Class<?>[] classesToLookFor = new Class[]{Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class}; Class[] var2 = classesToLookFor; int var3 = classesToLookFor.length; for(int var4 = 0; var4 < var3; ++var4) { Class<?> c = var2[var4]; AbstractAspectJAdvisorFactory.AspectJAnnotation<?> foundAnnotation = findAnnotation(method, c); if (foundAnnotation != null) { return foundAnnotation; } } return null; }
private static <A extends Annotation> AbstractAspectJAdvisorFactory.AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { //獲取指定方法上的註解並使用AspectJAnnotation封裝 A result = AnnotationUtils.findAnnotation(method, toLookFor); return result != null ? new AbstractAspectJAdvisorFactory.AspectJAnnotation(result) : null; }
根據切點信息生成增強。所有的增強都由Advisor的實現類InstantiationModelAwarePointcutAdvisorImpl統一封裝
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { .... if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); this.pointcut = new InstantiationModelAwarePointcutAdvisorImpl.PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { this.pointcut = this.declaredPointcut; this.lazy = false; this.instantiatedAdvice = this.instantiateAdvice(this.declaredPointcut); } }
在封裝過程中只是簡單的將信息封裝在類的實例中,所有的信息單純的賦值,在實例化過程中還完成了對於增強器的初始化。因爲不同的增強所體現的邏輯是不同的,
比如@Before("test()")與@After("test()")標籤的不同就是增強器增強的位置不同,所以就需要不同的增強器來完成不同的邏輯,而根據註解中的信息初始化對應的增強器就是在instantiateAdvice函數中實現的。
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; }
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { .... Object 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())) { ((AbstractAspectJAdvice)springAdvice).setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { ((AbstractAspectJAdvice)springAdvice).setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtPointcut: if (this.logger.isDebugEnabled()) { this.logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod); } .... }
從函數中可以看出,Spring會根據不同的註解生成不同的增強器,例如AtBefore會對應AspectJMethodBeforeAdvice,而在AspectJMethodBeforeAdvice中完成了增強方法的邏輯。
我們先分析幾個常用的增強器實現:
我們首先看下MethodBeforeAdviceInterceptor 類的內部實現
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable { //代表前置增強的AspectJMethodBeforeAdvice private MethodBeforeAdvice advice; 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(); } }
跟蹤before方法
public void before(Method method, Object[] args, @Nullable Object target) throws Throwable { this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null); }
protected Object invokeAdviceMethod(@Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable { return this.invokeAdviceMethodWithGivenArgs(this.argBinding(this.getJoinPoint(), jpMatch, returnValue, ex)); }
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable { Object[] actualArgs = args; if (this.aspectJAdviceMethod.getParameterCount() == 0) { actualArgs = null; } try { ReflectionUtils.makeAccessible(this.aspectJAdviceMethod); //激活增強方法 return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs); } catch (IllegalArgumentException var4) { throw new AopInvocationException("Mismatch on arguments to advice method [" + this.aspectJAdviceMethod + "]; pointcut expression [" + this.pointcut.getPointcutExpression() + "]", var4); } catch (InvocationTargetException var5) { throw var5.getTargetException(); } }
invokeAdviceMethodWithGivenArgs方法中的aspectJAdviceMethod正是對於前置增強的方法,在這裏實現了調用
AspectJAfterAdvice
後置增強與前置增強不一樣,前置增強是在攔截器鏈中放置MethodBeforeAdviceInterceptor,而在MethodBeforeAdviceInterceptor中又放置了AspectJMethodBeforeAdvice,並在調用invoke時首先串聯調用。
但是在後置增強的時候卻不一樣,沒有提供中間的類,而是直接在攔截器鏈中使用了中間的AspectJAfterAdvice。
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } public Object invoke(MethodInvocation mi) throws Throwable { Object var2; try { var2 = mi.proceed(); } finally { //激活增強的方法 this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null); } return var2; } public boolean isBeforeAdvice() { return false; } public boolean isAfterAdvice() { return true; } }
getAdvisor方法走完了,又回到我們的getAdvisors方法
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { //獲取標記爲AspectJ的類 Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); //獲取標記爲AspectJ的name String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); //驗證 this.validate(aspectClass); MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList(); Iterator var6 = this.getAdvisorMethods(aspectClass).iterator(); while(var6.hasNext()) { Method method = (Method)var6.next(); Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { //如果尋找的增強器不爲空而且配置了增強延遲初始化,那麼需要在首位加入同步實例化增強器 Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } Field[] var12 = aspectClass.getDeclaredFields(); int var13 = var12.length; for(int var14 = 0; var14 < var13; ++var14) { Field field = var12[var14]; //獲取DeclareParents註解 Advisor advisor = this.getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; }
增加同步器實例化增強器
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor { public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) { super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() { //目標方法前調用,類似Before public void before(Method method, Object[] args, @Nullable Object target) { //簡單初始化aspect aif.getAspectInstance(); } }); } }
獲取DeclareParents註解
private Advisor getDeclareParentsAdvisor(Field introductionField) { DeclareParents declareParents = (DeclareParents)introductionField.getAnnotation(DeclareParents.class); if (declareParents == null) { return null; } else if (DeclareParents.class == declareParents.defaultImpl()) { throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents"); } else { //使用DeclareParentsAdvisor對功能進行封裝 return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl()); } }
尋找匹配的增強器
前面的函數中已經完成了所有增強器的解析,但是對於所有的增強器來講,並不一定都適用於當前的bean,還要跳出適合的增強器,也就是滿足我們配置的通配符的增強器。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = this.findCandidateAdvisors(); //過濾已經得到的Advisors List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); this.extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = this.sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
繼續看findAdvisorsThatCanApply:
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); List var4; try { var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName((String)null); } return var4; }
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } else { List<Advisor> eligibleAdvisors = new LinkedList(); Iterator var3 = candidateAdvisors.iterator(); //首先處理引介增強 while(var3.hasNext()) { Advisor candidate = (Advisor)var3.next(); if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); Iterator var7 = candidateAdvisors.iterator(); while(var7.hasNext()) { Advisor candidate = (Advisor)var7.next(); //對於普通bean的處理 if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
具體做事的方法
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 { 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; } else { MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { return true; } else { IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher)methodMatcher; } Set<Class<?>> classes = new LinkedHashSet(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); Iterator var6 = classes.iterator(); while(var6.hasNext()) { Class<?> clazz = (Class)var6.next(); Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); Method[] var9 = methods; int var10 = methods.length; for(int var11 = 0; var11 < var10; ++var11) { Method method = var9[var11]; if (introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; } } }
創建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) { Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } } else { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }
在獲取所有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); if (!proxyFactory.isProxyTargetClass()) { //檢查設置和屬性 if (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { //添加代理接口 this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); //加入增強器 proxyFactory.addAdvisors(advisors); //設置需要代理的類 proxyFactory.setTargetSource(targetSource); //定製代理 this.customizeProxyFactory(proxyFactory); //用來控制代理工廠被配置後,是否還運行修改通知,默認false,不允許修改代理的配置 proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.getProxyClassLoader()); }
對於代理類創建及處理過程,Spring委託給了proxyFactory去處理,而在此函數中主要是對proxyFactory的初始化操作,進而對真正的創建代理做準備。
這些初始化的步驟如下:
1、獲取當前類的屬性
2、添加代理接口
3、封裝Advisor並加入到proxyFactory中
4、設置要代理的類
5、當然在Spring中還爲子類提供了定製函數customizeProxyFactory,子類可以在此函數中進行對proxyFactory的進一步封裝。
6、進行獲取代理操作
獲得五個通知
創建代理類
public Object getProxy(@Nullable ClassLoader classLoader) { return this.createAopProxy().getProxy(classLoader); }
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) { return new JdkDynamicAopProxy(config); } else { 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."); } else { return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); } } }
至此,我們已經完成 代理的創建,不管我們之前是否閱讀過Spring源代碼,但是都是或多或少聽過Spring的代理中JDKProxy的實現和CGLIBProxy的實現。
Spring是如何選取的呢?
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config))
從if中的判斷條件可以看到3個方面影響Spring的判斷
Optimize:用來控制CGLIB創建過程的代理是否使用激進的優化策略。除非完全瞭解AOP代理如何優化處理,否則不推薦用戶使用這個配置。目前這個屬性僅用於CGLIB代理,對於JDK動態代理(默認代理)無效。
ProxyTargetClas:這個屬性爲true時,目標類本身被代理而不是目標類的接口。如果這個屬性值設置爲true,CGLIB代理將會被創建
hasNoUserSuppliedProxyInterfaces:是否存在代理接口
SpringAOP總結:
1、配置@EnableAspectJAutoProxy:開啓AOP權限
2、@Import(AspectJAutoProxyRegistrar.class):往IOC容器中注入SpringAOP切面類
3、registerAspectJAnnotationAutoProxyCreatorIfNecessary():註冊切面類
4、AnnotationAwareAspectJAutoProxyCreator.class:註冊到IOC容器中,【AOP的入口】
5、AnnotationAwareAspectJAutoProxyCreator:祖宗是BeanPostProcessor接口,而實現BeanPostProcessor接口後,當Spring加載這個Bean會在實例化前調用其後置處理器實現增強
6、postProcessAfterInitialization:後置處理器【AOP實現核心邏輯】
####6.1、wrapIfNecessary()判斷該對象是否在AOP的掃包範圍內,真正創建代理類的地方
#########6.1.1、getAdvicesAndAdvisorsForBean創建代理對象包括獲取增強方法和根據獲取的增強進行代理
#########6.1.2、createAopProxy()判斷被代理類是否實現了接口,如果有實現了接口的化,是採用JDK動態代理,否則情況下就使用CGLIB代理
####6.2、根據條件判斷使用JdkDynamicAopProxy或者JdkDynamicAopProxy方法實現代理
####6.3、最終執行目標方法的時候,就會進入到JdkDynamicAopProxy 的invoke方法或者JdkDynamicAopProxy的intercept方法【後面講解】
####6.5、底層使用集合存放使用通知,然後再使用責任鏈設計模式循環的調用【後面講解】
本文參考:
參考書籍:Spring源碼深度解析