InstantiationAwareBeanPostProcessor源碼解析

轉(zhuǎn)載自個(gè)人博客https://chenjiabing666.github.io/2019/06/25/InstantiationAwareBeanPostProcessor%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/

簡(jiǎn)介

  • 繼承BeanPostProcessor接口脯倚,在此基礎(chǔ)上又定義了三個(gè)方法,分別在Bean實(shí)例化前后【不是初始化】執(zhí)行屎慢。
  • 從上面的介紹可以看到慷妙,這個(gè)接口相對(duì)于BeanPostProcessor功能更加強(qiáng)大宏所,一個(gè)接口承擔(dān)了Bean的實(shí)例化前后、初始化前后責(zé)任诈铛。

Bean加載順序

  • ioc容器創(chuàng)建加載Bean的執(zhí)行順序如下:
    • InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation,在實(shí)例化之前調(diào)用
    • Bean的實(shí)例化墨礁,調(diào)用構(gòu)造方法
    • InstantiationAwareBeanPostProcessor接口中的postProcessAfterInstantiation,在實(shí)例化之后調(diào)用
    • InstantiationAwareBeanPostProcessor接口中的postProcessPropertyValues【當(dāng)postProcessAfterInstantiation返回true才執(zhí)行】
    • BeanPostProcessor接口中的postProcessBeforeInitialization耳峦,在初始化之前調(diào)用
    • InitializingBean中的afterProperties方法恩静,執(zhí)行初始化
    • BeanPostProcessor接口中的postProcessAfterInitialization,在實(shí)例化之后調(diào)用

InstantiationAwareBeanPostProcessor接口方法的執(zhí)行順序

  • 正常的執(zhí)行順序如下:
    • postProcessBeforeInstantiation
    • postProcessAfterInstantiation
    • postProcessProperties
    • postProcessBeforeInitialization
    • postProcessAfterInitialization

方法解析

  • Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName):在實(shí)例化之前執(zhí)行【構(gòu)造方法之前執(zhí)行】
    • 返回值:如果返回的不為null蹲坷,那么后續(xù)的Bean的創(chuàng)建流程【實(shí)例化驶乾、初始化afterProperties】都不會(huì)執(zhí)行,而是直接使用返回的快捷Bean循签,此時(shí)的正常執(zhí)行順序如下:
      • InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation级乐,在實(shí)例化之前調(diào)用
      • BeanPostProcessor接口中的postProcessAfterInitialization,在實(shí)例化之后調(diào)用
/**
* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation 
* 作用:在實(shí)例化之前解析是否有快捷創(chuàng)建的Bean县匠,既是通過(guò)postProcessBeforeInstantiation返回的Bean
* 內(nèi)部調(diào)用兩個(gè)重要的方法:
*   1风科、applyBeanPostProcessorsBeforeInstantiation:內(nèi)部遍歷調(diào)用postProcessBeforeInstantiation方法【在實(shí)例化之前調(diào)用】
*   2、applyBeanPostProcessorsAfterInitialization:如果postProcessBeforeInstantiation方法返回了快捷的Bean乞旦,內(nèi)部遍歷調(diào)用postProcessBeforeInstantiation方法【在初始化之后調(diào)用】
*/
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    //調(diào)用方法贼穆,內(nèi)部遍歷調(diào)用postProcessBeforeInstantiation方法【在實(shí)例化之前調(diào)用】
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    //如果返回了快捷的Bean
                    if (bean != null) {
                        //如果postProcessBeforeInstantiation方法返回了快捷的Bean,內(nèi)部遍歷調(diào)用postProcessBeforeInstantiation方法【在初始化之后調(diào)用】
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
    
    /**
    *   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation
    *   作用:調(diào)用postProcessBeforeInstantiation方法
    */
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
                throws BeansException {
            //遍歷所有的后置處理器
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                //判斷是否是InstantiationAwareBeanPostProcessor類(lèi)型的兰粉,如果是的故痊,調(diào)用postProcessBeforeInstantiation方法獲取快捷Bean
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }
    
    /**
    *   org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization
    *   作用:遍歷調(diào)用postProcessAfterInitialization
    */
    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;
        }
  • boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException:正常情況下在實(shí)例化之后在執(zhí)行populateBean之前調(diào)用
    • 返回值:如果有指定的bean的時(shí)候返回false,那么后續(xù)的屬性填充和屬性依賴注入【populateBean】將不會(huì)執(zhí)行玖姑,同時(shí)后續(xù)的postProcessPropertyValues將不會(huì)執(zhí)行,但是初始化和BeanPostProcessor的仍然會(huì)執(zhí)行愕秫。
