Spring AspectJ AOP Bean建立分析

Spring AspectJ AOP Bean建立分析

1.@EnableAspectJAutoProxy

//EnableAspectJAutoProxy.java

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
        /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
     * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
     * Off by default, i.e. no guarantees that {@code AopContext} access will work.
     * @since 4.3.1
     */
    boolean exposeProxy() default false;
}

上述代碼是springAop源碼的最主要的註解;下邊咱們來分析下AspectJAutoProxyRegistrar.javajava

2.AspectJAutoProxyRegistrar

//AspectJAutoProxyRegistrar.java

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) {
        //若是須要註冊AspectJ代理自動建立器
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        AnnotationAttributes enableAspectJAutoProxy =
                AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }
        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }
    }

}

由上述代碼可知,AspectJAutoProxyRegistrar.java即AspectJ自動代理註冊組件,實現了ImportBeanDefinitionRegistrar接口,也就是自定義導入組件。git

咱們在AspectJAutoProxyRegistrar.java的45行打個斷點,進行調試github

image-20191127142417960.png

image-20191127143143201.png

2處加入了AnnotationAwareAspectJAutoProxyCreator.java 即AspectJ註解自動代理建立器,稍後咱們在分析spring

接下來咱們看registerOrEscalateApcAsRequired()方法:緩存

//AspectJAutoProxyRegistrar.java    
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        //<1>判斷容器中有沒有org.springframework.aop.config.internalAutoProxyCreator
        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;
        }
        //<2>若是沒有在bean註冊org.springframework.aop.config.internalAutoProxyCreator
        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;
    }

<1>由AUTO_PROXY_CREATOR_BEAN_NAME 可知確定是判斷是否容器中有internalAutoProxyCreator的beanapp

<2>沒有就建立一個ide

3.AnnotationAwareAspecttJAutoProxyCreator

image-20191127151239627.png

由類圖繼承關係可知AnnotationAwareAspecttJAutoProxyCreator的父類AbstractAutoProxyCreator實現了bean後置處理器和BeanfactoryAware。post

3.1AnnotationAwareAspecttJAutoProxyCreator分析

分別在父類ProxyProcessorSupport 204行和241行打斷點,由於都是和建立bean的相關方法。ui

父類AbstractAdvisorAutoProxyCreator 以下圖所示打好斷點this

圖片.png

AnnotationAwareAspectJAutoProxyCreator 75行打好斷點

image-20191127163202555.png

調試開始:
image-20191127163404667.png

查看調用棧:

3.1.1 刷新容器

image-20191127163556248.png

3.1.2 註冊攔截Bean建立的Bean處理器。

image-20191127163712060.png

3.1.3 註冊bean後置處理器

image-20191127163737325.png

3.1.4 獲取AnnotationAwareAspecttJAutoProxyCreator後置處理器

image-20191127163913629.png

3.1.5 獲取bean

image-20191127164132061.png

3.1.6 第一次獲取單例的bean發現是空 (AnnotationAwareAspecttJAutoProxyCreator的bean名稱是org.springframework.aop.config.internalAutoProxyCreator)

image-20191127164350407.png

image-20191127164243708.png

3.1.7 建立AnnotationAwareAspecttJAutoProxyCreator 的bean

image-20191127164529810.png

image-20191127164722580.png

3.1.8 初始化org.springframework.aop.config.internalAutoProxyCreator

image-20191127164821332.png

image-20191127164842673.png

3.1.9 bean類型轉換

image-20191127164918866.png

3.1.10 加入到BeanFactory而後初始化

image-20191127164956327.png

3.1.11 包裝bean初始化

image-20191127165549239.png

3.1.12 spring二級緩存獲取bean

image-20191127165651279.png

3.1.13 必要時一次性建立bean

image-20191127165754821.png

3.1.14 建立完畢

4.AbstractAutoProxyCreator.postProcessBeforeInstantiation()方法

postProcessBeforeInstantiation()即實例化以前的後置處理,通過屢次調試咱們會發現每建立一個bean以前都會通過這裏。

image-20191128142131640.png
通過屢次調試分析以下結果:

//AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        //爲給定的bean類和bean名稱構建一個緩存鍵。
        Object cacheKey = getCacheKey(beanClass, beanName);
        
        if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                //代理bean標記
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        //若是定義了TargetSource 在此處建立代理
        if (beanName != null) {
            TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
            if (targetSource != null) {
                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;
        }

咱們看一下getCacheKey()

//爲給定的bean類和bean名稱構建一個緩存鍵。
protected Object getCacheKey(Class<?> beanClass, String beanName) {
        if (StringUtils.hasLength(beanName)) {
            return (FactoryBean.class.isAssignableFrom(beanClass) ?
                    BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
        }
        else {
            return beanClass;
        }
    }

以下例子:image-20191128104303913.png

返回一個bean名稱是demo的對象。

5.AbstractAutoProxyCreator.postProcessAfterInitialization()

//AbstractAutoProxyCreator.java
/**
     * Create a proxy with the configured interceptors if the bean is
     * identified as one to proxy by the subclass.
     * @see #getAdvicesAndAdvisorsForBean
     */
//若是bean被子類標識爲代理,則使用配置的攔截器建立代理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

此方法是bean初始化的時候被調用的。

以下調用棧:

bean初始化

image-20191128143209149.png

初始化後應用bean處理

image-20191128143345105.png

image-20191128143456179.png

咱們進入wrapIfNecessary()方法:

/**
     * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @param cacheKey the cache key for metadata access
     * @return a proxy wrapping the bean, or the raw bean instance as-is
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && 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.
        //子類是否標記代理
        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;
    }

上述代碼大概意思是:若是有bean被子類bean作了代理在這裏建立建立bean代理。

image-20191128140051397.png

調試源碼詳見地址:
https://github.com/dakele895/...

相關文章
相關標籤/搜索