1. 程式人生 > >Spring AOP源碼分析

Spring AOP源碼分析

註冊 文件 reference exc 核心 spa ret png ice

核心類:AbstractAutoProxyCreator

技術分享圖片

繼續看:

技術分享圖片

流程說明

1)AOP標簽的定義解析劉徹骨肯定是從NamespaceHandlerSupport的實現類開始解析的,這個實現類就是AopNamespaceHandler。至於為什麽會是從NamespaceHandlerSupport的實現類開始解析的,這個的話我想讀者可以去在回去看看Spring自定義標簽的解析流程,裏面說的比較詳細。

2)要啟用AOP,我們一般會在Spring裏面配置<aop:aspectj-autoproxy/> ,所以在配置文件中在遇到aspectj-autoproxy標簽的時候我們會采用AspectJAutoProxyBeanDefinitionParser解析器

3)進入AspectJAutoProxyBeanDefinitionParser解析器後,調用AspectJAutoProxyBeanDefinitionParser已覆蓋BeanDefinitionParser的parser方法,然後parser方法把請求轉交給了AopNamespaceUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary去處理

4)進入AopNamespaceUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法後,先調用AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法,裏面在轉發調用給registerOrEscalateApcAsRequired,註冊或者升級AnnotationAwareAspectJAutoProxyCreator類。對於AOP的實現,基本是靠AnnotationAwareAspectJAutoProxyCreator去完成的,它可以根據@point註解定義的切點來代理相匹配的bean。

5)AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法處理完成之後,接下來會調用useClassProxyingIfNecessary() 處理proxy-target-class以及expose-proxy屬性。如果將proxy-target-class設置為true的話,那麽會強制使用CGLIB代理,否則使用jdk動態代理,expose-proxy屬性是為了解決有時候目標對象內部的自我調用無法實現切面增強。

6)最後的調用registerComponentIfNecessary 方法,註冊組建並且通知便於監聽器做進一步處理。

創建AOP代理

上面說到AOP的核心邏輯是在AnnotationAwareAspectJAutoProxyCreator類裏面實現,那麽我們先來看看這個類的層次關系

流程說明

1) spring 容器啟動,每個bean的實例化之前都會先經過AbstractAutoProxyCreator類的postProcessAfterInitialization()這個方法,然後接下來是調用wrapIfNecessary方法。

技術分享圖片

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;
    }

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
        if (this.nonAdvisedBeans.contains(cacheKey)) {
            return bean;
        }
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.nonAdvisedBeans.add(cacheKey);
            return bean;
        }

        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.add(cacheKey);
            Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        this.nonAdvisedBeans.add(cacheKey);
        return bean;
    }
創建代理對象
protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

        ProxyFactory proxyFactory = new ProxyFactory();
        // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
        proxyFactory.copyFrom(this);

        if (!shouldProxyTargetClass(beanClass, beanName)) {
            // Must allow for introductions; can‘t just set interfaces to
            // the target‘s interfaces only.
            Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
            for (Class<?> targetInterface : targetInterfaces) {
                proxyFactory.addInterface(targetInterface);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        for (Advisor advisor : advisors) {
            proxyFactory.addAdvisor(advisor);
        }

        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(this.proxyClassLoader);
    }

技術分享圖片

Spring AOP源碼分析