中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring的Aware注入源碼分析

發布時間:2022-03-19 10:24:08 來源:億速云 閱讀:152 作者:iii 欄目:云計算

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

Aware注入

在使用Spring的時候我們將自己的Bean實現BeanNameAware接口、BeanFactoryAware接口等,依賴容器幫我們注入當前Bean的名稱或者Bean工廠,其代碼實現的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行的實現:

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接口的實現類會調用setBeanName方法、如果bean是BeanClassLoaderAware接口的實現類會調用setBeanClassLoader方法、如果是BeanFactoryAware接口的實現類會調用setBeanFactory方法,注入對應的屬性值。

調用BeanPostProcessor的postProcessBeforeInitialization方法

上面initializeBean方法再看16行其實現:

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接口實現,調用postProcessBeforeInitialization方法,這個接口的調用時機之后會總結,這里就代碼先簡單提一下。

調用初始化方法

initializeBean方法的20行,調用Bean的初始化方法,看一下實現:

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的實現類,是的話,將Bean強轉為InitializingBean,直接調用afterPropertiesSet()方法

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

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

調用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,調用postProcessAfterInitialization方法。因此對于BeanPostProcessor方法總結一下:

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

2、在Bean屬性設置、Aware設置后調用postProcessBeforeInitialization方法

3、在初始化方法調用后調用postProcessAfterInitialization方法

注冊需要執行銷毀方法的Bean

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

看一下方法的實現:

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方法的實現為:

 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {

     return (bean != null &&

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

                     hasDestructionAwareBeanPostProcessors()));

 }

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

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

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

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

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

public void registerDisposableBean(String beanName, DisposableBean bean) {

     synchronized (this.disposableBeans) {

        this.disposableBeans.put(beanName, bean);

     }

}

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

“Spring的Aware注入源碼分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永定县| 翼城县| 武定县| 石楼县| 壶关县| 鄂伦春自治旗| 克东县| 凤阳县| 阜新市| 建昌县| 吴忠市| 会同县| 迁安市| 祁东县| 汉阴县| 天长市| 汉中市| 平邑县| 巴青县| 临江市| 新安县| 双峰县| 自贡市| 望谟县| 塔城市| 南溪县| 澄迈县| 罗城| 屯门区| 石渠县| 屏山县| 平阴县| 颍上县| 庆阳市| 射洪县| 鸡东县| 白银市| 淮阳县| 西乌| 鹤山市| 昂仁县|