欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring扩展点之Aware接口族

程序员文章站 2022-05-20 13:26:09
引言 Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,EnvironmentAware,BeanClassLoaderAware等,这些Aw ......

引言

spring中提供了各种aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:beanfactoryaware,beannameaware,applicationcontextaware,environmentaware,beanclassloaderaware等,这些aware的作用都可以从命名得知

aware处理

其中beannameawarebeanclassloaderawarebeanfactoryaware这三个是直接在bean的初始化之前就处理了的,具体代码在abstractautowirecapablebeanfactory.initializebean方法中:

protected object initializebean(string beanname, object bean, rootbeandefinition mbd) {
    // 判断对象实现的接口类型,处理特定的三种接口类型:beannameaware、beanclassloaderaware和beanfactoryaware。
    if (bean instanceof beannameaware) {
        ((beannameaware) bean).setbeanname(beanname);
    }
 
    if (bean instanceof beanclassloaderaware) {
        ((beanclassloaderaware) bean).setbeanclassloader(getbeanclassloader());
    }
 
    if (bean instanceof beanfactoryaware) {
        ((beanfactoryaware) bean).setbeanfactory(this);
    }
    // 开始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;
}

除了这三种之外的那些aware接口的实现就不太一样了,它们都是利用beanpostprocessor接口完成的,关于beanpostprocessor接口的原理可以这篇文章:spring扩展点之beanpostprocessor

applicationcontextaware就是利用applicationcontextawareprocessor实现的:

public object postprocessbeforeinitialization(final object bean, string beanname) throws beansexception {
        accesscontrolcontext acc = null;

        if (system.getsecuritymanager() != null &&
                (bean instanceof environmentaware || bean instanceof embeddedvalueresolveraware ||
                        bean instanceof resourceloaderaware || bean instanceof applicationeventpublisheraware ||
                        bean instanceof messagesourceaware || bean instanceof applicationcontextaware)) {
            acc = this.applicationcontext.getbeanfactory().getaccesscontrolcontext();
        }

        if (acc != null) {
            accesscontroller.doprivileged((privilegedaction<object>) () -> {
              //具体实现
                invokeawareinterfaces(bean);
                return null;
            }, acc);
        }
        else {
                      //具体实现
            invokeawareinterfaces(bean);
        }

        return bean;
    }
private void invokeawareinterfaces(object bean) {
        if (bean instanceof aware) {
            if (bean instanceof environmentaware) {
                ((environmentaware) bean).setenvironment(this.applicationcontext.getenvironment());
            }
            if (bean instanceof embeddedvalueresolveraware) {
                ((embeddedvalueresolveraware) bean).setembeddedvalueresolver(this.embeddedvalueresolver);
            }
            if (bean instanceof resourceloaderaware) {
                ((resourceloaderaware) bean).setresourceloader(this.applicationcontext);
            }
            if (bean instanceof applicationeventpublisheraware) {
                ((applicationeventpublisheraware) bean).setapplicationeventpublisher(this.applicationcontext);
            }
            if (bean instanceof messagesourceaware) {
                ((messagesourceaware) bean).setmessagesource(this.applicationcontext);
            }
            if (bean instanceof applicationcontextaware) {
                ((applicationcontextaware) bean).setapplicationcontext(this.applicationcontext);
            }
        }
    }

applicationcontextawareprocessor的注册奥秘在abstractapplicationcontext.preparebeanfactory方法中:

beanfactory.setbeanclassloader(getclassloader());
beanfactory.addpropertyeditorregistrar(new resourceeditorregistrar(this));
 beanfactory.addbeanpostprocessor(new applicationcontextawareprocessor(this)); 
beanfactory.ignoredependencyinterface(resourceloaderaware.class);
beanfactory.ignoredependencyinterface(applicationeventpublisheraware.class);
beanfactory.ignoredependencyinterface(messagesourceaware.class);
beanfactory.ignoredependencyinterface(applicationcontextaware.class);