久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Spring的Aware注入源碼分析

165次閱讀
沒有評論

共計 6225 個字符,預計需要花費 16 分鐘才能閱讀完成。

本篇內(nèi)容介紹了“Spring 的 Aware 注入源碼分析”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓丸趣 TV 小編帶領(lǐng)大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

Aware 注入

在使用 Spring 的時候我們將自己的 Bean 實現(xiàn) BeanNameAware 接口、BeanFactoryAware 接口等,依賴容器幫我們注入當前 Bean 的名稱或者 Bean 工廠,其代碼實現(xiàn)的 initializeBean 方法:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {

    if (System.getSecurityManager() != null) {

        AccessController.doPrivileged(new PrivilegedAction Object () {

            public Object run() {

                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;

}

看一下上面第 5 行的實現(xiàn):

private void invokeAwareMethods(final String beanName, final Object bean) {

    if (bean instanceof BeanNameAware) {

        ((BeanNameAware) bean).setBeanName(beanName);

    }

    if (bean instanceof BeanClassLoaderAware) {

        ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());

    }

    if (bean instanceof BeanFactoryAware) {

        ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

    }

}

看到這里判斷,如果 bean 是 BeanNameAware 接口的實現(xiàn)類會調(diào)用 setBeanName 方法、如果 bean 是 BeanClassLoaderAware 接口的實現(xiàn)類會調(diào)用 setBeanClassLoader 方法、如果是 BeanFactoryAware 接口的實現(xiàn)類會調(diào)用 setBeanFactory 方法,注入對應的屬性值。

調(diào)用 BeanPostProcessor 的 postProcessBeforeInitialization 方法

上面 initializeBean 方法再看 16 行其實現(xiàn):

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

        throws BeansException {

 

    Object result = existingBean;

    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

        result = beanProcessor.postProcessBeforeInitialization(result, beanName);

        if (result == null) {

            return result;

        }

    }

    return result;

}

遍歷每個 BeanPostProcessor 接口實現(xiàn),調(diào)用 postProcessBeforeInitialization 方法,這個接口的調(diào)用時機之后會總結(jié),這里就代碼先簡單提一下。

調(diào)用初始化方法

initializeBean 方法的 20 行,調(diào)用 Bean 的初始化方法,看一下實現(xiàn):

protected void invokeInitMethods(String beanName, final 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 +

        }

        if (System.getSecurityManager() != null) {

            try {

                AccessController.doPrivileged(new PrivilegedExceptionAction Object () {

                    public Object run() throws Exception {

                        ((InitializingBean) bean).afterPropertiesSet();

                        return null;

                    }

                }, getAccessControlContext());

            }

            catch (PrivilegedActionException pae) {

                throw pae.getException();

            }

        }                

        else {

            ((InitializingBean) bean).afterPropertiesSet();

        }

    }

 

    if (mbd != null) {

        String initMethodName = mbd.getInitMethodName();

        if (initMethodName != null !(isInitializingBean afterPropertiesSet .equals(initMethodName))

                    !mbd.isExternallyManagedInitMethod(initMethodName)) {

            invokeCustomInitMethod(beanName, bean, mbd);

        }

    }

}

看到,代碼做了兩件事情:

1、先判斷 Bean 是否 InitializingBean 的實現(xiàn)類,是的話,將 Bean 強轉(zhuǎn)為 InitializingBean,直接調(diào)用 afterPropertiesSet() 方法

2、嘗試去拿 init-method,假如有的話,通過反射,調(diào)用 initMethod

因此,兩種方法各有優(yōu)劣:使用實現(xiàn) InitializingBean 接口的方式效率更高一點,因為 init-method 方法是通過反射進行調(diào)用的;從另外一個角度講,使用 init-method 方法之后和 Spring 的耦合度會更低一點。具體使用哪種方式調(diào)用初始化方法,看個人喜好。

調(diào)用 BeanPostProcessor 的 postProcessAfterInitialization 方法

