溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Springboot中EnableAspectJAutoProxy的作用是什么

發(fā)布時間:2021-06-21 17:05:10 來源:億速云 閱讀:1314 作者:Leah 欄目:大數(shù)據(jù)

本篇文章給大家分享的是有關(guān)Springboot中EnableAspectJAutoProxy的作用是什么,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

摘要:

Spring Framwork的兩大核心技術(shù)就是IOCAOP,AOPSpring的產(chǎn)品線中有著大量的應(yīng)用。如果說反射是你通向高級的基礎(chǔ),那么代理就是你站穩(wěn)高級的底氣。AOP的本質(zhì)也就是大家所熟悉的CGLIB動態(tài)代理技術(shù),在日常工作中想必或多或少都用過但是它背后的秘密值得我們?nèi)ド钏?。本文主要?code>Spring AOP運行過程上,結(jié)合一定的源碼整體上介紹Spring AOP的一個運行過程。知其然,知其所以然,才能更好的駕馭這門核心技術(shù)。

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import({AspectJAutoProxyRegistrar.class})
    public @interface EnableAspectJAutoProxy {
        //表明該類采用CGLIB代理還是使用JDK的動態(tài)代理
        boolean proxyTargetClass() default false;
    	 /**
         * @since 4.3.1 代理的暴露方式:解決內(nèi)部調(diào)用不能使用代理的場景  默認為false表示不處理
         * true:這個代理就可以通過AopContext.currentProxy()獲得這個代理對象的一個副本(ThreadLocal里面),從而我們可以很方便得在Spring框架上下文中拿到當(dāng)前代理對象(處理事務(wù)時很方便)
         * 必須為true才能調(diào)用AopContext得方法,否則報錯:Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
         */
        boolean exposeProxy() default false;
    }

所有的EnableXXX驅(qū)動技術(shù)都得看他的@Import,所以上面最重要的是這一句@Import(AspectJAutoProxyRegistrar.class),下面看看它

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
        AspectJAutoProxyRegistrar() {
        }
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            //注冊了一個基于注解的自動代理創(chuàng)建器   AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
            AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
            if (enableAspectJAutoProxy != null) {
                  //表示強制指定了要使用CGLIB
                if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                    AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                }
              //強制暴露Bean的代理對象到AopContext
                if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                    AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
                }
            }
        }
    }

AspectJAutoProxyRegistrar是一個項容器注冊自動代理創(chuàng)建器

    @Nullable
    	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    			BeanDefinitionRegistry registry, @Nullable Object source) {
    		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    	}

說明spring容器的注解代理創(chuàng)建器就是AnnotationAwareAspectJAutoProxyCreator

    @Nullable
        private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
            Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
          //這里如果我們自己定義了這樣一個自動代理創(chuàng)建器就是用我們自定義的
            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());
                  /** 
                   *用戶注冊的創(chuàng)建器,必須是InfrastructureAdvisorAutoProxyCreator
                   *AspectJAwareAdvisorAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator之一
                  */
                    int requiredPriority = findPriorityForClass(cls);
                    if (currentPriority < requiredPriority) {
                        apcDefinition.setBeanClassName(cls.getName());
                    }
                }
                return null;
            } 
          //若用戶自己沒有定義,那就用默認的AnnotationAwareAspectJAutoProxyCreator
          RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    		  beanDefinition.setSource(source);
          //此處注意,增加了一個屬性:最高優(yōu)先級執(zhí)行,后面會和@Async注解一起使用的時候起關(guān)鍵作用
    		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    		return beanDefinition;
        }

我們就成功的注入了一個BeanAnnotationAwareAspectJAutoProxyCreator 基于注解的自動代理創(chuàng)建器

Spring中自動創(chuàng)建代理器

Springboot中EnableAspectJAutoProxy的作用是什么

由此可見,Spring使用BeanPostProcessor讓自動生成代理?;?code>BeanPostProcessor的自動代理創(chuàng)建器的實現(xiàn)類,將根據(jù)一些規(guī)則在容器實例化Bean時為匹配的Bean生成代理實例。

AbstractAutoProxyCreator是對自動代理創(chuàng)建器的一個抽象實現(xiàn)。最重要的是,它實現(xiàn)了SmartInstantiationAwareBeanPostProcessor接口,因此會介入到Spring IoC容器Bean實例化的過程。

SmartInstantiationAwareBeanPostProcessor繼承InstantiationAwareBeanPostProcessor所以它最主要的 職責(zé)是在bean的初始化前,先會執(zhí)行所有的InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,誰第一個返回了不為nullBean,后面就都不會執(zhí)行了 。然后會再執(zhí)行BeanPostProcessor#postProcessAfterInitialization

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    		Object exposedObject = bean;
    		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    			for (BeanPostProcessor bp : getBeanPostProcessors()) {
    				if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
    					SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
    					exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
    				}
    			}
    		}
    		return exposedObject;
    	}

說明:這個方法是spring的三級緩存中的其中一環(huán),當(dāng)你調(diào)用Object earlySingletonReference = getSingleton(beanName, false);時候就會觸發(fā),其實還有一個地方exposedObject = initializeBean(beanName, exposedObject, mbd);也會觸發(fā)導(dǎo)致返回一個代理對象。

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    		try {
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    		return wrappedBean;
    	}

強調(diào): 這2個地方雖然都有后置增強的作用,但是@Async所使用的AsyncAnnotationBeanPostProcessor不是SmartInstantiationAwareBeanPostProcessor的實現(xiàn)類,所以此處會導(dǎo)致@Transactional@Async處理循環(huán)依賴時候的不一致性。對于循環(huán)依賴后續(xù)會有單獨章節(jié)進行分享。

以上就是Springboot中EnableAspectJAutoProxy的作用是什么,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI