spring 源碼分析(二)Core

spring 源碼分析(二)Core

sschrodinger

2019/03/14


參考


Spring 中 Bean 的生命周期是怎樣的?-
大閑人柴毛毛

Spring Bean Life Cycle Explained - by - Lokesh Gupta

基于 spring centext 5.1.3.RELEASE


簡介


在 spring 中匠襟,使用 Bean 代指 spring 所管理的類,如上一節(jié)的 ServiceImpl,同時,spring 也規(guī)定了 Bean 的生命周期岔留,不同于普通類從載入到被垃圾回收器回收的生命周期,spring 實現(xiàn)了更加詳盡的生命周期检柬。spring bean 的生命周期如下:

  1. 實例化 bean 對象献联,即 new XX();
  2. 填充對象屬性
  3. 檢查Aware相關(guān)接口并設(shè)置相關(guān)依賴
  4. BeanPostProcessor 前置處理
  5. 檢查是否是 InitializingBean 決定是否調(diào)用 afterPropertiesSet 方法,檢查是否有自定義的 init-method何址,有的話調(diào)用
  6. BeanPosetProcessor 后置處理
  7. 注冊必要的 Destruction 相關(guān)回調(diào)接口
  8. 使用
  9. 是否實現(xiàn) DisposableBean 相關(guān)接口里逆,是的話執(zhí)行 destroy() 函數(shù)。
  10. 是否有自定義 destroy 方法用爪,是的話執(zhí)行原押。

詳細解釋參見大閑人柴毛毛知乎


組件簡介


BeanFactory

BeanFactory 是 spring 最基本的一個庫,BeanFactory 實現(xiàn)了 Bean 對象的管理偎血,包括如何利用 Bean 的名字獲得 Bean 對象等诸衔。BeanFactory 的接口如下:

public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";

    //根據(jù) bean name 獲得bean 對象
    Object getBean(String name) throws BeansException;
    
    //根據(jù) bean name 獲得 bean 對象并轉(zhuǎn)化成正確類型
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    //利用 bean name 獲得 bean 對象,并用 args 覆蓋一些配置
    Object getBean(String name, Object... args) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    boolean containsBean(String name);

    //bean 是否為單例模式
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    //是否為 原型模式
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    String[] getAliases(String name);

}

依據(jù) BeanFactory 所派生的接口非常復(fù)雜颇玷,大概有 20 個左右的類笨农。典型的接口如下:

//顧名思義,層級 BeanFactory帖渠,可以獲得上一級 BeanFatory谒亦,并且可以判斷某名字的 Bean 是否在該 BeanFacory 中。
public interface HierarchicalBeanFactory extends BeanFactory {

    BeanFactory getParentBeanFactory();

    boolean containsLocalBean(String name);

}
//能夠自動注解的類
public interface AutowireCapableBeanFactory extends BeanFactory {

    int AUTOWIRE_NO = 0;

    int AUTOWIRE_BY_NAME = 1;

    int AUTOWIRE_BY_TYPE = 2;

    int AUTOWIRE_CONSTRUCTOR = 3;

    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;

    String ORIGINAL_INSTANCE_SUFFIX = ".ORIGINAL";

    <T> T createBean(Class<T> beanClass) throws BeansException;

    void autowireBean(Object existingBean) throws BeansException;

    Object configureBean(Object existingBean, String beanName) throws BeansException;


    //-------------------------------------------------------------------------
    // Specialized methods for fine-grained control over the bean lifecycle
    //-------------------------------------------------------------------------

    Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
            throws BeansException;

    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;

    Object initializeBean(Object existingBean, String beanName) throws BeansException;

    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException;

    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException;

    void destroyBean(Object existingBean);


    //-------------------------------------------------------------------------
    // Delegate methods for resolving injection points
    //-------------------------------------------------------------------------

    <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;

    @Nullable
    Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) throws BeansException;

    @Nullable
    Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException;

}
//可以計數(shù)的 BeanFactory
public interface ListableBeanFactory extends BeanFactory {

    boolean containsBeanDefinition(String beanName);

    int getBeanDefinitionCount();

    String[] getBeanDefinitionNames();

    String[] getBeanNamesForType(ResolvableType type);

    String[] getBeanNamesForType(@Nullable Class<?> type);

    String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);

    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;

    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;

    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
            throws NoSuchBeanDefinitionException;

}
//最重要的一個接口,spring 中大部分的實例都是使用的該接口
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

    @Nullable
    String getId();

    String getApplicationName();

    String getDisplayName();

    long getStartupDate();

    @Nullable
    ApplicationContext getParent();

    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

}

