1. 程式人生 > >總結Spring框架擴充套件點(二)bean生命週期中的擴充套件點(持續更新中...)

總結Spring框架擴充套件點(二)bean生命週期中的擴充套件點(持續更新中...)

面向業務開發的時候,程式設計師需要明白業務的邏輯,並設計程式碼結構。而在進行中介軟體開發的時候,則需要明白框架的邏輯,進行開發。

所以要開發提供給spring的中介軟體,需要知道spring中有哪些擴充套件點,好在對應的地方插入我們的功能。

1. Spring容器初始化bean大致過程

1. 定義bean標籤

2. 將bean標籤解析成BeanDefinition

3. 呼叫構造方法例項化(IOC):

4. 屬性值得依賴注入(DI)

2. BeanFactory構造階段

1.1 NamespaceHandler

3. ApplicationContext構造階段

3.1 BeanFactoryPostProcessor

說明:

顧名思義,是BeanFactory的後置處理器,處理的物件是BeanFactory

執行時間:

    bean factory已經被standard initialization了

    所有的bean definitions已經被家在到bean factory中了

    但是還沒有例項化任何的bean,bean的建構函式都沒被執行

註冊方法:

    要使用BeanPostProcessor回撥,就必須先在容器中註冊實現該介面的類,那麼如何註冊呢?BeanFactory和ApplicationContext容器的註冊方式不大一樣:若使用BeanFactory,則必須要顯示的呼叫其addBeanPostProcessor()方法進行註冊,引數為BeanPostProcessor實現類的例項;如果是使用ApplicationContext.xml,那麼容器會在配置檔案在中自動尋找實現了BeanPostProcessor介面的Bean,然後自動註冊,我們要做的只是配置一個BeanPostProcessor實現類的Bean就可以了。  

一般用途:

    獲取相關Bean的bean definition,並修改bean definition

    例如:

  • 給屬性賦值,修改屬性值
  • 可以把bean的scope從singleton改為prototype,也可以把property的值給修改掉。
  • 可以同時配置多個BeanFactoryPostProcessor,並通過設定'order'屬性來控制各個BeanFactoryPostProcessor的執行次序

spring內建的BeanFactoryPostProcessor實現類:

  • org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:屬性佔位符配置
  • org.springframework.beans.factory.config.PropertyOverrideConfigurer:
  • org.springframework.beans.factory.config.CustomEditorConfigurer:用來註冊自定義的屬性編輯器

正式應用:

    筆者使用的某款知名內部RPC框架中,就是在這個階段,給bean

3.2 BeanPostProcessor

說明:

顧名思義,是Bean的後置處理器,處理的物件是Bean

執行時間:

    bean被spring容器例項化之,即建構函式已經被執行

    bean的set方法被呼叫注入屬性值之

    在執行bean的初始化方法前後。這裡說的初始化方法,指的是下面兩種:

  • bean實現了InitializingBean介面,對應的方法為afterPropertiesSet
  • 在bean定義的時候,通過init-method設定的方法

    如果上述方法都存在的話,執行順序是:

  1. postProcessBeforeInitialization
  2. afterPropertiesSet
  3. init-method
  4. postProcessAfterInitialization

註冊方法:

    跟BeanPostProcessor一樣,ApplicationContext也能自動檢測和呼叫容器中的BeanFactoryPostProcessor。 

一般用途:

    例如:給bean新增動態代理

spring內建的BeanPostProcessor實現類:

  • org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支援@Resource註解的注入
  • org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支援@Required註解的注入
  • org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支援@Autowired註解的注入
  • org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支援@PersistenceUnit和@PersistenceContext註解的注入
  • org.springframework.context.support.ApplicationContextAwareProcessor:用來為bean注入ApplicationContext等容器物件

3.3 系統如何呼叫這幾個方法的

在使用ApplicationContext啟動spring容器的時候,在AbstractApplicationContext.refresh()方法中,完成相關初始化工作:

首先是BeanFactoryPostProcessor鉤子:

在第5步invokeBeanFactoryPostProcessors方法中,呼叫了BeanFactoryPostProcessor.postProcessBeanFactory方法,相關原始碼如下:

