spring上下文

作者: binecy | 来源:发表于2018-01-11 17:45 被阅读19次

源码分析基于spring 4.3.x

前面已经说过spring 创建bean的过程, 也强调了BeanPostProcessor这些扩展接口。

在 创建bean过程中, spring会查找用户定义的BeanPostProcessor并进行相应操作, 那么问题来了, 用户定义的BeanPostProcessor是怎样进入spring的呢?
这里就要说到spring context了。

我们先来看看spring 模块

spring-modules.png
(图片出自 Framework Modules

Spring-core和Spring-beans模块提供了spring的框架基础,包括IoC和依赖注入功能。

Context(spring-context)模块建立在Core和Beans模块提供的可靠基础之上。Context模块增加了对国际化(例如使用资源包),事件传播,资源加载,上下文透明创建(如Servlet容器)的支持。Context模块还支持Java EE功能,如EJB,JMX和基本的远程处理。ApplicationContext接口是Context模块的焦点。

将用户定义的BeanPostProcessor加载到spring,正是spring context的工作。

回顾一下在spring加载配置中说到的测试例子, 修改为如下就可以使用到spring context了:

@Test
public void test() {
    ClassPathXmlApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring.xml");
    Blog bean = (Blog)beanFactory.getBean("blog");
    Assert.assertEquals(bean.getTitle(), "hello spring");
}

ClassPathXmlApplicationContext的继承层次很深, spring一般按功能的叠加会划分继承关系。


applicationContext.png

context可以简单分为web上下文, 非web的上下文。
这里直接看看例子中的ClassPathXmlApplicationContext

先看看构造方法

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}   

核心方法为refresh(),这个方法在AbstractApplicationContext中

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 准备刷新上下文环境
        prepareRefresh();

        // 初始化BeanFactory,并读取xml文件
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 对beanFacotry进行配置
        prepareBeanFactory(beanFactory);

        try {
            // 提供给子类覆盖方法做额外处理
            postProcessBeanFactory(beanFactory);

            // 激活BeanFactoryPostProcessors
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册BeanPostProcessors
            registerBeanPostProcessors(beanFactory);

            initMessageSource();

            // 初始化广播器,并放到上下文中   
            initApplicationEventMulticaster();

            // 提供给子类初始化其他的Bean
            onRefresh();

            // 注册事件监听器
            registerListeners();

            // 初始化剩下的非惰性单例bean
            finishBeanFactoryInitialization(beanFactory);

            // 完成刷新过程,通知生命周期处理器
            finishRefresh();
        }
        catch (BeansException ex) {
            ...
        } finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

初始化BeanFactory,读取context文件

obtainFreshBeanFactory负责初始化BeanFactory,并读取context文件

初始化BeanFactory

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

关键方法是refreshBeanFactory, getBeanFactory只是获取创建好的BeanFactory,refreshBeanFactory由AbstractRefreshableApplicationContext实现

protected final void refreshBeanFactory() throws BeansException {
    // 如果BeanFactory已存在,则销毁
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建beanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();   
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        // 读取xml
        loadBeanDefinitions(beanFactory);
        // beanFactory赋值
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}


protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

前面已经说过了, spring加载配置主要就是通过DefaultListableBeanFactory。

读取context文件

在看看读取xml文件的方法loadBeanDefinitions(DefaultListableBeanFactory beanFactory),该方法由AbstractXmlApplicationContext实现

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 创建XmlBeanDefinitionReader
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 配置XmlBeanDefinitionReader
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // 模板方法
    initBeanDefinitionReader(beanDefinitionReader);
    // 读取xml文件
    loadBeanDefinitions(beanDefinitionReader);
}

这里的loadBeanDefinitions(XmlBeanDefinitionReader reader)由AbstractXmlApplicationContext实现

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    // getConfigResources模板方法,提供子类扩展
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    // 获取用户指定的context文件
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}

这里通过XmlBeanDefinitionReader.loadBeanDefinitions读取xml文件, 并将结果加载到spring中(在spring加载配置中已经说过了)。

激活BeanFactoryPostProcessors

BeanFactoryPostProcessor也是spring提供的扩展接口,可以通过BeanFactoryPostProcessor对beanFactory进行处理,如修改其他BeanDefinition的配置。

这里会调用AbstractApplicationContext.invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    ...
}

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors会找到用户定义的BeanFactoryPostProcessor,并调用它们。

注册BeanPostProcessors

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

PostProcessorRegistrationDelegate.registerBeanPostProcessors会找到用户定义的BeanPostProcessor, 并注册到spring中, spring创建bean时会使用到它们。

初始化事件广播器

Spring事件体系包括三个组件:事件ApplicationEvent,事件监听器ApplicationListener,事件广播器ApplicationEventMulticaster。事件广播器负责管理事件监听器,并将事件广播给监听器。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // beanFactory中包含了事件广播器
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {   
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    }
    else {  // 使用默认的事件广播器
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}

注册事件监听器

事件监听器负责监听事件,并做出处理。
registerListeners将初始化事件监听器,并添加到事件广播器上。

protected void registerListeners() {
    // 首先注册静态指定的侦听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 注册spring上下文中的ApplicationListener
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 发布在此之前已发生的事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

初始化非惰性单例bean

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 初始化ConversionService
    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));
    }

    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }

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

    beanFactory.setTempClassLoader(null);

    beanFactory.freezeConfiguration();

    // 初始化非惰性单例bean
    beanFactory.preInstantiateSingletons();
}

finishRefresh

protected void finishRefresh() {
    // 初始化LifecycleProcessor
    initLifecycleProcessor();

    // 触发LifecycleProcessor.onRefresh()
    getLifecycleProcessor().onRefresh();

    // 发布事件
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    LiveBeansView.registerApplicationContext(this);
}

LifecycleProcessor也是spring提供的扩展点, 它可以定义spring启动(start),停止(stop),或刷新(onRefresh)时的额外操作。

protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
    }
    else {  // 使用默认的LifecycleProcessor
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
    }
}

这里主要讲了spring context事件传播,上下文创建, 加载扩展接口等内容,讲的比较简单,很多地方都是蜻蜓点水, 有兴趣的同学可以自行深入阅读源码。

相关文章

网友评论

    本文标题:spring上下文

    本文链接:https://www.haomeiwen.com/subject/buyznxtx.html