/**
* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean
* 填充指定Bean的屬性
* 在該方法內(nèi)部遍歷所有的BeanPostPorcessor,調(diào)用postProcessAfterInstantiation方法
*/
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        //獲取屬性
        PropertyValues pvs = mbd.getPropertyValues();
        if (bw == null) {
            if (!pvs.isEmpty()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        //**********************邏輯開(kāi)始執(zhí)行********************
        //標(biāo)志焰络,判斷是否繼續(xù)執(zhí)行屬性填充戴甩,默認(rèn)為false
        boolean continueWithPropertyPopulation = true;
        //判斷ioc容器中是否存在InstantiationAwareBeanPostProcessors(
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            //遍歷所有的BeanPostProcessor
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                //判斷類(lèi)型是InstantiationAwareBeanPostProcessor
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    //執(zhí)行postProcessAfterInstantiation方法
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        //返回結(jié)果為false,那么賦值continueWithPropertyPopulation=false舔琅,表示不繼續(xù)執(zhí)行屬性填充
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }
        //如果continueWithPropertyPopulation為false等恐,直接返回,不執(zhí)行下面的步驟
        if (!continueWithPropertyPopulation) {
            return;
        }
        //
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                //同樣是遍歷BeanPostProcessor
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        //執(zhí)行postProcessPropertyValues方法
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }
        //重要的一步备蚓,設(shè)置屬性
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
  • public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName):實(shí)例化之后調(diào)用课蔬,在方法applyPropertyValues【屬性填充】之前
    • 返回值:如果返回null,那么將不會(huì)進(jìn)行后續(xù)的屬性填充郊尝,比如依賴注入等二跋,如果返回的pvs額外的添加了屬性,那么后續(xù)會(huì)填充到該類(lèi)對(duì)應(yīng)的屬性中流昏。
    • pvs:PropertyValues對(duì)象扎即,用于封裝指定類(lèi)的對(duì)象吞获,簡(jiǎn)單來(lái)說(shuō)就是PropertyValue的集合,里面相當(dāng)于以key-value形式存放類(lèi)的屬性和值
    • pds:PropertyDescriptor對(duì)象數(shù)組谚鄙,PropertyDescriptor相當(dāng)于存儲(chǔ)類(lèi)的屬性各拷,不過(guò)可以調(diào)用set,get方法設(shè)置和獲取對(duì)應(yīng)屬性的值
/**
* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean的代碼片段
*/
if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            if (hasInstAwareBpps) {
                //遍歷調(diào)用postProcessPropertyValues方法
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        //如果返回的pvs是null闷营,直接返回
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }   
        //執(zhí)行真正的屬性填充
        applyPropertyValues(beanName, mbd, bw, pvs);