ConfigurableApplicationContext 繼承自 ApplicationContext诊霹,增加了一些配置的功能羞延,如設(shè)置 context ID,最重要的是增加了 addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)void refresh() throws BeansException, IllegalStateException 方法脾还,用于實現(xiàn) context 的刷新和初始化之前的一些操作伴箩。

BeanDefinition

用于保存每一個 bean 的定義。

BeanWrapper

用于封裝需要注入的類鄙漏,并提供 set 方式嗤谚,以避免用反射的方式設(shè)置屬性。

AbstractBeanDefinitionReader

AbstractBeanDefinitionReader 實現(xiàn)了 BeanDefinitionReader 接口和 EnvironmentCapable 接口怔蚌,主要作用是讀取配置文件并生成對應(yīng) Bean 的配置巩步。


處理流程分析


以如下的代碼分析處理流程,代碼如下:

package ioc;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring_ioc.xml");
        Service service = (Service) context.getBean("serviceImpl");
        service.doSomething();
    }

}
package ioc;

public interface Service {

    public void doSomething();

}
package ioc;

public class ServiceImpl implements Service {

    public void doSomething() {
        System.out.println(this.getClass().getName() + "#doSomething");
    }

}
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
       ">
    <bean name="serviceImpl" class="ioc.ServiceImpl">

    </bean>

</beans>

Bean 的生命周期分為10個步驟桦踊,按照步驟一步一步說明 BeanFactory 如何管理 Bean椅野。

初始化

這里的初始化指的是 Bean 生命周期中 Bean 實例準備就緒之前的所有動作。

準備工作

Bean 的初始化始于 ApplicationContext context = new ClassPathXmlApplicationContext("spring_ioc.xml")籍胯,總結(jié)來說就是讀取配置文件并生成實例竟闪。

ClaaPathXmlApplicationContextAbstractXmlApplicationContext 的子類,作用就是從 classpath 中查找配置文件并對 Bean 進行初始化杖狼。

ClaaPathXmlApplicationContext 的初始化函數(shù)如下:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

實際上是調(diào)用繼承的初始化函數(shù)炼蛤,并對 Bean 刷新。

super(parent) 方法在 AbstractApplicationContext 中正真執(zhí)行蝶涩,代碼如下:

public AbstractApplicationContext(@Nullable ApplicationContext parent) {
    this();
    setParent(parent);
}
public AbstractApplicationContext() {
    this.resourcePatternResolver = getResourcePatternResolver();
}

實際上作用只是獲得一個 ResourcePatternResolver理朋。
setConfigLocations(configLocations) 用于設(shè)定 confifLocation 的位置,并存儲绿聘。

最重要的函數(shù)是 refresh 方法嗽上,通過 refresh 更新 BeanFactoryrefresh 的方法實現(xiàn)在 AbstractApplicationContext 中熄攘,具體實現(xiàn)如下:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //step 1
        // Prepare this context for refreshing.
        prepareRefresh();

        //step 2
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        //step 3
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            //step 4
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            //step 5
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            //step 6
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            //step 7
            // Initialize message source for this context.
            initMessageSource();

            //step 8
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            //step 9
            // Initialize other special beans in specific context subclasses.
            onRefresh();

            //step 10
            // Check for listener beans and register them.
            registerListeners();

            //step 11
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            //step 12
            // Last step: publish corresponding event.
            finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

第一步

prepareRefresh()主要是做一些檢查的工作炸裆,并將當前的 BeanFacory 的屬性設(shè)置為激活。

第二步

obtainFreshBeanFactory 是真正的初始化函數(shù)鲜屏,函數(shù)定義如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

更新 BeanFactory 并將 BeanFactory 返回。其中国拇,refreshBeanFactory() 交給了子類實現(xiàn)洛史。具體的實現(xiàn)在 AbstractRefreshableApplicationContext 中。具體代碼如下:

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    } catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

當存在 beanFactory 時酱吝,首先先注銷原來的 BeanFactory也殖,接下來創(chuàng)建一個新的內(nèi)部 BeanFactory,設(shè)置序列號,并在 customizeBeanFactory(beanFactory) 中設(shè)置是否允許覆蓋定義(默認允許)忆嗜,最重要的是 loadBeanDefinitions 函數(shù)己儒,他負責了讀取配置并對 Bean 進行加載。

loadBeanDefinitions 函數(shù)由其子類 AbstractXmlApplicationContext 實現(xiàn)捆毫。主要功能實解析 xml 文件并產(chǎn)生 Bean Definition闪湾。

解析 xml 文件
loadBeanDefinitions() 函數(shù)的實現(xiàn)如下:

@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

