spring源码之旅(2)_applicationcontext启动流程分析

spring源码之旅(2)_applicationcontext启动流程分析

一、           一个简单的应用

此次分析从spring的一个入门级的应用作为入口,下面是应用的代码:

TestAction(TestAction.java)

package xqq.ioc.listen1;

public static void main(String[] args)

    {

       ApplicationContext ctx=new ClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);

       Action myAction=(Action)ctx.getBean(“myAction”);

       System.out.println(myAction.execute(“Qiang Qiang”));

    }

Action接口代码:(Action.java)

package xqq.ioc.listen1;

public interface Action {

    String execute(String str);

}

UpperAction类代码:(UpperAction.java)

package xqq.ioc.listen1;

public class UpperAction implements Action {

    String message;

    public String execute(String str) {

       // TODO Auto-generated method stub

       return (getMessage()+str).toUpperCase();

    }

    public String getMessage() {

       return message;

    }

    public void setMessage(String message) {

       this.message = message;

    }

}

Spring配置文件(listen1_beans.xml)

<?xml version=“1.0” encoding=“UTF-8”?>

<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-2.5.xsd”>

    <bean id=“myAction” class=“xqq.ioc.listen1.UpperAction”>

       <property name=“message”>

           <value>Hello</value>

       </property>

    </bean>

</beans>

 

 

二、           构造方法跟踪

1.         程序进入main方法后,第一步就是通过加载一个spring xml配置文件的路径创建applicationContext

ApplicationContext ctx=new ClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);

2.      进入ClassPathXmlApplicationContext的构造方法中

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {

       this(new String[] {configLocation}, true, null);

    }

3.      由上面的代码可以看见,代码进入了一个重载的构造方法

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

           throws BeansException {

       super(parent);

       this.configLocations = StringUtils.trimArrayElements(configLocations);

       if (refresh) {

           refresh();

       }

    }

4.      由上面代码可见首先调用超类的构造方法,经过代码跟踪,超类构造方法的调用直至AbstractApplicationContext类的构造方法止

public AbstractApplicationContext(ApplicationContext parent) {

       this.parent = parent;

       this.resourcePatternResolver = getResourcePatternResolver();

    }

    AbstractApplicationContext构造方法中设置了parent,并且设置了resourcePatternResolver属性,查看getResourcePatternResolver()方法的源码:

protected ResourcePatternResolver getResourcePatternResolver() {

       return new PathMatchingResourcePatternResolver(this);

    }

由上面可见在AbstractApplicationContext类中默认创建了一个PathMatchingResourcePatternResolver对象来进行资源路径的解析

 

 

三、           refresh()方法刷新流程

3中调用完超类的构造方法后,最重要的就是调用refresh()方法了,refresh()方法内部实现了整个applicationContext的启动流程

Refresh()方法是在AbstractApplicationContext类内部实现的,在3中调用的其实是超类的refresh()方法

/**

     * 刷新,spring ApplicationContext初始化并工作的核心方法

     */

    public void refresh() throws BeansException, IllegalStateException {

       synchronized (this.startupShutdownMonitor) {

           //准备刷新,设置启动时间和active属性的值

           prepareRefresh();

           //在此方法内部调用抽象方法refreshBeanFactory(),并返回刷新后的beanFactory实例

           ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

           //设置beanFactory的标准特性,包括类加载器,ResourceEditorRegistrar,beanFactory增加ApplicationContextAwareProcessorbeanPost后置处理器,并调用ignoreDependencyInterface()方法设置自动装配时被忽略的类型

           prepareBeanFactory(beanFactory);

           try {

              //模板方法,供子类进行覆盖实现,本类默认实现为空          postProcessBeanFactory(beanFactory);

              //调用本类中的BeanFactoryPostProcessor集合和beanFactory中的所有后置处理器对beanFactory进行处理,如果beanFactory中的后置处理器有顺序,则按照顺序进行处理

              invokeBeanFactoryPostProcessors(beanFactory);

              //按顺序将beanFactory中的bean后置处理器全都加入至beanFactorybean后置处理器列表中

              registerBeanPostProcessors(beanFactory);

              //初始化message source,并设置其父message source

              initMessageSource();

              //初始化ApplicationEvent消息广播器

              initApplicationEventMulticaster();

              //模板方法,供子类进行覆盖实现,本类默认实现为空

              onRefresh();

              //将本类的ApplicationListener和配置beans中的ApplicationListener添加至本类的消息广播器上

              registerListeners();

              //beanFactory实例化非延迟的单例bean

              beanFactory.preInstantiateSingletons();

              //完成刷新,并发布ContextRefreshedEvent事件

              finishRefresh();

           }

           catch (BeansException ex) {

              // Destroy already created singletons to avoid dangling resources.

              beanFactory.destroySingletons();

              // Reset ‘active’ flag.

              cancelRefresh(ex);

              // Propagate exception to caller.

              throw ex;

           }

       }

    }

