ClassPathXmlApplicationContext的启动

Spring将ApplicationContext启动的全过程,refresh函数中包含了几乎ApplicationContext中提供的全部功能,而且此函数中逻辑非常清晰明了,很容易分析对应的层次及逻辑。:
ClassPathXmlApplicationContext相比于XmlBeanFactory是在DefaultListableBeanFactory基础上多了一系列的扩展。

ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //准备刷新的上下文环境,例如对系统属性或者环境变量进行准备及验证。
            prepareRefresh();
            //初始化BeanFactory,并进行XML文件读取,
            //这一步之后,ClassPathXmlApplicationContext实际上就已经包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基础操作了。
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            //对BeanFactory进行各种功能填充,@Qualifier与@Autowired这两个注解正是在这一步骤中增加的支持。
            //设置@Autowired和 @Qualifier注解解析器QualifierAnnotationAutowireCandidateResolver
       prepareBeanFactory(beanFactory);
            try {
                //子类覆盖方法做额外的处理,提供了一个空的函数实现postProcessBeanFactory来方便程序员在业务上做进一步扩展。
                postProcessBeanFactory(beanFactory);
                //激活各种BeanFactory处理器
                invokeBeanFactoryPostProcessors(beanFactory);
                //注册拦截Bean创建的Bean处理器,这里只是注册,真正的调用是在getBean时候
                registerBeanPostProcessors(beanFactory);
                //为上下文初始化Message源,即不同语言的消息体进行国际化处理
                initMessageSource();
                //初始化应用消息广播器,并放入“applicationEventMulticaster”bean中
                initApplicationEventMulticaster();
                //留给子类来初始化其它的Bean
                onRefresh();
                //在所有注册的bean中查找Listener bean,注册到消息广播器中
                registerListeners();
                //初始化剩下的单实例(非惰性的)
                finishBeanFactoryInitialization(beanFactory);
                //完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
                finishRefresh();
            }
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

环境准备

protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }
        //留给子类覆盖
        initPropertySources();
        //验证需要的属性文件是否都已经放入环境中
        getEnvironment().validateRequiredProperties();
     //to be published once the multicaster is available...
        this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
    }

假如现在有这样一个需求,工程在运行过程中用到的某个设置(例如classpath)是从系统环境变量中取得的,而如果用户没有在系统环境变量中配置这个参数,那么工程可能不会工作。这一要求可能会有各种各样的解决办法,当然,在Spring中可以这样做,你可以直接修改Spring的源码,例如修改ClassPathXmlApplicationContext。当然,最好的办法还是对源码进行扩展,我们可以自定义类:

[
复制代码

](javascript:void(0); "复制代码")

public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{ 
  public MyClassPathXmlApplicationContext(String... configLocations ){       
     super(configLocations);
  } 
protected void initPropertySources() { //添加验证要求
        getEnvironment().setRequiredProperties("classpath");
    }
}

我们自定义了继承自ClassPathXmlApplicationContext的MyClassPathXmlApplicationContext,并重写了initPropertySources方法,在方法中添加了我们的个性化需求,那么在验证的时候也就是程序走到getEnvironment().validateRequiredProperties()代码的时候,如果系统并没有检测到对应classpath的环境变量,那么将抛出异常。

加载BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //初始化BeanFactory,并进行XML文件读取,并将得到的BeanFacotry记录在当前实体的属性中
        refreshBeanFactory();
        //返回当前实体的beanFactory属性
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

    AbstractRefreshableApplicationContext.java
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //在介绍BeanFactory的时候,声明方式为:BeanFactory bf = new XmlBeanFactory("beanFactoryTest.xml"),
       //其中的XmlBeanFactory继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader类型的reader属性,
       //也就是说DefaultListableBean Factory是容器的基础。必须首先要实例化,那么在这里就是实例化DefaultListableBeanFactory的步骤。
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //为了序列化指定id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
            beanFactory.setSerializationId(getId());
            //定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖以及
            customizeBeanFactory(beanFactory);
            //初始化DodumentReader,并进行XML文件读取及解析
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                //使用全局变量记录BeanFactory类实例。
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }


    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        //如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,
        //此属性的含义:是否允许覆盖同名称的不同定义的对象
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        //如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,
        //此属性的含义:是否允许bean之间存在循环依赖
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }


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

        //对beanDefinitionReader进行环境变量的设置
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        //对BeanDefinitionReader进行设置,可以覆盖
        initBeanDefinitionReader(beanDefinitionReader);
        //使用XmlBeanDefinitionReader的loadBeanDefinitions方法进行配置文件的加载及注册
        loadBeanDefinitions(beanDefinitionReader);
    }

