Spring IoC Container源码分析(二)-bean初始化流程

准备

Person实例

@Data
public class Person {
    private String name;
    private int age;
}

xml bean配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="person" class="com.gcdd1993.spring.framework.base.domain.Person"/>
</beans>

入口

AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("config.xml");
applicationContext.getBean("person");

使用Debug进入ClassPathXmlApplicationContext构造函数,源码如下

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {

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

super(parent)

一步步向上调用父类构造函数,路径为

ClassPathXmlApplicationContext -> AbstractXmlApplicationContext -> AbstractRefreshableConfigApplicationContext -> AbstractRefreshableApplicationContext -> AbstractApplicationContext

历经整个继承体系,最终到达AbstractApplicationContext:

public AbstractApplicationContext(ApplicationContext parent) {
    this();
    setParent(parent);
}

最后会设置当前ApplicationContext的父级ApplicationContext

setConfigLocations(configLocations)

设置配置文件路径,解析的细节参照官方文档Resource一节,不是本文讨论的重点,在此略过。

public void setConfigLocations(String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

refresh()

此方法是Spring容器的核心方法,源码(精简了try catch部分)如下:

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

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

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

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

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

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

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

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

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

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

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

    // Last step: publish corresponding event.
    finishRefresh();
}

此处可以看到Spring编码方式近似于流程图的,重点部分都抽出为了单独的方法,流程清晰,易于理解。我们一步步看:

prepareRefresh()

上下文刷新前预热

protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }

    // Initialize any placeholder property sources in the context environment
    initPropertySources();

    // Validate that all properties marked as required are resolvable
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
  1. 设置上下文基本信息,如startupDate(启动时刻)、closed(是否关闭)、active(是否存活)等等。
  2. 解析占位符资源,并验证标记为required的资源是否可用

obtainFreshBeanFactory()

初始化beanFactory(bean工厂,实际存放bean的就是它了)

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

核心方法refreshBeanFactory()

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);
    }
}
  1. createBeanFactory();
  2. 设置beanFactory属性
  3. loadBeanDefinitions(beanFactory);

loadBeanDefinitions(beanFactory)

解析bean定义,有几个bean就有几个BeanDefinition。注意,Spring并不是拿到配置就直接用反射实例化bean,而是先将bean配置解析为BeanDefinition。

BeanDefinition保存了实例化bean需要的一切信息,包括属性,依赖等。以ConcurrentHashMap<String, BeanDefinition>保存在DefaultListableBeanFactory的beanDefinitionMap里。

prepareBeanFactory(beanFactory)

设置beanFactory的其余属性

postProcessBeanFactory(beanFactory)

空实现,给子类一个机会,自定义beanFactory后置处理器

BeanFactoryPostProcessor定义:

public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

invokeBeanFactoryPostProcessors(beanFactory)

执行上一步中的beanFactory后置处理器的回调方法void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)

registerBeanPostProcessors(beanFactory)

注册bean后置处理器,实现bean初始化前后的自定义逻辑

BeanPostProcessor定义:

public interface BeanPostProcessor {
    // 在bean实例化前调用
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // 在bean实例化后调用
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

initMessageSource()

注册国际化相关bean

initApplicationEventMulticaster()

初始化Spring事件发布相关bean

onRefresh()

空实现,给子类一个机会,初始化特殊bean

registerListeners()

注册监听器

finishBeanFactoryInitialization(beanFactory)

实例化所有非懒加载的bean

直到这里,才开始真正实例化bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 1. 实例化bean的类型转换器
    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));
    }

    // 2. 实例化属性占位符解析器
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }

    // 3. 实例化LoadTimeWeaverAware
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // 4. 停止使用临时ClassLoader进行类型匹配
    beanFactory.setTempClassLoader(null);

    // 5. 禁止再修改bean定义
    beanFactory.freezeConfiguration();

    // 6. 实例化所有非懒加载单例bean
    beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons()

  1. 根据每一个bean定义,实例化bean
  2. 为每一个实现SmartInitializingSingleton的bean执行回调方法

实例化bean部分的代码:

for (String beanName : beanNames) {
    // 获取bean定义
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // 只有不是abstract、单例且不是懒加载的bean才在这里实例化
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        // 如果是FactoryBean
        if (isFactoryBean(beanName)) {
            // 先实例化实例对应的FactoryBean
            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) {
                // 使用FactoryBean的getObject()方法返回真正的实例
                getBean(beanName);
            }
        }
        else {
            getBean(beanName);
        }
    }
}

getBean(String name)

该方法调用了一个doGetBean,doGetBean代码较长,而且有部分代码是为了解决并发场景下单例的生成,我们挑出重点的看:

  1. 从父BeanFactory检查是否存在该bean的定义,如果存在,委托父BeanFactory来实例化
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    String nameToLookup = originalBeanName(name);
    if (args != null) {
        // Delegation to parent with explicit args.
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    }
    else {
        // No args -> delegate to standard getBean method.
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
}
  1. 获得bean定义,如果存在依赖,先实例化每一个依赖bean,注意:不允许循环依赖
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
//如果存在依赖,先实例化每一个依赖bean
if (dependsOn != null) {
    // 实例化每一个依赖bean
    for (String dep : dependsOn) {
        // 检查循环依赖
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        // 实例化依赖bean
        registerDependentBean(dep, beanName);
        try {
            getBean(dep);
        }
        catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
    }
}
  1. 实例化bean

方法调用流程:

createBean > doCreateBean > populateBean

其中doCreateBean:

  1. 从BeanDefinition生成BeanWrapper
  2. 将BeanWrapper和BeanDefinition.getPropertyValues() 传给populateBean,实例化bean

finishRefresh()

protected void finishRefresh() {
    // 初始化生命周期处理器
    initLifecycleProcessor();

    // 刷新生命周期处理器状态 running = true
    getLifecycleProcessor().onRefresh();

    // 发布上下文初始化完成事件ContextRefreshedEvent
    publishEvent(new ContextRefreshedEvent(this));

    // 如果处于活动状态,将自己注册到LiveBeans
    LiveBeansView.registerApplicationContext(this);
}

总结

Spring IoC Container时序图

猜你喜欢

转载自www.cnblogs.com/gcdd/p/12292313.html