1. 程式人生 > >Spring初始化過程到AOP

Spring初始化過程到AOP

should aop amp 切點 reg 遞歸調用 finish pes auto

初始化過程

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory
(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } // ... }

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
-> AbstractRefreshableApplicationContext#refreshBeanFactory() get a beanFactory(DefaultListableBeanFactory)
-> loadBeanDefinitions(beanFactory)
-> AbstractXmlApplicationContext#loadBeanDefinitions, XmlBeanDefinitionReader, loadBeanDefinition...(not yet instantiate)

registerBeanPostProcessors(beanFactory)
-> 註冊BPP,其中就包含AOP的BPPAbstractAutoProxyCreator,註意BPP是not-lazy-init的

finishBeanFactoryInitialization(beanFactory); 實例化非lazy-init的bean
-> DefaultListableDeanFactory#preInstantiateSingletons() -> getBean(beanName)
-> AbstractBeanFactory#getBean(beanName) -> doGetBean(name, null, null, false) -> getSingleton -> createBean
-> AbstractAutowiredCapableBeanFactory#createBean -> doCreateBean -> populateBean -> initializeBean -> applyBeanPostProcessorsBeforeInitialization -> invokeInitMethods -> applyBeanPostProcessorsAfterInitialization -> getBeanPostProcessors() 然後對每個bean挨個調用bpp的postProcessAfterInitialization方法,對於AOP,在其中就會有判定是否需要包裝、是否需要生成代理等操作,最後生成一個代理(這部分就是AOP的代碼了)

AOP創建代理

Spring默認會加載AbstractAutoProxyCreator這個Bean(是一個BPP)
AbstractAutoProxyCreator#postProcessAfterInitialization -> wrapIfNecessary

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

getAdvicesAndAdvisorsForBean方法找到所有的攔截器,調用createProxy方法生成代理。
生成Advisor[]設置到ProxyFactory中,然後調用ProxyFactory#getProxy方法獲取代理(JdkDynamicAopProxy和CglibAopProxy)。其中在生成Advisors是一個表復雜的過程,涉及匹配切點、包裝生成通知(AspectJPointcutAdvisor.)

ProxyFactor extends ProxyCreatorSupport extends AdvisedSupport

    protected final synchronized AopProxy createAopProxy() {
        if (!this.active) {
            activate();
        }
        return getAopProxyFactory().createAopProxy(this);
    }

ProxyFactory以自身為參數,因為把Advisors設置進去了,生成代理時就可以拿到了。生成AopProxyCglibAopProxy或者JdkDynamicAopProxy的構造參數需要AdvisedSupport)。
對於不需要包裝(攔截)的方法,有一個攔截器是ExposeInvocationInterceptor
在代理的invoke方法裏,會先從AdvisedSupport中獲取到攔截器鏈,最後包裝成一個MethodInvocationReflectiveMethodInvocation)調用其proceed方法。
關鍵是proceed這個方法,會遞歸調用其中每一個interceptor,這裏的this就是ReflectiveMethodInvocation,然後在interceptor的invoke方法裏,有前置/後置/環繞等邏輯,或者沒有邏輯(ExposeInvocationInterceptor是第一個攔截器),參數是MethodInvocation,然後再調用mi的proceed方法,回到ReflectiveMethodInvocation中繼續處理,攔截器鏈調完之後就會反射調用返回。此處有點繞,需要多看幾遍代碼。

return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

攔截器接口InvocationInterceptor,前置後置等邏輯都實現了該接口。
AspectJAfterAdvice
MethodBeforeAdviceInterceptor
AspectJAroundAdvice
等等

Spring初始化過程到AOP