功能扩展

 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //设置beanFactory的classLoader为当前context的classLoader
        beanFactory.setBeanClassLoader(getClassLoader());
        //设置beanFactory的表达式语言处理器,Spring3增加了表达式语言的支持,SPEL语言。
        //默认可以使用#{bean.xxx}的形式来调用相关属性值。
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        //为beanFactory增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        //添加BeanPostProcessor
        //ApplicationContextAwareProcessor实现了BeanPostProcessor接口,在bean实例化的时候会被调用
        //postProcessBeforeInitialization方法中调用了invokeAwareInterfaces。从invokeAwareInterfaces方法中,
     //我们可以看出来,实现这些Aware接口的bean在被初始化之后,可以取得一些对应的资源。
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        //Spring将ApplicationContextAwareProcessor注册后,在invokeAwareInterfaces方法中间调用的Aware类已经不是普通的bean了,
        //如ResourceLoaderAware,ApplicationEventPublisherAware等,需要在Spring做bean的依赖注入的时候忽略它们。
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

        //设置了几个自动装配的特殊规则  
        //当注册了依赖解析后,例如当注册了对BeanFactory.class的解析后,当bean的属性注入的时候,
     //一旦检测到属性为BeanFactory类型便会将beanFactory的实例注入进去。
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        //增加对AspectJ的支持
        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()));
        }

        //将相关环境变量及属性注册以单例模式注册,environment,systemProperties,systemEnvironment
        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());
        }
    }


ResourceEditorRegistrar的registerCustomEditors的调用时机,就是AbstractBeanFactory类中的initBeanWrapper方法,这是在bean初始化时使用的一个方法,主要是在将BeanDefinition转换为BeanWrapper后用于对属性的填充。在bean的初始化后会调用ResourceEditorRegistrar的registerCustomEditors方法进行批量的通用属性编辑器注册。注册后,在属性填充的环节便可以直接让Spring使用这些编辑器进行属性的解析了。
Spring中用于封装bean的是BeanWrapper类型,而它又间接继承了PropertyEditorRegistry类型,也就是我们之前反复看到的方法参数PropertyEditorRegistry,其实大部分情况下都是BeanWrapper,对于BeanWrapper在Spring中的默认实现是BeanWrapperImpl,而BeanWrapperImpl除了实现BeanWrapper接口外还继承了PropertyEditorRegistrySupport,在PropertyEditorRegistrySupport中有这样一个方法:createDefaultEditors,基本的属性编辑器就在此处被注册。
BeanFactory的后处理
BeanFactoryPostProcessor接口跟BeanPostProcessor类似,可以对bean的定义(配置元数据)进行处理。也就是说,Spring IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其他的bean之前读取配置元数据,并有可能修改它。如果你愿意,你可以配置多个BeanFactoryPostProcessor。你还能通过设置“order”属性来控制BeanFactoryPostProcessor的执行次序(仅当BeanFactoryPostProcessor实现了Ordered接口时你才可以设置此属性,因此在实现BeanFactoryPostProcessor时,就应当考虑实现Ordered接口)。

如果你想改变实际的bean实例(例如从配置元数据创建的对象),那么你最好使用BeanPostProcessor。同样地,BeanFactoryPostProcessor的作用域范围是容器级的。它只和你所使用的容器有关。如果你在容器中定义一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后置处理。BeanFactoryPostProcessor不会对定义在另一个容器中的bean进行后置处理,即使这两个容器都是在同一层次上。

在Spring中存在对于BeanFactoryPostProcessor的两种典型应用。

(1)比如PropertyPlaceholderConfigurer

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
   <list>
    <value>/WEB-INF/mail.properties</value>  
    <value>classpath: conf/sqlmap/jdbc.properties</value>//注意这两种value值的写法
   </list>
  </property>
   <property name="fileEncoding">
     <value>UTF-8</value>
   </property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName"value="${jdbc.driverClassName}" />
  <property name="url" value="${jdbc.url}" />
  <property name="username" value="${jdbc.username}"/>
  <property name="password"value="${jdbc.password}" />
