zoukankan      html  css  js  c++  java
  • spring源码分析之context

    重点类:

    1、ApplicationContext是核心接口,它为一个应用提供了环境配置。当应用在运行时ApplicationContext是只读的,但你可以在该接口的实现中来支持reload功能。

    定义

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
            MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    }

    特点:

    提供了一个bean工厂方法来访问应用组件,通过继承org.springframework.beans.factory.ListableBeanFactory来获得的;

    通过通用的方式来加载文件资源的能力,通过继承org.springframework.core.io.ResourceLoader来获得的;

    发布事件到注册的监听器的能力,通过继承ApplicationEventPublisher来获得的;

    解析消息,支持国际化的能力,通过继承MessageSource来获得的;

    context的继承机制。定义在子context将优先级别更高。这意味着,例如:一个父context可以被整个web应用共享,而每个servlet可以有自己的子context,并且这些servlet彼此独立。例如http://www.cnblogs.com/davidwang456/p/4122842.html

    另外还有标准的org.springframework.beans.factory.BeanFactory的生命周期管理能力,ApplicationContext实现类发现和触发beanApplicationContextAware,还包括ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware bean。

    1.1 EnvironmentCapable

    包含并暴露了Environment引用的接口。定义

    public interface EnvironmentCapable {
    
        /**
         * Return the {@link Environment} associated with this component.
         */
        Environment getEnvironment();
    
    }

    其中,Environment表示当前运行的应用所在的环境,它有两个重要的熟悉:profiles和properties。

    proportiers相关方法通过父接口PropertyResolver来暴露。

    profile用来为注册的bean进行逻辑分组的工具,例如开发环境,测试环境,发布环境等。profile的激活可以通过设置AbstractEnvironment#ACTIVE_PROFILES_PROPERTY_NAME"spring.profiles.active"的系统

    属性,也可以通过调用ConfigurableEnvironment的setActiveProfiles(String...)来激活。

    1.2 ListableBeanFactory

    ListableBeanFactory可以枚举所有bean的实例。注意,若该Beanfactory是HierarchicalBeanFactory,那么将不会考虑BeanFactory的继承关系,只返回当前工厂定义的相关bean。可以使用BeanFactoryUtils工具类获取父beanfactory的bean。

    1.3 HierarchicalBeanFactory

    HierarchicalBeanFactory可以通过方法BeanFactory getParentBeanFactory()获取父BeanFactory,其子接口定义了设置父BeanFactory的方法:void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

     1.4 MessageSource

    MessageSource是解析消息的策略接口,支持消息的参数化和国际化。

    spring提供两种开箱即用的可用于生产的实现:

    org.springframework.context.support.ResourceBundleMessageSource 基于标准的java.util.ResourceBundle消息解析方式

    org.springframework.context.support.ReloadableResourceBundleMessageSource 具有无需重启VM即可重载消息定义的能力。

     1.5 Application事件机制

    1.5.1 EventPublisher事件发布

    ApplicationEventPublisher接口封装了事件发布功能,作为ApplicationContext的父接口使用。

    ApplicationEvent:继承自java.util.EventObject的抽象类,可以由所有的application事件扩展,但不能作为直接发布通用事件的类。常用的事件有:

    实现发布的实现在AbstractApplicationConText类中:

    /**
         * Publish the given event to all listeners.
         * <p>Note: Listeners get initialized after the MessageSource, to be able
         * to access it within listener implementations. Thus, MessageSource
         * implementations cannot publish events.
         * @param event the event to publish (may be application-specific or a
         * standard framework event)
         */
        @Override
        public void publishEvent(ApplicationEvent event) {
            Assert.notNull(event, "Event must not be null");
            if (logger.isTraceEnabled()) {
                logger.trace("Publishing event in " + getDisplayName() + ": " + event);
            }
            getApplicationEventMulticaster().multicastEvent(event);
            if (this.parent != null) {
                this.parent.publishEvent(event);
            }
        }
    
        /**
         * Return the internal ApplicationEventMulticaster used by the context.
         * @return the internal ApplicationEventMulticaster (never {@code null})
         * @throws IllegalStateException if the context has not been initialized yet
         */
        ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
            if (this.applicationEventMulticaster == null) {
                throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
                        "call 'refresh' before multicasting events via the context: " + this);
            }
            return this.applicationEventMulticaster;
        }

    其中

    ApplicationEventMulticaster的初始化 来自于AbstractApplicationConText的refresh()方法
    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // 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);
    
                try {
                    // 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();
                }
    
                catch (BeansException ex) {
                    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;
                }
            }
        }

    调用初始化方法:

    /**
         * Initialize the ApplicationEventMulticaster.
         * Uses SimpleApplicationEventMulticaster if none defined in the context.
         * @see org.springframework.context.event.SimpleApplicationEventMulticaster
         */
        protected void initApplicationEventMulticaster() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
                this.applicationEventMulticaster =
                        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
                if (logger.isDebugEnabled()) {
                    logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
                }
            }
            else {
                this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                            APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                            "': using default [" + this.applicationEventMulticaster + "]");
                }
            }
        }

    发布事件的默认实现SimpleApplicationEventMulticaster:

        @Override
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public void multicastEvent(final ApplicationEvent event) {
            for (final ApplicationListener listener : getApplicationListeners(event)) {
                Executor executor = getTaskExecutor();
                if (executor != null) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            listener.onApplicationEvent(event);
                        }
                    });
                }
                else {
                    listener.onApplicationEvent(event);
                }
            }
        }

    1.5.2 ApplicationListener事件监听

    ApplicationListener application事件监听器的基础接口,继承于java.util.EventListener,基于监听器涉及模式。

    AbstractApplicationContext注册ApplicationListener监听器

        /**
         * Add beans that implement ApplicationListener as listeners.
         * Doesn't affect other listeners, which can be added without being beans.
         */
        protected void registerListeners() {
            // Register statically specified listeners first.
            for (ApplicationListener<?> listener : getApplicationListeners()) {
                getApplicationEventMulticaster().addApplicationListener(listener);
            }
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let post-processors apply to them!
            String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
            for (String lisName : listenerBeanNames) {
                getApplicationEventMulticaster().addApplicationListenerBean(lisName);
            }
        }

    1.6 ResourcePatternResolver

    ResourcePatternResolver是一个解析位置模式(例如ant-样式的路径模式)到Resource对象的策略接口。

    它扩展了org.springframework.core.io.ResourceLoader接口。内部传递的ResourceLoader(例如,在一个运行的context中,org.springframework.context.ApplicationContext的传递通过org.springframework.context.ResourceLoaderAware来实现)可以检查它的实现是否实现了该扩展接口。

    PathMatchingResourcePatternResolver是一个独立的实现,可以在Applicationcontext外部使用,也可以由ResourceArrayPropertyEditor使用来给Resource 数组 bean的属性。

     ResourceArrayPropertyEditor是一个Resource数组编辑器,自动将位置模式例如file:C:/my*.txt或者classpath*:myfile.txt转换成Resource数组属性。同样,也可以将一组位置模式转换成合并的Resource数组。一个路径也许包含了${...}占位符,可以解析成org.springframework.core.env.Environment属性:如${user.dir}.不能解析的占位符默认将忽略。

    它代理了一个ResourcePatternResolver,默认使用PathMatchingResourcePatternResolver。

    1.7 Lifecycle

    Lifecycle定义了start/stop方法里对生命周期进行管理。典型应用是控制异步处理。

    可以由组件(典型的在spring beanFactory定义的spring bean)或者容器(典型的是spring ApplicationContext)。容器将会传播start/stop信号到它应用的所有组件上。

    Lifecycle还可以通过JMX来直接触发或者管理各种操作。在后一种应用中,org.springframework.jmx.export.MBeanExporter和org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler一起定义活跃的可控组件对Lifecycle的可见性。

    注意,Lifecycle接口仅支持最高级别的单实例bean,在别的地方,Lifecycle接口将不会被检查到而因此被忽略。同样,注意Lifeclycle的扩展接口SmartLifecycle提供更灵巧的集成容器的启动和关闭阶段。

    LifecycleProcessor是一个处理ApplicationContext中bean的生命周期的策略接口。扩展了Lifecycle接口。

    默认实现是DefaultLifecycleProcessor

    SmartLifecycle是Lifecycle的扩展接口,使用对象是需要在ApplicationContext 刷新或者关闭时一些对象需要有序进行。isAutoStartup()方法返回值表示一个对象是否应该在context刷新时启动。stop(Runnable)方法的回调在异步关闭进程时非常有用。在整个ApplicationContext关闭时,为避免不必要的延迟,该接口的实现必须在关闭完成时触发回调的run方法。

    这个接口扩展了Phased接口,并且getPhase()方法返回值表明了在组件的生命周期里应该开始或者停止的阶段。进程启动时拥有最低的阶段,结束时拥有最好的阶段值(Integer.MIN_VALUE是最低的可能值,Integer.MAX_VALUE是最高的可能值)。进程关闭时则正好相反。具有相同值的组件将会判断为处于同一阶段。

    例如:如果依赖于组件A的组件B已经启动,那么组件A应该拥有比组件B更低的阶段值。在关闭进程中,组件B应该比组件A更先关闭。Context内的Lifecycle如果没有实现SmartLifecycle将会认为其阶段值为0.这种情况下,具有负的阶段值的SmartLifecycle的实现将比这些Lifecycle组件先启动,或者具有正的阶段值的SmartLifecycle的实现比这些Lifecycle晚启动。

    注意:因SmartLifecycle支持auto-startup,在ApplicationContext启动的任何情况下,一个SmartLifecycle bean实例将会被初始化。所以,bean定义中的lazy-init属性将无法对SmartLifecycle bean产生影响。

    Phased 定义了进程所处的阶段

    /**
     * Interface for objects that may participate in a phased
     * process such as lifecycle management.*/
    public interface Phased {
    
        /**
         * Return the phase value of this object.
         */
        int getPhase();
    
    }

    小结:

      本文围绕ApplicationContext具有的功能,对spring-context的context模块进行了解释,只要抓住ApplicationContext的核心就行。

    下面列出了BeanFactory提供的功能和ApplicationContext提供的功能(包括其实现)。

    特性                                                   BeanFactory   ApplicationContext 
    Bean 实例化/装配                                Yes                 Yes

    自动 BeanPostProcessor 注册                No                  Yes

    自动 BeanFactoryPostProcessor 注册      No                  Yes

    便捷的 MessageSource 访问( i18n)         No                  Yes

    ApplicationEvent 发送                         No                  Yes

     加载Resource             No                 Yes         

  • 相关阅读:
    三: 视图容器。
    (微信小程序)一 : 初识微信小程序
    Centos 从零开始 (四)
    Centos 从零开始 (三)
    Centos 从零开始 (二)
    Centos 从零开始 (一)
    9、下拉刷新 与 上拉加载
    8、导航:Nav
    C#异步编程 Task await的理解
    WPF 获取主线程
  • 原文地址:https://www.cnblogs.com/davidwang456/p/5717972.html
Copyright © 2011-2022 走看看