通过阅读refresh()方法代码,可以非常清楚的了解spring applicationcontext启动时的整个初始化流程:

准备刷新(记录启动时间,设置active属性为true——-à获取刷新后的beanFactory——-à

设置beanFacotry类加载器、默认属性编辑器、默认beanPost后置处理器——-à获取beanFactory中的BeanFactoryPostProcessor类型的对象,并让其对beanFactory进行后置处理——-à将配置中的beanPostProcessor类型的对象加入至beanFactory——-à初始化messageSource(如有配置,则获取配置文件中的messageSource bean对象,如没有,则创建DelegatingMessageSource让其将对messageSource的请求代理给父容器的messageSource对象处理) ——-à初始化ApplicationEvent事件广播器(如有配置,则使用配置文件中所配置的消息广播器,否则默认使用SimpleApplicationEventMulticaster作为消息广播器) ——-à调用模板方法onRefresh()——-à注册配置文件中所配置的消息监听器—–àbeanFactory实例化非延迟的单例bean—–à完成刷新,并发布ContextRefreshedEvent事件

 

四、           ApplicationContext内部beanFactory的创建

整个刷新过程中,创建了新的beanFactory,原有的旧beanFactory将被丢弃,obtainFreshBeanFactory()方法内部调用的refreshBeanFactory()方法实现了这种功能。refreshBeanFactory()具体由子类AbstractRefreshableApplicationContext进行实现,先将旧的beanFactory中的所有单例全都销毁,然后创建一个新的beanFactory,加载beanDefinitions,并将新的beanFactory赋给本类的beanFactory实例。

ConfigurableListableBeanFactory oldBeanFactory = null;

       synchronized (this.beanFactoryMonitor) {

           oldBeanFactory = this.beanFactory;

       }

       if (oldBeanFactory != null) {

           //销毁bean工厂中的所有单例

           oldBeanFactory.destroySingletons();

           synchronized (this.beanFactoryMonitor) {

              this.beanFactory = null;

           }

       }

 

       // Initialize fresh bean factory.

       try {

           //创建新的beanFactory

           DefaultListableBeanFactory beanFactory = createBeanFactory();

           //模板方法,供子类覆盖实现,为beanFactory提供客户端自定义的操作

           customizeBeanFactory(beanFactory);

           //beanFactory中加载bean定义

           loadBeanDefinitions(beanFactory);

           //将创建的beanFactory设置为本类的beanFactory实例

           synchronized (this.beanFactoryMonitor) {

              this.beanFactory = beanFactory;

           }

       }…………

AbstractRefreshableApplicationContext类的createBeanFactory()方法中实现了为ApplicationContext创建内部beanFactory的功能,此内部beanFactory保存了根据配置文件解析而来的各个beanBeanDefinition实例,因此ApplicationContext创建、查找bean以及对bean进行操作等功能的实现都是通过其内部beanFactory实现的。下面是此方法的代码:

protected DefaultListableBeanFactory createBeanFactory() {

       return new DefaultListableBeanFactory(getInternalParentBeanFactory());

    }

由以上代码可以看见,以applicationcontext父亲的内部beanFactory作为构造参数,创建了DefaultListableBeanFactory对象作为applicationcontext的内部beanFactory

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/XQQ8765/article/details/5409489
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