可以看到主要是生成一個 XmlBeanDefinitionReader 實例對 xml 文件進行解析。以下的函數(shù)都是實現(xiàn)在其父類 AbstractBeanDefinitionReader 中的方法绩卤,提供通用的加載策略途样。最重要的是 loadBeanDefinitions(beanDefinitionReader) 函數(shù)。函數(shù)定義如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}

因為使用 configLocation 加載配置濒憋,所以 configResources 為空何暇,Resource 接口定義了資源是否存在,資源是否準備好凛驮,資源是否是文件等信息裆站,一般用于網(wǎng)絡(luò)資源的加載。我們只關(guān)心以 Stringp[] 作為參數(shù)的 loadBeanDefinitions 函數(shù)黔夭。
定義如下:

@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) {
        count += loadBeanDefinitions(location);
    }
    return count;
}

邏輯很簡單宏胯,有多少個文件就執(zhí)行多少次 loadDefinition 函數(shù),并計數(shù)纠修。真正的處理函數(shù)在 loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) 中胳嘲。代碼如下:

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
                "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        // Resource pattern matching available.
        try {
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            int count = loadBeanDefinitions(resources);
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    } else {
        // Can only load single resources by absolute URL.
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}

ClassPathXmlApplicationContext 的實現(xiàn)中,他既繼承了 BeanFactory扣草,也同時繼承了 ResourceLoaderResourcePatternResolver 即可以實現(xiàn)資源的加載和將 url 封裝成 Resource 的功能了牛。

url 經(jīng)過解析之后,實際上還是調(diào)用的 loadDefinifions(Resource[])辰妙,這時鹰祸,Resource 中包含了 path 和類加載器。我們再看 loadDefinifions(Resource[])密浑,定義如下:

@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int count = 0;
    for (Resource resource : resources) {
        count += loadBeanDefinitions(resource);
    }
    return count;
}

loadBeanDefinitions(Resource) 由其子類重寫蛙婴,用來加載真正的資源。XmlBeanDefinitionReader 實現(xiàn)如下:

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //EncodedResource 封裝了 encode 方法和 encode 的編碼類型
    return loadBeanDefinitions(new EncodedResource(resource));
}

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    //resourcesCurrentlyBeingLoaded 是一個 ThreadLocal 變量尔破,用于安全的線程中存儲數(shù)據(jù).
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    //將 encodedResource 添加到 ThreadLocal 中街图。
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            //解析數(shù)據(jù)
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        } finally {
            inputStream.close();
        }
    } catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    } finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {

    try {
        Document doc = doLoadDocument(inputSource, resource);
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    catch...
}

doLoadBeanDefinitions 主要有兩個步驟,第一個步驟是獲得 xml 的 Document 文檔懒构,第二個步驟是將文檔中的 Bean 定義注冊到 context 中餐济。

第一個步驟的代碼如下:

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    //生成 Document,利用 EntityResolver 解析 SAX 文件(DTD等)胆剧,生成Document
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
            getValidationModeForResource(resource), isNamespaceAware());
}

第二個步驟的代碼如下:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

Registry 是存儲 Bean 的結(jié)構(gòu)絮姆,在這里,默認使用 DefaultListableBeanFactory 實現(xiàn)。解析 Document 文件并根據(jù)解析結(jié)果將 BeanDefinition 存儲在 Regist 中篙悯。

第三步

prepareBeanFactory 主要是對 beanFactory 做一些初始化蚁阳,比如說設(shè)置 classLoader,忽略的接口鸽照,并提前注冊一些 Bean螺捐,如使用 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory) 函數(shù)注冊他自身,或者注冊單例模式(使用 beanFactory.registerSingleton()函數(shù))移宅。代碼如下:

/**
     * Configure the factory's standard context characteristics,
     * such as the context's ClassLoader and post-processors.
     * @param beanFactory the BeanFactory to configure
     */
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()));

    // Configure the bean factory with context callbacks.
    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);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Register early post-processor for detecting inner beans as ApplicationListeners.
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

第四步

postProcessBeanFactory(beanFactory) 允許子類對 beanFactory 做一些自定義的操作归粉,這里沒有實現(xiàn),是一個空方法漏峰。

第五步

invokeBeanFactoryPostProcessors 實例化所有注冊的的 BeanFactoryPostProcessor Bean糠悼。

第六步

registerBeanPostProcessors(beanFactory) 注冊預(yù)處理器。

第七步

initMessageSource()浅乔,初始化數(shù)據(jù)源倔喂。

第八步

initApplicationEventMulticaster(),初始化多播器靖苇。

第九步

onRefresh()席噩,更新。子類未實現(xiàn)贤壁。

第十步

registerListeners() 第九步悼枢,注冊監(jiān)聽器