</bean>

jdbc.properties文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost/mysqldb?useUnicode=true&amp;characterEncoding=UTF-8&amp;
jdbc.username=root
jdbc.password=123456

PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是BeanFactoryPostProcessor接口的一个实现。PropertyPlaceholderConfigurer可以将上下文(配置文件)中的属性值放在另一个单独的标准java Properties文件中去。在XML文件中用${key}替换指定的properties文件中的值。这样的话,只需要对properties文件进行修改,而不用对xml配置文件进行修改。
在Spring中,使用PropertyPlaceholderConfigurer可以在XML配置文件中加入外部属性文件,当然也可以指定外部文件的编码,PropertyPlaceholderConfigurer如果在指定的Properties文件中找不到你想使用的属性,它还会在Java的System类属性中查找。可以通过System.setProperty(key, value)或者java中通过-Dnamevalue来给Spring配置文件传递参数。

查看层级结构可以看出PropertyPlaceholderConfigurer这个类间接继承了BeanFactoryPostProcessor接口。这是一个很特别的接口,当Spring加载任何实现了这个接口的bean的配置时,都会在bean工厂载入所有bean的配置之后执行postProcessBeanFactory方法。在PropertyResourceConfigurer类中实现了postProcessBeanFactory方法,在方法中先后调用了mergeProperties、convertProperties、processProperties这3个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知BeanFactory。正是通过实现BeanFactoryPostProcessor接口,BeanFactory会在实例化任何bean之前获得配置信息,从而能够正确解析bean描述文件中的变量引用。

(2)使用自定义BeanFactoryPostProcessor

实现一个BeanFactoryPostProcessor,实现一个简单的回调处理器,它能去除潜在的"流氓"属性值,例如bean定义中留下bollocks这样的字眼。

<bean id="bfpp" class="com.spring.ch04.ObscenityRemovingBeanFactoryPostProcessor">  
    <property name="obscenties">  
        <set>  
            <value>bollocks</value>  
            <value>winky</value>  
            <value>bum</value>  
            <value>Microsoft</value>  
        </set>  
    </property>  
  
</bean>  
<bean id="simpleBean" class="com.spring.ch04.SimplePostProcessor">  
    <property name="connectionString" value="bollocks"/>  
    <property name="password" value="imaginecup"/>  
    <property name="username" value="Microsoft"/>  
</bean>  

java代码

public class ObscenityRemovingBeanFactoryPostProcessor implements  
        BeanFactoryPostProcessor {  
    private Set<String> obscenties;  
    public ObscenityRemovingBeanFactoryPostProcessor(){  
        this.obscenties=new HashSet<String>();  
    }  
    public void postProcessBeanFactory(  
            ConfigurableListableBeanFactory beanFactory) throws BeansException {  
        String[] beanNames=beanFactory.getBeanDefinitionNames();  
        for(String beanName:beanNames){  
            BeanDefinition bd=beanFactory.getBeanDefinition(beanName);  
            StringValueResolver valueResover=new StringValueResolver() {  
                public String resolveStringValue(String strVal) {  
                    if(isObscene(strVal)) return "*****";  
                    return strVal;  
                }  
            };  
            BeanDefinitionVisitor visitor=new BeanDefinitionVisitor(valueResover);  
            visitor.visitBeanDefinition(bd);  
        }  
    }  
    public boolean isObscene(Object value){  
        String potentialObscenity=value.toString().toUpperCase();  
        return this.obscenties.contains(potentialObscenity);  
    }  
    public void setObscenties(Set<String> obscenties) {  
        this.obscenties.clear();  
        for(String obscenity:obscenties){  
            this.obscenties.add(obscenity.toUpperCase());  
        }  
    }  
  
}  

测试类

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
import org.springframework.beans.factory.xml.XmlBeanFactory;  
import org.springframework.core.io.ClassPathResource;  
public class PropertyConfigurerDemo {  
    public static void main(String[] args) {  
        ConfigurableListableBeanFactory bf=new XmlBeanFactory(new ClassPathResource("/META-INF/BeanFactory.xml"));  
        BeanFactoryPostProcessor bfpp=(BeanFactoryPostProcessor)bf.getBean("bfpp");  
        bfpp.postProcessBeanFactory(bf);  
        System.out.println(bf.getBean("simpleBean"));  
          
    }  
}  

