在线精品99_中国九九盗摄偷拍偷看_91免费版在线观看_91.app_91高清视频在线_99热最新网站

Spring的Aware注入源码分析

144次阅读
没有评论

共计 6225 个字符,预计需要花费 16 分钟才能阅读完成。

本篇内容介绍了“Spring 的 Aware 注入源码分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

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 注入源码分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-03发表,共计6225字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)
主站蜘蛛池模板: 久久亚洲av无码精品色午夜麻 | 大陆熟妇丰满多毛xxxx | 亚洲国产五月综合网 | 日本欧美国产 | 亚洲精品国产三级在线观看 | 精品国产免费一区二区三区五区 | 久热这里只有精品视频6 | 十八岁污网站在线观看 | 精品牛牛影视久久精品 | 波多野结衣网站 | 一级网站在线观看 | 免费二级毛片免费完整视频 | 欧美老熟妇乱xxxxx | 男人激烈吮乳吃奶视频免费 | 亚洲国产精品第一页 | 久久99精品久久久 | 欧美高清videosex极品 | 欧美激情久久欧美激情 | 亚洲精品久久久久中文字幕二区 | 九九久久精品这里久久网 | 成人午夜动漫在线观看 | 免费一看一级毛片全播放 | 91日韩在线 | 国产成人理在线观看视频 | 亚洲欧美视频在线观看 | 本日三级 | 伊人国产在线播放 | 日本一区二区免费电影 | 久久ww精品w免费人成 | 久久只有精品视频 | 两个人的www免费视频 | 亚洲天堂中文 | 成人午夜看片 | 人人妻人人爽人人澡av | h视频在线免费 | 在线不卡一区二区三区日韩 | 亚洲性69影视 | 免费a级作爱片免费观看美国 | 亚洲人成影院在线高清 | 99热精品国产三级在线 | 成人男女拍拍拍在线视频 |