第十一步

finishBeanFactoryInitialization() 初始化所有剩下的Beans,集體實現(xiàn)如下:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }

    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    //此時禁止配置脾拆,以防止出現(xiàn)不可預(yù)料的問題
    beanFactory.freezeConfiguration();

    //初始化剩下的單例 Bean
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

重點函數(shù)在 preInstantiateSingletons 上馒索。這個函數(shù)負責真正加載單例 Bean。代碼如下:

@Override
public void preInstantiateSingletons() throws BeansException {

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 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)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final 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);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            } else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

首先獲得所有 Bean 的名字名船,通過名字獲得 BeanDefinition绰上,如果不是 FactoryBean 的話,執(zhí)行 getBean(beanName)渠驼。

getBean()doGetBean() 具體實現(xiàn)蜈块,實現(xiàn)是在 AbstractBeanFactory 中,具體實現(xiàn)如下:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    final String beanName = transformedBeanName(name);
    Object bean;

    // phase 1
    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // phase 2
        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            } else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);
            
            // phase 3
            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // phase 4
            // 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);
            } else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            } else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        } finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                } catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        } catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        } catch (TypeMismatchException ex) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

代碼非常的長迷扇,將其分段百揭。

第一階段,主要是在人工注入的 Register 中有沒有 Bean蜓席,如果有信峻,返回。

第二階段瓮床,檢查父節(jié)點中有沒有 Bean,有,返回隘庄。

第三階段踢步,主要是檢查 有沒有循環(huán)依賴,循環(huán)依賴的報錯就是在這產(chǎn)生的丑掺。并且初始化所有的依賴 Bean获印。

第四階段,調(diào)用 createBean(beanName, mbd, args) 新建一個單例 bean街州。在這一階段兼丰,做了生命周期中大量的工作,包括初始化 Bean唆缴、填充屬性鳍征、如果繼承自 BeanNameAware,設(shè)置 Bean name面徽、如果繼承自 BeanFactoryAware艳丛,設(shè)置 BeanFactory、調(diào)用BeanPostProcessorpostProcessBeforeInitialization 做一些前期處理趟紊、如果繼承了 InitializingBean 接口氮双,則調(diào)用 afterPropertiesSet 方法、如果繼承了 BeanPostProcess 接口霎匈,則調(diào)用 postProcessAfterInitialization 方法戴差。可以說铛嘱,這一步暖释,實現(xiàn)了 Bean 大部分的生命周期函數(shù)。

第十二步

finishRefresh()弄痹,主要是做一些收尾工作饭入。

至此,初始化 Bean 的工作九到此結(jié)束肛真。

使用過程

使用過程和初始化復(fù)用了大量的代碼谐丢,主要是 getBean() 函數(shù)的代碼,唯一的區(qū)別是在初始化時蚓让,要新建實例乾忱,而使用時直接從緩存中讀取數(shù)據(jù)并返回。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末历极,一起剝皮案震驚了整個濱河市窄瘟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趟卸,老刑警劉巖氏义,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異图云,居然都是意外死亡惯悠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門竣况,熙熙樓的掌柜王于貴愁眉苦臉地迎上來克婶,“玉大人,你說我怎么就攤上這事丹泉∏橛” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵摹恨,是天一觀的道長筋岛。 經(jīng)常有香客問我,道長睬塌,這世上最難降的妖魔是什么泉蝌? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮揩晴,結(jié)果婚禮上勋陪,老公的妹妹穿的比我還像新娘。我一直安慰自己硫兰,他們只是感情好诅愚,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著劫映,像睡著了一般违孝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泳赋,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天雌桑,我揣著相機與錄音,去河邊找鬼祖今。 笑死校坑,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的千诬。 我是一名探鬼主播耍目,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼徐绑!你這毒婦竟也來了邪驮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤傲茄,失蹤者是張志新(化名)和其女友劉穎毅访,沒想到半個月后沮榜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡喻粹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年敞映,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磷斧。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖捷犹,靈堂內(nèi)的尸體忽然破棺而出弛饭,到底是詐尸還是另有隱情,我是刑警寧澤萍歉,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布侣颂,位于F島的核電站,受9級特大地震影響枪孩,放射性物質(zhì)發(fā)生泄漏憔晒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一蔑舞、第九天 我趴在偏房一處隱蔽的房頂上張望拒担。 院中可真熱鬧,春花似錦攻询、人聲如沸从撼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽低零。三九已至,卻和暖如春拯杠,著一層夾襖步出監(jiān)牢的瞬間掏婶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工潭陪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雄妥,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓畔咧,卻偏偏與公主長得像茎芭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子誓沸,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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