SimplePostProcessor{connectionString=*****,username=*****,password=imaginecup

激活BeanFactoryPostProcessor

1)从invokeBeanFactoryPostProcessors的方法中我们看到,对于BeanFactoryPostProcessor的处理主要分两种情况进行,一个是对于BeanDefinitionRegistry类的特殊处理,另一种是对普通的BeanFactoryPostProcessor进行处理。而对于每种情况都需要考虑硬编码注入注册的后处理器以及通过配置注入的后处理器。

对于硬编码注册的后处理器的处理,主要是通过AbstractApplicationContext中的添加处理器方法addBeanFactoryPostProcessor进行添加。

public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor) {

this.beanFactoryPostProcessors.add(beanFactoryPostProcessor);

}

添加后的后处理器会存放在beanFactoryPostProcessors中,而在处理BeanFactoryPostProcessor时候会首先检测beanFactoryPostProcessors是否有数据。当然,BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,不但有BeanFactoryPostProcessor的特性,同时还有自己定义的个性化方法,也需要在此调用。所以,这里需要从beanFactoryPostProcessors中挑出BeanDefinitionRegistryPostProcessor的后处理器,并进行其postProcessBeanDefinitionRegistry方法的激活。

(2)记录后处理器主要使用了三个List完成。

registryPostProcessors:记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor类型的处理器。

regularPostProcessors:记录通过硬编码方式注册的BeanFactoryPostProcessor类型的处理器。

registryPostProcessorBeans:记录通过配置方式注册的BeanDefinitionRegistryPostProcessor类型的处理器。

(3)对以上所记录的List中的后处理器进行统一调用BeanFactoryPostProcessor的postProcessBeanFactory方法。

(4)对beanFactoryPostProcessors中非BeanDefinitionRegistryPostProcessor类型的后处理器进行统一的BeanFactoryPostProcessor的postProcessBeanFactory方法调用。

(5)普通beanFactory处理。BeanDefinitionRegistryPostProcessor只对BeanDefinitionRegistry类型的ConfigurableListableBeanFactory有效,所以如果判断所示的beanFactory并不是BeanDefinitionRegistry,那么便可以忽略BeanDefinitionRegistryPostProcessor,而直接处理BeanFactoryPostProcessor,当然获取的方式与上面的获取类似。

对于硬编码方式手动添加的后处理器是不需要做任何排序的,但是在配置文件中读取的处理器,Spring并不保证读取的顺序。所以,为了保证用户的调用顺序的要求,Spring对于后处理器的调用支持按照PriorityOrdered或者Ordered的顺序调用。

注册BeanPostProcessor

来探索下BeanPostProcessor,但是这里并不是调用,而是注册。真正的调用其实是在bean的实例化阶段进行的。这是一个很重要的步骤,也是很多功能BeanFactory不支持的重要原因。Spring中大部分功能都是通过后处理器的方式进行扩展的,这是Spring框架的一个特性,但是在BeanFactory中其实并没有实现后处理器的自动注册,所以在调用的时候如果没有进行手动注册其实是不能使用的。

对于BeanPostProcessor的处理与BeanFactoryPostProcessor的处理极为相似,但是似乎又有些不一样的地方。经过反复的对比发现,对于BeanFactoryPostProcessor的处理要区分两种情况,一种方式是通过硬编码方式的处理,另一种是通过配置文件方式的处理。那么为什么在BeanPostProcessor的处理中只考虑了配置文件的方式而不考虑硬编码的方式呢?对于BeanFactoryPostProcessor的处理,不但要实现注册功能,而且还要实现对后处理器的激活操作,所以需要载入配置中的定义,并进行激活;而对于BeanPostProcessor并不需要马上调用,再说,硬编码的方式实现的功能是将后处理器提取并调用,这里并不需要调用,当然不需要考虑硬编码的方式了,这里的功能只需要将配置文件的BeanPostProcessor提取出来并注册进入beanFactory就可以了。

