Spring源碼分析

AnnotationConfigApplicationContext作為注解型IOC的入口
ClassPathXmlApplicationContext 作為XML IOC的入口

    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        this();
        register(componentClasses);
        refresh();
    }

傳入一個Class對象
首先this()初始化reader和scanner,創(chuàng)建beanFactory虽惭,這個this其實是執(zhí)行了父類GenericApplicationContext中的初始化方法

    /**
     * Create a new GenericApplicationContext.
     * @see #registerBeanDefinition
     * @see #refresh
     */
    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

他初始化了一個beanFactory琅束,beanFactory會記錄一些bean信息。
Register(class)通過AnnotatedBeanDefinitionReader去doRegisterBean()秕岛。
這里其實是把主類解析成BeanDefinition同時會解析主類上的注解會把配置類信息放進beanDefinitionMap蒂破。
refresh()方法,refresh是放在AbstractApplicationContext類中的抽象方法伪货,主要是對beanFactory進行一系列配置刷新袍啡。

refresh方法

  1. prepareBeanFactory()為 beanFactory 工廠添加一些單例內(nèi)置組件踩官,進行預處理
    預埋三級緩存
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }
  1. invokeBeanFactoryPostProcessors() 一個后置方法允許我們按需注入暴露了ConfigurableListableBeanFactory 和BeanDefinitionRegistry 。找出來境输,排序然后重新注入蔗牡。主要是對實現(xiàn)后置處理器的方法的一個調(diào)用。
    處理一些實現(xiàn)了后置處理器postProcessor的類嗅剖,然后調(diào)用postProcessor.postProcessBeanDefinitionRegistry(registry)
@Component
public class BeanDefinitionRegistryPostProcessorTest implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("A");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("B");
    }
}

初始化的時候允許自由修改registry與beanFactory

  1. registerBeanPostProcessors() 這一步是向容器中注入實現(xiàn)了 BeanPostProcessor的類辩越。注意是注冊而非使用
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // Remove from old position, if any
        this.beanPostProcessors.remove(beanPostProcessor);
        // Track whether it is instantiation/destruction aware
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
        // Add to end of list
        this.beanPostProcessors.add(beanPostProcessor);
    }
  1. initMessageSource() 初始化messageSource,對messageSource bean進行裝配信粮,messageSource是國際化文件
  2. initApplicationEventMulticaster()對BeanFactory中的ApplicationEventMulticaster的事件進行監(jiān)聽黔攒,通過實現(xiàn)ApplicationEventMulticaster接口來監(jiān)聽事件。如果沒有則采用SimpleApplicationEventMulticaster來監(jiān)聽事件强缘。初始化事件監(jiān)聽器亏钩,一種觀察者模式。
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) {
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        }
        else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }
  1. registerListeners() 找出實現(xiàn)ApplicationListener的類裝配進applicationListeners欺旧。其實是放到ApplicationEventMulticaster 廣播器里。發(fā)布事件通知蛤签,對應(yīng)Listener會收到消息進行處理辞友。
  2. finishBeanFactoryInitialization() ,直接看里面調(diào)用的beanFactory.preInstantiateSingletons()
    剩下來的這個步驟就是初始化所有剩余的單實例 bean震肮。RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName)獲取称龙。下面會根據(jù)是不是FactoryBean來選擇初始化方式。普通的直接走getBean()就行戳晌。transformedBeanName會獲得bean的真實名字
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged(
                                    (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

通過getBean()走到dogetBean()鲫尊。但其實里面最終都會走到getObjectForBeanInstance()。
在getObjectForBeanInstance()方法中會先判斷bean是不是FactoryBean沦偎,如果不是疫向,就直接返回Bean。

  • 如果是FactoryBean豪嚎,且name是以&符號開頭搔驼,那么表示的是獲取FactoryBean的原生對象,也會直接返回侈询。如果name不是以&符號開頭舌涨,那么表示要獲取FactoryBean中g(shù)etObject()方法返回的對象即Bean.class。
  • 接下來會先嘗試從緩存中獲取扔字,如果緩存中不存在則getObjectFromFactoryBean()然后doGetObjectFromFactoryBean()這樣走下去囊嘉。這是FactoryBean的流程温技。
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

再說一下dogetBean(),用到三級緩存的地方是getSingleton()方法扭粱,
singletonObjects一級緩存:單例對象緩存池舵鳞,beanName->Bean,其中存儲的是完整的Bean
earlySingletonObjects二級緩存早期的單例對象,beanName->ObjectFactory,存儲的是實例化后,屬性未賦值的單例對象
singletonFactories三級緩存:單例工廠的緩存焊刹,beanName->ObjectFactory,添加進去的時候?qū)嵗淳邆鋵傩?br> 一層一層往下找就是了系任,最后找不到調(diào)用singletonFactory.getObject()

                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName);
                        if (singletonObject == null) {
                            ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject();
                                this.earlySingletonObjects.put(beanName, singletonObject);
                                this.singletonFactories.remove(beanName);
                            }
                        }
                    }

  • 嘗試從一級緩存中查找完整的Bean實例,找到則直接返回.
  • 如果無法從一級緩存中查找虐块,對一級緩存進行上鎖俩滥,然后嘗試從二級緩存中查找半成品的Bean.找到直接返回.
  • 從三級緩存中查找,找到則放入二級緩存,同時為了保證一個對象實例為單例贺奠,將該實例從第三級緩存中進行移除

