spring之ApplicationContextAware詳解

一咙好、進(jìn)入正題

Aware本義就是"自動的",顧名思義spring給我們自動做了些事情。spring有很多以Aware結(jié)尾的類,有EnvironmentAware学歧、ApplicationContextAware、MessageSourceAware等耗式。這里我主要講一下ApplicationContextAware唆垃。

二五芝、使用

  @Service("gatewayService")
public class GatewayServiceImpl implements IGatewayService,ApplicationContextAware {

    private Logger logger= LoggerFactory.getLogger(getClass());


    Map<ServiceBeanEnum,IGatewayBo> chargeHandlerMap=new HashMap<ServiceBeanEnum,IGatewayBo>();

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext=applicationContext;
    }
}

在我們需要使用ApplicationContext的服務(wù)中實現(xiàn)ApplicationContextAware接口,系統(tǒng)啟動時就可以自動給我們的服務(wù)注入applicationContext對象,我們就可以獲取到ApplicationContext里的所有信息了。

三辕万、原理分析

我們都知道spring的入口方法就在AbstractApplicationContext的refresh()方法.我們先去看看refresh().prepareBeanFactory()方法与柑。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // 添加ApplicationContextAware的處理器
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
                ...
    }

也就是說,spring在啟動的時候給我們添加了ApplicationContextAwareProcessor這樣一個processor。進(jìn)去看看它的實現(xiàn):

@Override
    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(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                   //核心方法,調(diào)用aware接口方法
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }
    //實現(xiàn)
    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);
            }
          //針對實現(xiàn)了ApplicationContextAware的接口,spring都將調(diào)用其setApplicationContext,將applicationContext注入到當(dāng)前bean對象蓄坏。
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

那ApplicationContextAwareProcessor又是什么時候調(diào)用的呢价捧?我們接著往下看,原來refresh()方法中還有個beanFactory.preInstantiateSingletons()方法,里面有這樣一段代碼:

拿到所有的beanNames,然后依次判斷是否需要加載,如果是,則調(diào)用getBean(beanName)方法實例化出來。
// Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            @Override
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

依次查看getBean() ->doGetBean()->createBean()->doCreateBean()方法:

// Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                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);
            }
        }

查看一下initializeBean方法:

if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            //調(diào)用setBeanName() 涡戳、setBeanClassLoaderAware结蟋、setBeanFactoryAware方法
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
          //調(diào)用afterPropertiesSet()方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

      //這里才是ApplicationContextProcessor的postProcessAfterInitialization()執(zhí)行入口:
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;

原來AbstractAutowireCapableBeanFactory中的inititalBean()方法就是BeanPostProcessor的調(diào)用處。但是像BeanNameAware渔彰、BeanFactoryAware不同,是通過initialBean()中的invokeAwareMethods直接調(diào)用實現(xiàn)的嵌屎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市恍涂,隨后出現(xiàn)的幾起案子宝惰,更是在濱河造成了極大的恐慌,老刑警劉巖再沧,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尼夺,死亡現(xiàn)場離奇詭異,居然都是意外死亡炒瘸,警方通過查閱死者的電腦和手機淤堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顷扩,“玉大人拐邪,你說我怎么就攤上這事“兀” “怎么了扎阶?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長婶芭。 經(jīng)常有香客問我东臀,道長,這世上最難降的妖魔是什么雕擂? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任啡邑,我火速辦了婚禮贱勃,結(jié)果婚禮上井赌,老公的妹妹穿的比我還像新娘谤逼。我一直安慰自己,他們只是感情好仇穗,可當(dāng)我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布流部。 她就那樣靜靜地躺著,像睡著了一般纹坐。 火紅的嫁衣襯著肌膚如雪枝冀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天耘子,我揣著相機與錄音果漾,去河邊找鬼。 笑死谷誓,一個胖子當(dāng)著我的面吹牛绒障,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捍歪,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼户辱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了糙臼?” 一聲冷哼從身側(cè)響起庐镐,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎变逃,沒想到半個月后必逆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡揽乱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年末患,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锤窑。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡璧针,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渊啰,到底是詐尸還是另有隱情探橱,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布绘证,位于F島的核電站隧膏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嚷那。R本人自食惡果不足惜胞枕,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望魏宽。 院中可真熱鬧腐泻,春花似錦决乎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铆惑,卻和暖如春范嘱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背员魏。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工丑蛤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撕阎。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓盏阶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親闻书。 傳聞我的和親對象是個殘疾皇子名斟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容