/** 
     * Instantiate and invoke all registered BeanFactoryPostProcessor beans, 
     * respecting explicit order if given. 
     * <p>Must be called before singleton instantiation. 
     */  
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {  
        // Invoke factory processors registered with the context instance.  
        for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {  
            BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();  
            factoryProcessor.postProcessBeanFactory(beanFactory);  
        }  
  
        // Do not initialize FactoryBeans here: We need to leave all regular beans  
        // uninitialized to let the bean factory post-processors apply to them!  
        String[] postProcessorNames =  
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);  
  
        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,  
        // Ordered, and the rest.  
        List priorityOrderedPostProcessors = new ArrayList();  
        List orderedPostProcessorNames = new ArrayList();  
        List nonOrderedPostProcessorNames = new ArrayList();  
        for (int i = 0; i < postProcessorNames.length; i++) {  
            if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {  
                priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));  
            }  
            else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {  
                orderedPostProcessorNames.add(postProcessorNames[i]);  
            }  
            else {  
                nonOrderedPostProcessorNames.add(postProcessorNames[i]);  
            }  
        }  
  
        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.  
        Collections.sort(priorityOrderedPostProcessors, new OrderComparator());  
        invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);  
  
        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.  
        List orderedPostProcessors = new ArrayList();  
        for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {  
            String postProcessorName = (String) it.next();  
            orderedPostProcessors.add(getBean(postProcessorName));  
        }  
        Collections.sort(orderedPostProcessors, new OrderComparator());  
        invokeBeanFactoryPostProcessors(beanFactory, orderedPostProcessors);  
  
        // Finally, invoke all other BeanFactoryPostProcessors.  
        List nonOrderedPostProcessors = new ArrayList();  
        for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {  
            String postProcessorName = (String) it.next();  
            nonOrderedPostProcessors.add(getBean(postProcessorName));  
        }  
        invokeBeanFactoryPostProcessors(beanFactory, nonOrderedPostProcessors);  
    }  
  
    /** 
     * Invoke the given BeanFactoryPostProcessor beans. 
     */  
    private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {  
        for (Iterator it = postProcessors.iterator(); it.hasNext();) {  
            BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) it.next();  
            postProcessor.postProcessBeanFactory(beanFactory);  
        }  
    } 

上面的程式碼中,首先通過beanFactory.getBeanNamesForType獲取spring配置檔案中定義的,所有實現BeanFactoryPostProcessor介面的bean,然後根據優先順序進行排序,之後對於每個BeanFactoryPostProcessor,呼叫postProcessBeanFactory方法。

然後是BeanPostProcessor鉤子:

第一種情況,對於prototype型別的bean,第6步中,呼叫registerBeanPostProcessors方法,註冊所有實現BeanPostProcessor介面的bean。然後等到程式執行該bean的getBean方法初始化的時候執行對應的BeanPostProcessor方法。

第二種情況,對於singleton型別的bean,並且不是抽象類,也不延遲初始化,則在第11步中,通過finishBeanFactoryInitialization方法,呼叫getBean方法來例項化bean,從而直接執行BeanPostProcessor方法

可以看到,BeanPostProcessor鉤子都是在bean被getBean方法初始化的時候被執行,只不過getBean方法被執行的時間不同。我們接下來看看getBean方法做了什麼:

getBean方法最終是通過呼叫AbstractAutowireCapableBeanFactory.doCreateBean方法來執行初始化的,該方法的實現如下:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
        // Instantiate the bean.  
        BeanWrapper instanceWrapper = null;  
        if (mbd.isSingleton()) {  
            instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);  
        }  
        if (instanceWrapper == null) {  
            instanceWrapper = createBeanInstance(beanName, mbd, args);  
        }  
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
        Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
  
        // Allow post-processors to modify the merged bean definition.  
        synchronized (mbd.postProcessingLock) {  
            if (!mbd.postProcessed) {  
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
                mbd.postProcessed = true;  
            }  
        }  
  
        // Eagerly cache singletons to be able to resolve circular references  
        // even when triggered by lifecycle interfaces like BeanFactoryAware.  
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
                isSingletonCurrentlyInCreation(beanName));  
        if (earlySingletonExposure) {  
            if (logger.isDebugEnabled()) {  
                logger.debug("Eagerly caching bean '" + beanName +  
                        "' to allow for resolving potential circular references");  
            }  
            addSingletonFactory(beanName, new ObjectFactory() {  
                public Object getObject() throws BeansException {  
                    return getEarlyBeanReference(beanName, mbd, bean);  
                }  
            });  
        }  
  
        // Initialize the bean instance.  
        Object exposedObject = bean;  
        try {  
            populateBean(beanName, mbd, instanceWrapper);  
            exposedObject = initializeBean(beanName, exposedObject, mbd);  
        }  
        catch (Throwable ex) {  
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
                throw (BeanCreationException) ex;  
            }  
            else {  
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
            }  
        }  
  
        if (earlySingletonExposure) {  
            Object earlySingletonReference = getSingleton(beanName, false);  
            if (earlySingletonReference != null) {  
                if (exposedObject == bean) {  
                    exposedObject = earlySingletonReference;  
                }  
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
                    String[] dependentBeans = getDependentBeans(beanName);  
                    Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);  
                    for (int i = 0; i < dependentBeans.length; i++) {  
                        String dependentBean = dependentBeans[i];  
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
                            actualDependentBeans.add(dependentBean);  
                        }  
                    }  
                    if (!actualDependentBeans.isEmpty()) {  
                        throw new BeanCurrentlyInCreationException(beanName,  
                                "Bean with name '" + beanName + "' has been injected into other beans [" +  
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
                                "] in its raw version as part of a circular reference, but has eventually been " +  
                                "wrapped. This means that said other beans do not use the final version of the " +  
                                "bean. This is often the result of over-eager type matching - consider using " +  
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
                    }  
                }  
            }  
        }  
  
        // Register bean as disposable.  
        registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  
        return exposedObject;  
    }  

我們可以看到,getBean方法中,首先呼叫createBeanInstance方法,建立bean例項物件(這個時候執行bean的構造方法),然後呼叫populateBean方法,對bean進行填充,注入相關依賴,之後再呼叫方法initializeBean,進行相關初始化工作,initializeBean方法的實現如下:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {  
        if (bean instanceof BeanNameAware) {  
            ((BeanNameAware) bean).setBeanName(beanName);  
        }  
  
        if (bean instanceof BeanClassLoaderAware) {  
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());  
        }  
  
        if (bean instanceof BeanFactoryAware) {  
            ((BeanFactoryAware) bean).setBeanFactory(this);  
        }  
  
        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;  
    }  

從上面的實現可以看出,initializeBean先呼叫applyBeanPostProcessorsBeforeInitialization方法,執行每個BeanPostProcessor的postProcessBeforeInitialization,然後呼叫invokeInitMethods方法,執行bean的初始化方法,最後呼叫applyBeanPostProcessorsAfterInitialization方法,執行每個BeanPostProcessor的postProcessAfterInitialization方法。

postProcessBeforeInitialization,applyBeanPostProcessorsAfterInitialization,invokeInitMethods這三個方法的實現如下:

    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
            throws BeansException {  
  
        Object result = existingBean;  
        for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
            BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
        }  
        return result;  
    }  
  
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
            throws BeansException {  
  
        Object result = existingBean;  
        for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {  
            BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();  
            result = beanProcessor.postProcessAfterInitialization(result, beanName);  
        }  
        return result;  
    }  
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)  
            throws Throwable {  
  
        boolean isInitializingBean = (bean instanceof InitializingBean);  
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  
            if (logger.isDebugEnabled()) {  
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");  
            }  
            ((InitializingBean) bean).afterPropertiesSet();  
        }  
  
        String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);  
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  
                !mbd.isExternallyManagedInitMethod(initMethodName)) {  
            invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());  
        }  
    }  

重點看一下invokeInitMethods方法,裡面先執行afterPropertiesSet方法,然後再通過反射,執行init-method指定的方法。

一個完整的例子:

a) DestructionAwareBeanPostProcessor

b) InstantiationAwareBeanPostProcessor

c) SmartInstantiationAwareBeanPostProcessor

d) MergedBeanDefinitionPostProcessor

總結:

等待補充