同前一篇一样,本文的分析还是基于Spring的web应用。
从web.xml里面配置的ContextLoaderListener开始。
ContextLoaderListener引用了一个ContextLoader(可以是它自身);
ContextLoader引用了一个WebApplicationContext;
WebApplicationContext本身是一个beanFactory. 如果不指定,默认的实现类是
XmlWebApplicationContext--这个类的实例是一个beanFactory,同时也引用了一个BeanFactory. (Decorator Pattern);
其中bean的加载是由AbstractApplicationContext的refresh方法调用的。
为了稍微形象的描述,我把refresh方法的调用层次贴了出来。
在ContextLoader的createWebApplicationContext里面,新建了一个ApplicationContext,并且刷新这个context.
新建的代码:
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
刷新的代码:
wac.refresh();
refresh方法的实现是在XmlWebApplicationContext的父类AbstractApplicationContext里面实现的。
refresh里面完成了WebApplicationContext里面的beanfactory的初始化和bean载入,beanfactorypostprocessor的调用,beanpostprocessor的注册,ApplicationEvent的监听和注册,non-lazy-init的bean的初始化。
换言之,已经把该准备的都准备好了,只需要有请求来获取bean,就根据情况或返回已经初始化的bean或进行bean的Instantiation 和 Initialization。
源码如下:
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) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
注意其中的obtainFreshBeanFactory方法,beanFactory的初始化是由这个方法调用的。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
继续追踪refreshBeanFactory方法,发现是在AbstractRefreshableApplicationContext中实现的。
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
由此可见,正是在refreshBeanFactory中,新建了一个DefaultListableBeanFactory并且载入了所有BeanDefinition.(载入过程在后续的篇章中继续分析)。
OK.现在脉络清楚了。我们知道了contextLoader在哪里获取了WebApplicationContext,知道了WebApplicationContext在哪里获取了beanFactory,知道了beanFactory在哪里创建和载入bean.
后面需要关注的就是bean的载入和初始话过程了。具体细节在后续的文章里面分析。
分享到:
相关推荐
Spring 源码分析 Spring 框架是 Java 语言中最流行的开源框架之一,它提供了一个强大且灵活的基础设施来构建企业级应用程序。在 Spring 框架中,IOC 容器扮演着核心角色,本文将深入分析 Spring 源码,了解 IOC ...
NULL 博文链接:https://ylxy3058.iteye.com/blog/2223489
Spring源代码分析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器...
NULL 博文链接:https://ylxy3058.iteye.com/blog/2224244
NULL 博文链接:https://ylxy3058.iteye.com/blog/2224140
NULL 博文链接:https://ylxy3058.iteye.com/blog/2223687
Spring Bean 加载顺序 实验小例子
spring源码分析(一)
spring源码分析,百度云视频。链接如果失效了,请私聊我。
spring源码分析专题,源码分析视频,对spring的源码进行分析
spring 重新动态加载数据库或xml中的bean,可以不用重启tomcat
springBean加载过程源码解析文档,附有代码类名和行数
Spring源码分析_Spring_IOC
Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class文件,动态实现spring bean 的动态加载,并通过UrlClassLoader完成jar和class文件的加载。可以实现jar的热替换。spring的bean动态加载则需要对...
Spring源码分析 对了解spring很好的文档
该项目展示spring配置文件的那些bean的加载顺序
spring boot整合JPA——demo
深入分析 Spring 源码(第一阶段),设计模式
只需要把需要注册进容器的bean声明为@Component即可,spring会自动扫描到这个Bean完成初始化并加载到spring上下文容器。 而当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成...