<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
@EnableAspectJAutoProxy
註解用於開啟AOP功能,那麼這個註解底層到底做了什麼呢?
檢視@EnableAspectJAutoProxy
的原始碼,發現它使用@Import
註解向Spring容器中注入了一個型別為AspectJAutoProxyRegistrar
的Bean:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 注入一個bean名字為org.springframework.aop.config.internalAutoProxyCreator的AspectJAwareAdvisorAutoProxyCreator AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { // proxyTargetClass為true AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { // exposeProxy為true AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar介面,而ImportBeanDefinitionRegistrar是spring提供的擴充套件點之一,主要用來向容器中注入BeanDefinition,spring會根據BeanDefinion來生成Bean。
那麼AspectJAutoProxyRegistrar到底向容器中注入了什麼BeanDefinion呢?
org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)
@Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null); } @Nullable public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( BeanDefinitionRegistry registry, @Nullable Object source) { // AnnotationAwareAspectJAutoProxyCreator return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); } @Nullable private static BeanDefinition registerOrEscalateApcAsRequired( Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } // 注入AspectJAwareAdvisorAutoProxyCreator RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
從原始碼可以發現AspectJAutoProxyRegistrar
向容器中注入了一個型別為AnnotationAwareAspectJAutoProxyCreator
的Bean。
那麼AnnotationAwareAspectJAutoProxyCreator
又是幹什麼的呢?
AnnotationAwareAspectJAutoProxyCreator
主要實現了三個介面(由父類別AbstractAutoProxyCreator
實現):
AnnotationAwareAspectJAutoProxyCreator的繼承結構:
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { /** * @see AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() */ // 獲取容器中所有的切面Advisor // 這裡返回的切面中的方法已經是有序的了,先按註解順序(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),再按方法名稱 List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 獲取所有能夠作用於當前Bean上的Advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); /** * @see AspectJAwareAdvisorAutoProxyCreator#extendAdvisors(java.util.List) */ // 往集合第一個位置加入了一個DefaultPointcutAdvisor extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { /** * @see AspectJAwareAdvisorAutoProxyCreator#sortAdvisors(java.util.List) */ // 這裡是對切面進行排序,例如有@Order註解或者實現了Ordered介面 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 獲取容器中所有的切面Advisor List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { // 這裡還需要解析@Aspect註解,生成Advisor advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); // InstantiationModelAwarePointcutAdvisorImpl for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { // IntroductionAdvisor型別為引入切面,具體型別為DeclareParentsAdvisor eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // PointCut中的ClassFilter.match 匹配類 // PointCut中的MethodMatcher.match 匹配方法 if (canApply(candidate, clazz, hasIntroductions)) { // @Aspect,型別為InstantiationModelAwarePointcutAdvisorImpl eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
代理物件的建立時機位於bean的初始化之後,因為代理物件內部還是需要去呼叫目標物件的方法,所以需要讓目標物件範例化並完成初始化後才會建立代理物件。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 先從快取中獲取代理物件 Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 按需生成代理物件 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
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; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. /** * @see AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class, java.lang.String, org.springframework.aop.TargetSource) */ // 獲取與當前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; }
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
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()) { // 進來說明proxyTargetClass=false,指定JDK代理 if (shouldProxyTargetClass(beanClass, beanName)) { // 進來這裡說明BD中有個屬性preserveTargetClass=true,可以BD中屬性設定的優先順序最高 proxyFactory.setProxyTargetClass(true); } else { // 這裡會判斷bean有沒有實現介面,沒有就只能使用CGlib evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); // 切面 proxyFactory.setTargetSource(targetSource); // 目標物件 customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } // 使用JDK或者CGlib建立代理物件 return proxyFactory.getProxy(getProxyClassLoader()); }
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
這裡主要看JDK動態代理的實現,Proxy.newProxyInstance()的第三個引數為InvocationHandler,而這裡傳的是this,也就是當前的類肯定實現了InvocationHandler介面。
由於是JDK動態代理,那麼代理方法的呼叫肯定會進入InvocationHandler.invoke()方法中,這裡的InvocationHandler的實現類為org.springframework.aop.framework.JdkDynamicAopProxy。
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
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 { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } 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; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); // 目標物件 Class<?> targetClass = (target != null ? target.getClass() : null); // 目標物件的型別 // Get the interception chain for this method. // 這裡會對方法進行匹配,因為不是目標物件中的所有方法都需要增強 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. // 沒有匹配的切面,直接通過反射呼叫目標物件的目標方法 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. /** * @see ReflectiveMethodInvocation#proceed() */ // 這裡才是增強的呼叫,重點,火炬的傳遞 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); } } }
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // 執行到最後一個Advice,才會到這裡執行目標方法 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. // dm.isRuntime()=true的走這 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); if (dm.methodMatcher.matches(this.method, 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 { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. // 走這 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
interceptorsAndDynamicMethodMatchers中第一個advice為org.springframework.aop.interceptor.ExposeInvocationInterceptor。
org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
private static final ThreadLocal<MethodInvocation> invocation = new NamedThreadLocal<>("Current AOP method invocation"); public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } }
ExposeInvocationInterceptor#invoke,只幹了一件事就是將MethodInvocation加入到了ThreadLocal中,這樣後續可以在其他地方使用ExposeInvocationInterceptor#currentInvocation獲取到MethodInvocation,而MethodInvocation中封裝了目標物件,目標方法,方法引數等資訊。
org.springframework.aop.aspectj.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); }
這裡會去呼叫環繞通知的增強方法,而環繞通知的增強方法中會執行proceedingJoinPoint.proceed(),這樣就會呼叫下一個MethodInterceptor–>MethodBeforeAdviceInterceptor。
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); }
這裡又會呼叫MethodInvocation.proceed()傳遞給下一個MethodInterceptor。
org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } }
先執行MethodInvocation.proceed(),最後在finally塊中呼叫後置通知的增強,不管目標方法有沒有丟擲異常,finally程式碼塊中的程式碼都會執行,也就是不管目標方法有沒有丟擲異常,後置通知都會執行。
org.springframework.aop.framework.adapter.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; }
先執行MethodInvocation.proceed(),然後再執行返回後通知的增強。
org.springframework.aop.aspectj.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; } }
先執行MethodInvocation.proceed(),如果目標方法丟擲了異常就會執行異常通知的增強,然後丟擲異常,所以這時返回後通知的增強就不會執行了。
總結各種通知的執行順序:
Around begin // 環繞通知開始 Before // 前置通知 UserServiceImpl // 目標方法的執行 AfterReturning // 返回後通知 After // 後置通知 Around end // 環繞通知結束
到此這篇關於spring AOP原理及原始碼分析的文章就介紹到這了,更多相關spring AOP原理原始碼內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45