【Spring源码--IOC容器的实现】(一)Web容器的启动 - Go语言中文社区

【Spring源码--IOC容器的实现】(一)Web容器的启动


  1. public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
  2. private ContextLoader contextLoader;
  3. /**
  4. * 初始化容器
  5. * Initialize the root web application context.
  6. */
  7. public void contextInitialized(ServletContextEvent event) {
  8. //这个方法实现的本意是提供一个占位符方法createContextLoader()给子类机会创建客户化的环境加载,但是,后来这个证明不是非常有用的,已经鼓励不再使用了,事实上,子类可以通过重写本方法达到同样的目的
  9. this.contextLoader = createContextLoader();
  10. if (this.contextLoader == null) {
  11. this.contextLoader = this;
  12. }
  13. this.contextLoader.initWebApplicationContext(event.getServletContext());
  14. }
  15. /**
  16. * Create the ContextLoader to use. Can be overridden in subclasses.
  17. * @return the new ContextLoader
  18. * @deprecated in favor of simply subclassing ContextLoaderListener itself
  19. * (which extends ContextLoader, as of Spring 3.0)
  20. */
  21. @Deprecated
  22. protected ContextLoader createContextLoader() {
  23. return null;
  24. }
  25. /**
  26. * Return the ContextLoader used by this listener.
  27. * @return the current ContextLoader
  28. * @deprecated in favor of simply subclassing ContextLoaderListener itself
  29. * (which extends ContextLoader, as of Spring 3.0)
  30. */
  31. @Deprecated
  32. public ContextLoader getContextLoader() {
  33. return this.contextLoader;
  34. }
  35. /**
  36. * 销毁容器的方法
  37. * Close the root web application context.
  38. */
  39. public void contextDestroyed(ServletContextEvent event) {
  40. if (this.contextLoader != null) {
  41. this.contextLoader.closeWebApplicationContext(event.getServletContext());
  42. }
  43. ContextCleanupListener.cleanupAttributes(event.getServletContext());
  44. }
  45. }

我们先重点关注容器的启动,也就是contextInitialized方法,从代码中可以看到它是调用的ContextLoader的initWebApplicationContext方法。我们来看下这个方法的代码:

代码1.2:ContextLoader的initWebApplicationContext方法

  1. public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
  2. //判断ServletContext中是否已经有根上下文存在,存在抛出异常
  3. if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
  4. throw new IllegalStateException(
  5. "Cannot initialize context because there is already a root application context present - " +
  6. "check whether you have multiple ContextLoader* definitions in your web.xml!");
  7. }
  8. Log logger = LogFactory.getLog(ContextLoader.class);
  9. servletContext.log("Initializing Spring root WebApplicationContext");
  10. if (logger.isInfoEnabled()) {
  11. logger.info("Root WebApplicationContext: initialization started");
  12. }
  13. long startTime = System.currentTimeMillis();
  14. try {
  15. //载入双亲上下文(通常是不存在)
  16. ApplicationContext parent = loadParentContext(servletContext);
  17. // 创建WebApplicationContext
  18. this.context = createWebApplicationContext(servletContext, parent);
  19. //把创建的根context保存到Servlet环境中
  20. servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
  21. //取得线程的类加载器
  22. ClassLoader ccl = Thread.currentThread().getContextClassLoader();
  23. if (ccl == ContextLoader.class.getClassLoader()) {
  24. //如果线程和本类拥有相同的类加载器,则使用静态变量保存即可,因为同一类加载器加载同一份静态变量
  25. currentContext = this.context;
  26. }
  27. else if (ccl != null) {
  28. //如果线程和本类拥有不同的类加载器,则使用线程的类加载器作为key在保存在一个映射对象里,保证析构时能拿到Webcontext进行关闭操作
  29. currentContextPerThread.put(ccl, this.context);
  30. }
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
  33. WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
  34. }
  35. if (logger.isInfoEnabled()) {
  36. long elapsedTime = System 版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    原文链接:https://blog.csdn.net/u013185616/article/details/52186184
    站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