實(shí)例

  • 只是寫(xiě)了InstantiationAwareBeanPostProcessor定義的方法烤黍,另外的BeanPostProcessor的方法,請(qǐng)看上一篇文章
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    /**
     * 在實(shí)例化之前調(diào)用傻盟,如果返回null速蕊,一切按照正常順序執(zhí)行,如果返回的是一個(gè)實(shí)例的對(duì)象娘赴,那么這個(gè)將會(huì)跳過(guò)實(shí)例化规哲、初始化的過(guò)程
     * @param beanClass
     * @param beanName
     * @return
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanClass == User.class) {
            System.out.println("postProcessBeforeInstantiation執(zhí)行");
            return null;
        }

        return null;
    }

    /**
     * 在實(shí)例化之后,postProcessBeforeInitialization之前執(zhí)行
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) {
            System.out.println("postProcessAfterInstantiation執(zhí)行");
            return true;
        }

        return true;
    }

    /**
     * 實(shí)例化之后調(diào)用诽表,屬性填充之前
     * @param pvs PropertyValues對(duì)象唉锌,用于封裝指定類(lèi)的對(duì)象,簡(jiǎn)單來(lái)說(shuō)就是PropertyValue的集合关顷,里面相當(dāng)于以key-value形式存放類(lèi)的屬性和值
     * @param pds PropertyDescriptor對(duì)象數(shù)組糊秆,PropertyDescriptor相當(dāng)于存儲(chǔ)類(lèi)的屬性,不過(guò)可以調(diào)用set议双,get方法設(shè)置和獲取對(duì)應(yīng)屬性的值
     * @param bean 當(dāng)前的bean
     * @param beanName beanName
     * @return 如果返回null痘番,那么將不會(huì)進(jìn)行后續(xù)的屬性填充,比如依賴注入等平痰,如果返回的pvs額外的添加了屬性汞舱,那么后續(xù)會(huì)填充到該類(lèi)對(duì)應(yīng)的屬性中。
     */
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        if (pvs instanceof MutablePropertyValues&&bean instanceof User){
           MutablePropertyValues mutablePropertyValues= (MutablePropertyValues) pvs;
           HashMap<Object, Object> map = new HashMap<>();
           map.put("name","陳加兵");
           map.put("age",44);
           mutablePropertyValues.addPropertyValues(map);
           return mutablePropertyValues;
        }

        /**使用pds設(shè)置值
        if (bean instanceof User) {
            for (PropertyDescriptor descriptor:pds) {
                try {
                    if ("name".equals(descriptor.getName())) {
                        descriptor.getWriteMethod().invoke(bean, "陳加兵");
                    }else if("age".equals(descriptor.getName())){
                        descriptor.getWriteMethod().invoke(bean,40);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            return null;
        }**/
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) {
            System.out.println("postProcessBeforeInitialization執(zhí)行");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof User) {
            System.out.println("postProcessAfterInitialization執(zhí)行");
        }
        return bean;
    }
}

源碼梳理

  • 無(wú)論是BeanPostProcessor還是InstantiationAwareBeanPostProcessor都是在對(duì)象實(shí)例化和初始化前后執(zhí)行的邏輯宗雇,因此我們主要的代碼都在getBean昂芜,doGetBeancerateBean方法中
  • BeanPostProcessor的兩個(gè)方法的執(zhí)行源碼請(qǐng)看上一篇的文章
  • 步驟如下:
    • [圖片上傳失敗...(image-4658b9-1561472145733)]
    • [圖片上傳失敗...(image-824031-1561472145733)]
    • [圖片上傳失敗...(image-b7d4b0-1561472145733)]
    • [圖片上傳失敗...(image-d4fb2f-1561472145733)]
    • [圖片上傳失敗...(image-1ad844-1561472145733)]
    • [圖片上傳失敗...(image-40efd3-1561472145733)]
    • [圖片上傳失敗...(image-cd78c-1561472145733)]
    • [圖片上傳失敗...(image-2b40a-1561472145733)]
    • [圖片上傳失敗...(image-acc5c5-1561472145733)]

Autowired源碼解析

  • 從源碼可以看出赔蒲,Autowired的功能實(shí)現(xiàn)最重要的一個(gè)接口就是AutowiredAnnotationBeanPostProcessor泌神,繼承關(guān)系如下:
    [圖片上傳失敗...(image-518665-1561472145733)]
  • 從繼承關(guān)系圖可以看出,實(shí)際上關(guān)鍵的實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor這個(gè)接口舞虱。
  • 源碼實(shí)現(xiàn)如下圖:
    [圖片上傳失敗...(image-f8c9e8-1561472145733)]