在這里判斷的循環(huán)依賴霜旧,如果一個beanName可以從單力池里拿到實例,而他還在創(chuàng)建說明這個類循環(huán)依賴儡率,就還會走到getObjectForBeanInstance()方法拿到對象挂据。Spring對于循環(huán)依賴的處理時不是一個一個去找,而是直接看池子里有沒有儿普。

        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

如果實在拿不到崎逃,就要開始創(chuàng)建了。首先會到ParentBeanFactory中進行遞歸查找眉孩。根據(jù)名稱和type个绍。對合并后的BeanDefinition進行檢測,主要是判斷是否為abstract浪汪,然后會找到所有依賴的Bean名稱巴柿,如果循環(huán)依賴直接拋異常,然后會遞歸走getBean死遭。
遞歸完成后走到getSingleton()走createBean()广恢。真正創(chuàng)建單例Bean前會檢測是否正在創(chuàng)建,做點預處理呀潭,最后都會走到createBean()钉迷。

                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

進到createBean()。先獲取Bean的Class放到BeanDefinition钠署。經(jīng)過方法重載以及代理對象判斷后走到doCreateBean()篷牌。
這里會再進一次緩存,如果拿不到BeanWrapper(包裝類對象)則調(diào)用createBeanInstance()來創(chuàng)建Bean實例踏幻,此時獲取類的構(gòu)造方法createBean枷颊,即調(diào)用autowireConstructor(),最典型的應(yīng)用就是Autowire打在構(gòu)造方法上。mbd.getConstructorArgumentValues()可以從BeanDefinition中拿到構(gòu)造函數(shù)信息夭苗,通過resolveConstructorArguments()拿到參數(shù)信卡。

        // Candidate constructors for autowiring?
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // Preferred constructors for default construction?
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }

這個時候會把BeanDefinition盡早放進SingletonFactory。然后會進行依賴注入题造,再看下屬性注入傍菇,走到populateBean()方法會通過BeanDefinition進行屬性判斷。這里會選擇名稱進行注入或者根據(jù)類型進行注入界赔。這里最后還是走getBean遞歸

        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }

通過名稱注入丢习,先通過 unsatisfiedNonSimpleProperties() 找到需要填充的所有屬性 name。然后遞歸getbean加載屬性

    protected void autowireByName(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            if (containsBean(propertyName)) {
                Object bean = getBean(propertyName);
                pvs.add(propertyName, bean);
                registerDependentBean(propertyName, beanName);
                if (logger.isTraceEnabled()) {
                    logger.trace("Added autowiring by name from bean name '" + beanName +
                            "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
                }
            }
            else {
                if (logger.isTraceEnabled()) {
                    logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                            "' by name: no matching bean found");
                }
            }
        }
    }

類型則是先通過 unsatisfiedNonSimpleProperties() 找到需要填充的所有屬性 name淮悼,根據(jù)傳入的參數(shù) pvs 中找出已經(jīng)加載的 bean咐低,并遞歸實例化,然后再加入到 pvs 中

            try {
                PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                // Don't try autowiring by type for type Object: never makes sense,
                // even if it technically is a unsatisfied, non-simple property.
                if (Object.class != pd.getPropertyType()) {
                    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                    // Do not allow eager init for type matching in case of a prioritized post-processor.
                    boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if (autowiredArgument != null) {
                        pvs.add(propertyName, autowiredArgument);
                    }
                    for (String autowiredBeanName : autowiredBeanNames) {
                        registerDependentBean(autowiredBeanName, beanName);
                        if (logger.isTraceEnabled()) {
                            logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                    propertyName + "' to bean named '" + autowiredBeanName + "'");
                        }
                    }
                    autowiredBeanNames.clear();
                }
            }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袜腥,一起剝皮案震驚了整個濱河市见擦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌羹令,老刑警劉巖鲤屡,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異福侈,居然都是意外死亡酒来,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門肪凛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來役首,“玉大人,你說我怎么就攤上這事显拜。” “怎么了爹袁?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵远荠,是天一觀的道長。 經(jīng)常有香客問我失息,道長譬淳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任盹兢,我火速辦了婚禮邻梆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绎秒。我一直安慰自己浦妄,他們只是感情好,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剂娄,像睡著了一般蠢涝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阅懦,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天和二,我揣著相機與錄音,去河邊找鬼耳胎。 笑死惯吕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的怕午。 我是一名探鬼主播废登,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诗轻!你這毒婦竟也來了钳宪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤扳炬,失蹤者是張志新(化名)和其女友劉穎吏颖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恨樟,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡半醉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了劝术。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缩多。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖养晋,靈堂內(nèi)的尸體忽然破棺而出衬吆,到底是詐尸還是另有隱情,我是刑警寧澤绳泉,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布逊抡,位于F島的核電站,受9級特大地震影響零酪,放射性物質(zhì)發(fā)生泄漏冒嫡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一四苇、第九天 我趴在偏房一處隱蔽的房頂上張望孝凌。 院中可真熱鬧,春花似錦月腋、人聲如沸蟀架。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辜窑。三九已至钩述,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間穆碎,已是汗流浹背牙勘。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留所禀,地道東北人方面。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像色徘,于是被迫代替她去往敵國和親恭金。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

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