最后一步,initializeBean 方法的 29 行:

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

        throws BeansException {

 

    Object result = existingBean;

    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {

        result = beanProcessor.postProcessAfterInitialization(result, beanName);

        if (result == null) {

            return result;

        }

    }

    return result;

}

同樣遍歷 BeanPostProcessor,調(diào)用 postProcessAfterInitialization 方法。因此對于 BeanPostProcessor 方法總結(jié)一下:

1、在初始化每一個 Bean 的時候都會調(diào)用每一個配置的 BeanPostProcessor 的方法

2、在 Bean 屬性設(shè)置、Aware 設(shè)置后調(diào)用 postProcessBeforeInitialization 方法

3、在初始化方法調(diào)用后調(diào)用 postProcessAfterInitialization 方法

注冊需要執(zhí)行銷毀方法的 Bean

接下來看一下最上面 doCreateBean 方法的第 83 行 registerDisposableBeanIfNecessary(beanName, bean, mbd) 這一句,完成了創(chuàng)建 Bean 的最后一件事情:注冊需要執(zhí)行銷毀方法的 Bean。

看一下方法的實現(xiàn):

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {

    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);

    if (!mbd.isPrototype() requiresDestruction(bean, mbd)) {

        if (mbd.isSingleton()) {

            // Register a DisposableBean implementation that performs all destruction

            // work for the given bean: DestructionAwareBeanPostProcessors,

            // DisposableBean interface, custom destroy method.

            registerDisposableBean(beanName,

                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));

        }

        else {

            // A bean with a custom scope…

            Scope scope = this.scopes.get(mbd.getScope());

            if (scope == null) {

                throw new IllegalStateException(No Scope registered for scope + mbd.getScope() +

            }

            scope.registerDestructionCallback(beanName,

                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));

        }

    }

}

其中第 3 行第一個判斷為必須不是 prototype(原型)的,第二個判斷 requiresDestruction 方法的實現(xiàn)為:

 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {

     return (bean != null

             (bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||

                     hasDestructionAwareBeanPostProcessors()));

 }

要注冊銷毀方法,Bean 需要至少滿足以下三個條件之一:

(1)Bean 是 DisposableBean 的實現(xiàn)類,此時執(zhí)行 DisposableBean 的接口方法 destroy()

(2)Bean 標簽中有配置 destroy-method 屬性,此時執(zhí)行 destroy-method 配置指定的方法

(3)當前 Bean 對應的 BeanFactory 中持有 DestructionAwareBeanPostProcessor 接口的實現(xiàn)類,此時執(zhí)行 DestructionAwareBeanPostProcessor 的接口方法 postProcessBeforeDestruction

在滿足上面三個條件之一的情況下,容器便會注冊銷毀該 Bean,注冊 Bean 的方法很簡單,見 registerDisposableBean 方法實現(xiàn):

public void registerDisposableBean(String beanName, DisposableBean bean) {

    synchronized (this.disposableBeans) {

        this.disposableBeans.put(beanName, bean);

     }

}

容器銷毀的時候,會遍歷 disposableBeans,逐一執(zhí)行銷毀方法。

“Spring 的 Aware 注入源碼分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編將為大家輸出更多高質(zhì)量的實用文章!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-03發(fā)表,共計6225字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 芦山县| 馆陶县| 同江市| 正镶白旗| 简阳市| 南昌市| 尚志市| 曲周县| 镇远县| 从江县| 哈尔滨市| 股票| 宝清县| 鄂温| 北票市| 竹溪县| 仲巴县| 三河市| 长宁区| 双鸭山市| 南宫市| 土默特右旗| 墨玉县| 榆中县| 灵寿县| 正定县| 遵化市| 姚安县| 当阳市| 石狮市| 马鞍山市| 河曲县| 武胜县| 遂川县| 抚宁县| 雷州市| 库伦旗| 寿光市| 长白| 海安县| 中山市|