總結(jié)

  • 源碼:
    • ioc容器創(chuàng)建Bean的方法是從createBean方法進(jìn)入的欢际,真正執(zhí)行創(chuàng)建的Bean的是doCreateBean方法,我們從createBean開(kāi)始往下走
      • 調(diào)用resolveBeforeInstantiation方法【在doCreatBean之前執(zhí)行矾兜,即是實(shí)例化之前】损趋,在內(nèi)部遍歷BeanPostProcessor調(diào)用postProcessBeforeInstantiation方法
      • 如果postProcessBeforeInstantiation方法返回null,那么需要執(zhí)行實(shí)例化的過(guò)程椅寺,調(diào)用doCreatBean實(shí)例化Bean浑槽。
        • doCreateBean內(nèi)部分為兩步:①調(diào)用createBeanInstance實(shí)例化Bean蒋失;②調(diào)用populateBean設(shè)置Bean的屬性
      • populateBean內(nèi)部分為如下的步驟:
        • 調(diào)用postProcessAfterInstantiation【實(shí)例化之后調(diào)用】,分為兩種情況:①返回false桐玻,后續(xù)的postProcessPropertyValues將不再執(zhí)行篙挽,屬性也不在進(jìn)行設(shè)置;②返回true畸冲,程序照常進(jìn)行嫉髓,調(diào)用postProcessPropertyValues,屬性設(shè)置的過(guò)程正常進(jìn)行
      • 執(zhí)行完populateBean之后將會(huì)調(diào)用initializeBean【初始化Bean邑闲,調(diào)用afterPropertiesSet方法】,在內(nèi)部就涉及到BeanPostProcessor定義的接口了梧油,步驟如下:
        • 執(zhí)行applyBeanPostProcessorsBeforeInitialization方法調(diào)用postProcessBeforeInitialization【在初始化之前調(diào)用】方法
        • 執(zhí)行invokeInitMethods方法苫耸,內(nèi)部其實(shí)是調(diào)用afterPropeertiesSet方法,進(jìn)行初始化
        • 執(zhí)行applyBeanPostProcessorsAfterInitialization儡陨,內(nèi)部調(diào)用postProcessAfterInitialization【在實(shí)例化之后調(diào)用】方法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末褪子,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子骗村,更是在濱河造成了極大的恐慌嫌褪,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胚股,死亡現(xiàn)場(chǎng)離奇詭異笼痛,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)琅拌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)缨伊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人进宝,你說(shuō)我怎么就攤上這事刻坊。” “怎么了党晋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵谭胚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我未玻,道長(zhǎng)灾而,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任深胳,我火速辦了婚禮绰疤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舞终。我一直安慰自己轻庆,他們只是感情好癣猾,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著余爆,像睡著了一般纷宇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛾方,一...
    開(kāi)封第一講書(shū)人閱讀 52,268評(píng)論 1 309
  • 那天像捶,我揣著相機(jī)與錄音,去河邊找鬼桩砰。 笑死拓春,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亚隅。 我是一名探鬼主播硼莽,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼煮纵!你這毒婦竟也來(lái)了懂鸵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤行疏,失蹤者是張志新(化名)和其女友劉穎匆光,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酿联,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡终息,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了货葬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片采幌。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖震桶,靈堂內(nèi)的尸體忽然破棺而出休傍,到底是詐尸還是另有隱情,我是刑警寧澤蹲姐,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布磨取,位于F島的核電站,受9級(jí)特大地震影響柴墩,放射性物質(zhì)發(fā)生泄漏忙厌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一江咳、第九天 我趴在偏房一處隱蔽的房頂上張望逢净。 院中可真熱鬧,春花似錦、人聲如沸爹土。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)胀茵。三九已至社露,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琼娘,已是汗流浹背峭弟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脱拼,地道東北人瞒瘸。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像熄浓,于是被迫代替她去往敵國(guó)和親挨务。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • 本來(lái)是準(zhǔn)備看一看Spring源碼的玉组。然后在知乎上看到來(lái)一個(gè)帖子,說(shuō)有一群**自己連Spring官方文檔都沒(méi)有完全讀...
    此魚(yú)不得水閱讀 6,937評(píng)論 4 21
  • 參考W3C Spring教程 Spring致力于J2EE應(yīng)用的各種解決方案丁侄,而不僅僅專注于某一層解決方案惯雳。可以說(shuō)S...
    王偵閱讀 1,172評(píng)論 0 6
  • 一鸿摇、Spring IOC其實(shí)很簡(jiǎn)單 ?有部分Java開(kāi)發(fā)者對(duì)IOC(Inversion Of Control)和D...
    Chandler_玨瑜閱讀 4,462評(píng)論 0 41
  • Spring容器高層視圖 Spring 啟動(dòng)時(shí)讀取應(yīng)用程序提供的Bean配置信息石景,并在Spring容器中生成一份相...
    Theriseof閱讀 2,819評(píng)論 1 24
  • 上班之后難得的休閑,一直連續(xù)的上班時(shí)間對(duì)于剛剛適應(yīng)新年工作的我有點(diǎn)小小的吃不消拙吉。 老弟最近心態(tài)上的問(wèn)題潮孽,也讓我一頭...
    Bonnie徐丫丫閱讀 188評(píng)論 0 0