对于beanFactory的注册,也不是直接注册就可以的。在Spring中支持对于BeanPostProcessor的排序,比如根据PriorityOrdered进行排序、根据Ordered进行排序或者无序,而Spring在BeanPostProcessor的激活顺序的时候也会考虑对于顺序的问题而先进行排序。

初始化消息资源

在initMessageSource中的方法主要功能是提取配置中定义的messageSource,并将其记录在Spring的容器中,也就是AbstractApplicationContext中。当然,如果用户未设置资源文件的话,Spring中也提供了默认的配置DelegatingMessageSource。

在initMessageSource中获取自定义资源文件的方式为beanFactory.getBean(MESSAGE_ SOURCE_BEAN_NAME, MessageSource.class),在这里Spring使用了硬编码的方式硬性规定了子定义资源文件必须为message,否则便会获取不到自定义资源配置。

 protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        //messageSource
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            //如果在配置中已经配置了messageSource,那么将messageSource提取并记录在this.messageSource中
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            //如果用户并没有定义配置文件,那么使用临时的DelegatingMessageSource以便于作为调用getMessage方法的返回。
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                        "': using default [" + this.messageSource + "]");
            }
        }
    }

初始化ApplicationEventMulticaster

initApplicationEventMulticaster的方式比较简单,无非考虑两种情况:

如果用户自定义了事件广播器,那么使用用户自定义的事件广播器。

如果用户没有自定义事件广播器,那么使用默认的ApplicationEventMulticaster。

protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        //applicationEventMulticaster
        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
    public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            Executor executor = getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        invokeListener(listener, event);
                    }
                });
            }
            else {
                invokeListener(listener, event);
            }
        }
    }

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
   ErrorHandler errorHandler = getErrorHandler();
   if (errorHandler != null) {
      try {
         listener.onApplicationEvent(event);
      }
      catch (Throwable err) {
         errorHandler.handleError(err);
      }
   }
   else {
      listener.onApplicationEvent(event);
   }
}

可以推断,当产生Spring事件发生的时候会默认使用SimpleApplicationEventMulticaster的multicastEvent来广播事件,遍历所有监听器,并使用监听器中的onApplicationEvent方法来进行监听器的处理。而对于每个监听器来说其实都可以获取到产生的事件,但是是否进行处理则由事件监听器来决定。

注册监听器

 protected void registerListeners() {
        //硬编码方式注册的监听器处理
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }
        //配置文件注册的监听器处理
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
        
     //广播早期的事件进行广播和事件处理
     // Publish early application events now that we finally have a multicaster...
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

初始化非延迟加载单例

finishBeanFactoryInitialization完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。

 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //conversionService的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));
        }
        // 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);
        //冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理。
        beanFactory.freezeConfiguration();
        //初始化剩下的单实例(非惰性的)
        beanFactory.preInstantiateSingletons();
    }

ConversionService的设置,之前我们提到过使用自定义类型转换器从String转换为Date的方式,使用属性编辑器,那么,在Spring中还提供了另一种转换方式:使用Converter。

ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的单例bean。通常情况下这是一件好事,因为这样在配置中的任何错误就会即刻被发现(否则的话可能要花几个小时甚至几天)。而这个实例化的过程就是在finishBeanFactoryInitialization中完成的,详细流程见Spring框架的设计理念章节。

finishRefresh

在Spring中还提供了Lifecycle接口,Lifecycle中包含start/stop方法,实现此接口后Spring保证在启动的时候调用其start方法开始生命周期,并在Spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,在启动后一直运行(如对MQ进行轮询等)。而ApplicationContext的初始化最后正是保证了这一功能的实现。

 protected void finishRefresh() {
        // Initialize lifecycle processor for this context.
        //lifecycleProcessor的bean会被注册
     initLifecycleProcessor();
        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();
        // Publish the final event.
        publishEvent(new ContextRefreshedEvent(this));
        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }

initLifecycleProcessor

当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有声明的bean周期做状态更新,而在LifecycleProcessor的使用前首先需要初始化。

onRefresh

启动所有实现了Lifecycle接口的bean。

publishEvent

当完成ApplicationContext初始化的时候,要通过Spring中的事件发布机制来发出ContextRefreshedEvent事件,以保证对应的监听器可以做进一步的逻辑处理。

原文链接:https://www.cnblogs.com/wade-luffy/p/6072460.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容