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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

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

一、一个简单的应用

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

TestAction类(TestAction.java)

packagexqq.ioc.listen1;publicstaticvoidmain(String[]args)   {      ApplicationContextctx=newClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);      ActionmyAction=(Action)ctx.getBean(“myAction”);      System.out.println(myAction.execute(“QiangQiang”));   }
packagexqq.ioc.listen1;publicstaticvoidmain(String[]args)   {      ApplicationContextctx=newClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);      ActionmyAction=(Action)ctx.getBean(“myAction”);      System.out.println(myAction.execute(“QiangQiang”));   }

Action接口代码:(Action.java)

packagexqq.ioc.listen1;publicinterfaceAction{   Stringexecute(Stringstr);}
packagexqq.ioc.listen1;publicinterfaceAction{   Stringexecute(Stringstr);}

UpperAction类代码:(UpperAction.java)

packagexqq.ioc.listen1;publicclassUpperActionimplementsAction{   Stringmessage;   publicStringexecute(Stringstr){      //TODOAuto-generatedmethodstub      return(getMessage()+str).toUpperCase();   }   publicStringgetMessage(){      returnmessage;   }   publicvoidsetMessage(Stringmessage){      this.message=message;   }}
packagexqq.ioc.listen1;publicclassUpperActionimplementsAction{   Stringmessage;   publicStringexecute(Stringstr){      //TODOAuto-generatedmethodstub      return(getMessage()+str).toUpperCase();   }   publicStringgetMessage(){      returnmessage;   }   publicvoidsetMessage(Stringmessage){      this.message=message;   }}

Spring配置文件(listen1_beans.xml):

<?xmlversion=“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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd”>   <beanid=“myAction”class=“xqq.ioc.listen1.UpperAction”>      <propertyname=“message”>          <value>Hello</value>      </property>   </bean></beans>;
<?xmlversion=“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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd”>   <beanid=“myAction”class=“xqq.ioc.listen1.UpperAction”>      <propertyname=“message”>          <value>Hello</value>      </property>   </bean></beans>;

二、构造方法跟踪

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

ApplicationContextctx=newClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);
ApplicationContextctx=newClassPathXmlApplicationContext(“xqq//ioc//listen1//listen1_beans.xml”);

2.进入ClassPathXmlApplicationContext的构造方法中

publicClassPathXmlApplicationContext(StringconfigLocation)throwsBeansException{      this(newString[]{configLocation},true,null);   }
publicClassPathXmlApplicationContext(StringconfigLocation)throwsBeansException{      this(newString[]{configLocation},true,null);   }

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

publicClassPathXmlApplicationContext(String[]configLocations,booleanrefresh,ApplicationContextparent)          throwsBeansException{      super(parent);      this.configLocations=StringUtils.trimArrayElements(configLocations);      if(refresh){          refresh();      }   }
publicClassPathXmlApplicationContext(String[]configLocations,booleanrefresh,ApplicationContextparent)          throwsBeansException{      super(parent);      this.configLocations=StringUtils.trimArrayElements(configLocations);      if(refresh){          refresh();      }   }

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

publicAbstractApplicationContext(ApplicationContextparent){      this.parent=parent;      this.resourcePatternResolver=getResourcePatternResolver();   }
publicAbstractApplicationContext(ApplicationContextparent){      this.parent=parent;      this.resourcePatternResolver=getResourcePatternResolver();   }

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

protectedResourcePatternResolvergetResourcePatternResolver(){      returnnewPathMatchingResourcePatternResolver(this);   }
protectedResourcePatternResolvergetResourcePatternResolver(){      returnnewPathMatchingResourcePatternResolver(this);   }

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

三、refresh()方法刷新流程

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

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

/*    刷新,springApplicationContext初始化并工作的核心方法    */   publicvoidrefresh()throwsBeansException,IllegalStateException{      synchronized(this.startupShutdownMonitor){          //准备刷新,设置启动时间和active属性的值          prepareRefresh();          //在此方法内部调用抽象方法refreshBeanFactory(),并返回刷新后的beanFactory实例          ConfigurableListableBeanFactorybeanFactory=obtainFreshBeanFactory();          //设置beanFactory的标准特性,包括类加载器,ResourceEditorRegistrar,为beanFactory增加ApplicationContextAwareProcessor的beanPost后置处理器,并调用ignoreDependencyInterface()方法设置自动装配时被忽略的类型          prepareBeanFactory(beanFactory);          try{             //模板方法,供子类进行覆盖实现,本类默认实现为空        postProcessBeanFactory(beanFactory);             //调用本类中的BeanFactoryPostProcessor集合和beanFactory中的所有后置处理器对beanFactory进行处理,如果beanFactory中的后置处理器有顺序,则按照顺序进行处理             invokeBeanFactoryPostProcessors(beanFactory);             //按顺序将beanFactory中的bean后置处理器全都加入至beanFactory的bean后置处理器列表中             registerBeanPostProcessors(beanFactory);             //初始化messagesource,并设置其父messagesource             initMessageSource();             //初始化ApplicationEvent消息广播器             initApplicationEventMulticaster();             //模板方法,供子类进行覆盖实现,本类默认实现为空             onRefresh();             //将本类的ApplicationListener和配置beans中的ApplicationListener添加至本类的消息广播器上             registerListeners();             //beanFactory实例化非延迟的单例bean             beanFactory.preInstantiateSingletons();             //完成刷新,并发布ContextRefreshedEvent事件             finishRefresh();          }          catch(BeansExceptionex){             //Destroyalreadycreatedsingletonstoavoiddanglingresources.             beanFactory.destroySingletons();             //Reset‘active’flag.             cancelRefresh(ex);             //Propagateexceptiontocaller.             throwex;          }      }   }

通过阅读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实例。

ConfigurableListableBeanFactoryoldBeanFactory=null;      synchronized(this.beanFactoryMonitor){          oldBeanFactory=this.beanFactory;      }      if(oldBeanFactory!=null){          //销毁bean工厂中的所有单例          oldBeanFactory.destroySingletons();          synchronized(this.beanFactoryMonitor){             this.beanFactory=null;          }      }       //Initializefreshbeanfactory.      try{          //创建新的beanFactory          DefaultListableBeanFactorybeanFactory=createBeanFactory();          //模板方法,供子类覆盖实现,为beanFactory提供客户端自定义的操作          customizeBeanFactory(beanFactory);          //从beanFactory中加载bean定义          loadBeanDefinitions(beanFactory);          //将创建的beanFactory设置为本类的beanFactory实例          synchronized(this.beanFactoryMonitor){             this.beanFactory=beanFactory;          }      }…………
ConfigurableListableBeanFactoryoldBeanFactory=null;      synchronized(this.beanFactoryMonitor){          oldBeanFactory=this.beanFactory;      }      if(oldBeanFactory!=null){          //销毁bean工厂中的所有单例          oldBeanFactory.destroySingletons();          synchronized(this.beanFactoryMonitor){             this.beanFactory=null;          }      }       //Initializefreshbeanfactory.      try{          //创建新的beanFactory          DefaultListableBeanFactorybeanFactory=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**实现的。下面是此方法的代码:

protectedDefaultListableBeanFactorycreateBeanFactory(){      returnnewDefaultListableBeanFactory(getInternalParentBeanFactory());   }
protectedDefaultListableBeanFactorycreateBeanFactory(){      returnnewDefaultListableBeanFactory(getInternalParentBeanFactory());   }

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


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring源码之旅(2)_applicationcontext启动流程分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