这篇文章分析spring web启动时ioc源码研究
研究IOC首先创建一个简单的web项目,在web.xml中我们都会加上这么一句
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>这代表了web容器启动的时候会首先进入ContextLoaderListener这个类,并且之后会去加载classpath下的applicationContext.xml文件。那么重点就在ContextLoaderListener上,点开源码:
/**
* Initialize the root web application context. */
@Override public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
} /**
* Close the root web application context. */
@Override public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}里面主要为ServletContextListener接口的两个实现方法。web容器会首先调用contextInitialized方法,传入tomcat封装的容器资源,之后调用父类的初始化容器方法。
/*** The root WebApplicationContext instance that this loader manages.*/private WebApplicationContext context;public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
...........省略// Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown.
if (this.context == null) { this.context = createWebApplicationContext(servletContext);
} if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> // determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
......省略 return this.context;
}这个方法里主要步骤createWebApplicationContext方法用来创建XmlWebApplicationContext这个root根容器,这个容器就是取自servletContextEvent。
loadParentContext方法用来加载父容器。主要方法configureAndRefreshWebApplicationContext用来配置和刷新root容器,在方法内最主要的就是refresh方法,里面实现了最主要的功能。
@Override 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;
}
}
}prepareRefresh方法用来准备之后需要用到的环境。
obtainFreshBeanFactory方法获取beanFactory
@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);
}
}实际返回的beanFactory为其实现类DefaultListableBeanFactory,实例化该类用来为之后装载xml中实例化的类。
loadBeanDefinitions为重要的方法,用来真正的加载类了,之前的都是准备工作。
以上就是分析spring web启动时IOC源码的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号