国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 深入講解spring boot中servlet的啟動過程與原理

深入講解spring boot中servlet的啟動過程與原理

2021-05-12 15:29期待華麗轉身 Java教程

這篇文章主要給大家介紹了關于spring boot中servlet啟動過程與原理的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

本文主要介紹了關于spring boot中servlet啟動過程與原理的相關內容,下面話不多說了,來一起看看詳細的介紹吧

啟動過程與原理:

1 spring boot 應用啟動運行run方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
stopwatch stopwatch = new stopwatch();
 stopwatch.start();
 configurableapplicationcontext context = null;
 failureanalyzers analyzers = null;
 configureheadlessproperty();
 springapplicationrunlisteners listeners = getrunlisteners(args);
 listeners.starting();
 try {
  applicationarguments applicationarguments = new defaultapplicationarguments(
   args);
  configurableenvironment environment = prepareenvironment(listeners,
   applicationarguments);
  banner printedbanner = printbanner(environment);
   //創建一個applicationcontext容器
  context = createapplicationcontext();
  analyzers = new failureanalyzers(context);
  preparecontext(context, environment, listeners, applicationarguments,
   printedbanner);
   //刷新ioc容器
  refreshcontext(context);
  afterrefresh(context, applicationarguments);
  listeners.finished(context, null);
  stopwatch.stop();
  if (this.logstartupinfo) {
  new startupinfologger(this.mainapplicationclass)
   .logstarted(getapplicationlog(), stopwatch);
  }
  return context;
 }
 catch (throwable ex) {
  handlerunfailure(context, listeners, analyzers, ex);
  throw new illegalstateexception(ex);
 }

2  createapplicationcontext():創建ioc容器,如果是web應用則創建annotationconfigembeddedwebapplacation的ioc容器,如果不是,則創建annotationconfigapplication的ioc容器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static final string default_context_class = "org.springframework.context."
  + "annotation.annotationconfigapplicationcontext";
 
 /**
 * the class name of application context that will be used by default for web
 * environments.
 */
 public static final string default_web_context_class = "org.springframework."
  + "boot.context.embedded.annotationconfigembeddedwebapplicationcontext";
 
 
protected configurableapplicationcontext createapplicationcontext() {
 class<?> contextclass = this.applicationcontextclass;
 if (contextclass == null) {
  try {
          //根據應用環境,創建不同的ioc容器
  contextclass = class.forname(this.webenvironment
   ? default_web_context_class : default_context_class);
  }
  catch (classnotfoundexception ex) {
  throw new illegalstateexception(
   "unable create a default applicationcontext, "
    + "please specify an applicationcontextclass",
   ex);
  }
 }
 return (configurableapplicationcontext) beanutils.instantiate(contextclass);
 }

3    refreshcontext(context) spring boot刷新ioc容器(創建容器對象,并初始化容器,創建容器每一個組件)

?
1
2
3
4
5
6
7
8
9
10
11
private void refreshcontext(configurableapplicationcontext context) {
 refresh(context);
 if (this.registershutdownhook) {
  try {
  context.registershutdownhook();
  }
  catch (accesscontrolexception ex) {
  // not allowed in some environments.
  }
 }
 }

4 refresh(context);刷新剛才創建的ioc容器

?
1
2
3
4
protected void refresh(applicationcontext applicationcontext) {
 assert.isinstanceof(abstractapplicationcontext.class, applicationcontext);
 ((abstractapplicationcontext) applicationcontext).refresh();
 }

5 調用父類的refresh()的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void refresh() throws beansexception, illegalstateexception {
 object var1 = this.startupshutdownmonitor;
 synchronized(this.startupshutdownmonitor) {
  this.preparerefresh();
  configurablelistablebeanfactory beanfactory = this.obtainfreshbeanfactory();
  this.preparebeanfactory(beanfactory);
 
  try {
  this.postprocessbeanfactory(beanfactory);
  this.invokebeanfactorypostprocessors(beanfactory);
  this.registerbeanpostprocessors(beanfactory);
  this.initmessagesource();
  this.initapplicationeventmulticaster();
  this.onrefresh();
  this.registerlisteners();
  this.finishbeanfactoryinitialization(beanfactory);
  this.finishrefresh();
  } catch (beansexception var9) {
  if (this.logger.iswarnenabled()) {
   this.logger.warn("exception encountered during context initialization - cancelling refresh attempt: " + var9);
  }
 
  this.destroybeans();
  this.cancelrefresh(var9);
  throw var9;
  } finally {
  this.resetcommoncaches();
  }
 
 }
 }

6  抽象父類abstractapplicationcontext類的子類embeddedwebapplicationcontext的onrefresh方法

?
1
2
3
4
5
6
7
8
9
10
11
@override
 protected void onrefresh() {
 super.onrefresh();
 try {
  createembeddedservletcontainer();
 }
 catch (throwable ex) {
  throw new applicationcontextexception("unable to start embedded container",
   ex);
 }
 }

7  在createembeddedservletcontainer放啊發中會獲取嵌入式servlet容器工廠,由容器工廠創建servlet

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void createembeddedservletcontainer() {
 embeddedservletcontainer localcontainer = this.embeddedservletcontainer;
 servletcontext localservletcontext = getservletcontext();
 if (localcontainer == null && localservletcontext == null) {
                //獲取嵌入式servlet容器工廠
  embeddedservletcontainerfactory containerfactory = getembeddedservletcontainerfactory();
          //根據容器工廠獲取對應嵌入式servlet容器
  this.embeddedservletcontainer = containerfactory
   .getembeddedservletcontainer(getselfinitializer());
 }
 else if (localservletcontext != null) {
  try {
  getselfinitializer().onstartup(localservletcontext);
  }
  catch (servletexception ex) {
  throw new applicationcontextexception("cannot initialize servlet context",
   ex);
  }
 }
 initpropertysources();
 }

8  從ioc容器中獲取servlet容器工廠

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//embeddedwebapplicationcontext#getembeddedservletcontainerfactory
protected embeddedservletcontainerfactory getembeddedservletcontainerfactory() {
 // use bean names so that we don't consider the hierarchy
 string[] beannames = getbeanfactory()
 .getbeannamesfortype(embeddedservletcontainerfactory.class);
 if (beannames.length == 0) {
 throw new applicationcontextexception(
  "unable to start embeddedwebapplicationcontext due to missing "
  + "embeddedservletcontainerfactory bean.");
 }
 if (beannames.length > 1) {
 throw new applicationcontextexception(
  "unable to start embeddedwebapplicationcontext due to multiple "
  + "embeddedservletcontainerfactory beans : "
  + stringutils.arraytocommadelimitedstring(beannames));
 }
 return getbeanfactory().getbean(beannames[0],
     embeddedservletcontainerfactory.class);
}

9  使用servlet容器工廠獲取嵌入式servlet容器,具體使用哪一個容器工廠看配置環境依賴

?
1
2
this.embeddedservletcontainer = containerfactory
  .getembeddedservletcontainer(getselfinitializer());

10  上述創建過程  首先啟動ioc容器,接著啟動嵌入式servlet容器,接著將ioc容器中剩下沒有創建的對象獲取出來,比如自己創建的controller

?
1
2
// instantiate all remaining (non-lazy-init) singletons.
  finishbeanfactoryinitialization(beanfactory);
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
protected void finishbeanfactoryinitialization(configurablelistablebeanfactory beanfactory) {
 // initialize conversion service for this context.
 if (beanfactory.containsbean(conversion_service_bean_name) &&
  beanfactory.istypematch(conversion_service_bean_name, conversionservice.class)) {
  beanfactory.setconversionservice(
   beanfactory.getbean(conversion_service_bean_name, conversionservice.class));
 }
 
 // register a default embedded value resolver if no bean post-processor
 // (such as a propertyplaceholderconfigurer bean) registered any before:
 // at this point, primarily for resolution in annotation attribute values.
 if (!beanfactory.hasembeddedvalueresolver()) {
  beanfactory.addembeddedvalueresolver(new stringvalueresolver() {
  @override
  public string resolvestringvalue(string strval) {
   return getenvironment().resolveplaceholders(strval);
  }
  });
 }
 
 // initialize loadtimeweaveraware beans early to allow for registering their transformers early.
 string[] weaverawarenames = beanfactory.getbeannamesfortype(loadtimeweaveraware.class, false, false);
 for (string weaverawarename : weaverawarenames) {
  getbean(weaverawarename);
 }
 
 // stop using the temporary classloader for type matching.
 beanfactory.settempclassloader(null);
 
 // allow for caching all bean definition metadata, not expecting further changes.
 beanfactory.freezeconfiguration();
 
 // instantiate all remaining (non-lazy-init) singletons.
 beanfactory.preinstantiatesingletons();
 }

看看 preinstantiatesingletons方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public void preinstantiatesingletons() throws beansexception {
  if (this.logger.isdebugenabled()) {
   this.logger.debug("pre-instantiating singletons in " + this);
  }
 
  list<string> beannames = new arraylist(this.beandefinitionnames);
  iterator var2 = beannames.iterator();
 
  while(true) {
   while(true) {
    string beanname;
    rootbeandefinition bd;
    do {
     do {
      do {
       if (!var2.hasnext()) {
        var2 = beannames.iterator();
 
        while(var2.hasnext()) {
         beanname = (string)var2.next();
         object singletoninstance = this.getsingleton(beanname);
         if (singletoninstance instanceof smartinitializingsingleton) {
          final smartinitializingsingleton smartsingleton = (smartinitializingsingleton)singletoninstance;
          if (system.getsecuritymanager() != null) {
           accesscontroller.doprivileged(new privilegedaction<object>() {
            public object run() {
             smartsingleton.aftersingletonsinstantiated();
             return null;
            }
           }, this.getaccesscontrolcontext());
          } else {
           smartsingleton.aftersingletonsinstantiated();
          }
         }
        }
 
        return;
       }
 
       beanname = (string)var2.next();
       bd = this.getmergedlocalbeandefinition(beanname);
      } while(bd.isabstract());
     } while(!bd.issingleton());
    } while(bd.islazyinit());
 
    if (this.isfactorybean(beanname)) {
     final factorybean<?> factory = (factorybean)this.getbean("&" + beanname);
     boolean iseagerinit;
     if (system.getsecuritymanager() != null && factory instanceof smartfactorybean) {
      iseagerinit = ((boolean)accesscontroller.doprivileged(new privilegedaction<boolean>() {
       public boolean run() {
        return ((smartfactorybean)factory).iseagerinit();
       }
      }, this.getaccesscontrolcontext())).booleanvalue();
     } else {
      iseagerinit = factory instanceof smartfactorybean && ((smartfactorybean)factory).iseagerinit();
     }
 
     if (iseagerinit) {
      this.getbean(beanname);
     }
    } else {
            //注冊bean
     this.getbean(beanname);
    }
   }
  }
 }

是使用getbean方法來通過反射將所有未創建的實例創建出來

  使用嵌入式servlet容器:

     優點:   簡單,便攜

     缺點:   默認不支持jsp,優化定制比較復雜

使用外置servlet容器的步驟:

  1  必須創建war項目,需要劍豪web項目的目錄結構

  2  嵌入式tomcat依賴scope指定provided

  3  編寫springbootservletinitializer類子類,并重寫configure方法

?
1
2
3
4
5
6
7
public class servletinitializer extends springbootservletinitializer {
 
 @override
 protected springapplicationbuilder configure(springapplicationbuilder application) {
  return application.sources(springboot04webjspapplication.class);
 }
}

        4  啟動服務器

jar包和war包啟動區別

    jar包:執行springbootapplication的run方法,啟動ioc容器,然后創建嵌入式servlet容器

 war包:  先是啟動servlet服務器,服務器啟動springboot應用(springbootservletinitizer),然后啟動ioc容器

servlet 3.0+規則

    1  服務器啟動(web應用啟動),會創建當前web應用里面所有jar包里面的servletcontainerlnitializer實例

     2 servletcontainerinitializer的實現放在jar包的meta-inf/services文件夾下

   3  還可以使用@handlestypes注解,在應用啟動的時候加載指定的類。

外部tomcat流程以及原理

  ①  啟動tomcat

  ②  根據上述描述的servlet3.0+規則,可以在spring的web模塊里面找到有個文件名為javax.servlet.servletcontainerinitializer的文件,而文件的內容為org.springframework.web.springservletcontainerinitializer,用于加載springservletcontainerinitializer類

  ③看看springservletcontainerinitializer定義

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@handlestypes(webapplicationinitializer.class)
public class springservletcontainerinitializer implements servletcontainerinitializer {
 
 /**
  * delegate the {@code servletcontext} to any {@link webapplicationinitializer}
  * implementations present on the application classpath.
  * <p>because this class declares @{@code handlestypes(webapplicationinitializer.class)},
  * servlet 3.0+ containers will automatically scan the classpath for implementations
  * of spring's {@code webapplicationinitializer} interface and provide the set of all
  * such types to the {@code webappinitializerclasses} parameter of this method.
  * <p>if no {@code webapplicationinitializer} implementations are found on the classpath,
  * this method is effectively a no-op. an info-level log message will be issued notifying
  * the user that the {@code servletcontainerinitializer} has indeed been invoked but that
  * no {@code webapplicationinitializer} implementations were found.
  * <p>assuming that one or more {@code webapplicationinitializer} types are detected,
  * they will be instantiated (and <em>sorted</em> if the @{@link
  * org.springframework.core.annotation.order @order} annotation is present or
  * the {@link org.springframework.core.ordered ordered} interface has been
  * implemented). then the {@link webapplicationinitializer#onstartup(servletcontext)}
  * method will be invoked on each instance, delegating the {@code servletcontext} such
  * that each instance may register and configure servlets such as spring's
  * {@code dispatcherservlet}, listeners such as spring's {@code contextloaderlistener},
  * or any other servlet api componentry such as filters.
  * @param webappinitializerclasses all implementations of
  * {@link webapplicationinitializer} found on the application classpath
  * @param servletcontext the servlet context to be initialized
  * @see webapplicationinitializer#onstartup(servletcontext)
  * @see annotationawareordercomparator
  */
 @override
 public void onstartup(set<class<?>> webappinitializerclasses, servletcontext servletcontext)
   throws servletexception {
 
  list<webapplicationinitializer> initializers = new linkedlist<webapplicationinitializer>();
 
  if (webappinitializerclasses != null) {
   for (class<?> waiclass : webappinitializerclasses) {
    // be defensive: some servlet containers provide us with invalid classes,
    // no matter what @handlestypes says...
    if (!waiclass.isinterface() && !modifier.isabstract(waiclass.getmodifiers()) &&
      webapplicationinitializer.class.isassignablefrom(waiclass)) {
     try {
                //為所有的webapplicationinitializer類型創建實例,并加入集合中
      initializers.add((webapplicationinitializer) waiclass.newinstance());
     }
     catch (throwable ex) {
      throw new servletexception("failed to instantiate webapplicationinitializer class", ex);
     }
    }
   }
  }
 
  if (initializers.isempty()) {
   servletcontext.log("no spring webapplicationinitializer types detected on classpath");
   return;
  }
 
  servletcontext.log(initializers.size() + " spring webapplicationinitializers detected on classpath");
  annotationawareordercomparator.sort(initializers);
      //調用每一個webapplicationinitializer實例的onstartup方法
  for (webapplicationinitializer initializer : initializers) {
   initializer.onstartup(servletcontext);
  }
 }
}

 在上面一段長長的注釋中可以看到,springservletcontainerinitializer將@handlestypes(webapplicationinitializer.class)標注的所有webapplicationinitializer這個類型的類都傳入到onstartup方法的set參數中,并通過反射為這些webapplicationinitializer類型的類創建實例;

  ④  方法最后,每一個webapplicationinitilizer實現調用自己onstartup方法

  ⑤  而webapplicationinitializer有個抽象實現類springbootservletinitializer(記住我們繼承了該抽象類),則會調用每一個webapplicationinitializer實例(包括springbootservletinitializer)的onstartup方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public abstract class springbootservletinitializer implements webapplicationinitializer {
 
  //other code...
   
  @override
  public void onstartup(servletcontext servletcontext) throws servletexception {
    // logger initialization is deferred in case a ordered
    // logservletcontextinitializer is being used
    this.logger = logfactory.getlog(getclass());
    //創建ioc容器
    webapplicationcontext rootappcontext = createrootapplicationcontext(
        servletcontext);
    if (rootappcontext != null) {
      servletcontext.addlistener(new contextloaderlistener(rootappcontext) {
        @override
        public void contextinitialized(servletcontextevent event) {
          // no-op because the application context is already initialized
        }
      });
    }
    else {
      this.logger.debug("no contextloaderlistener registered, as "
          + "createrootapplicationcontext() did not "
          + "return an application context");
    }
  }
 
  protected webapplicationcontext createrootapplicationcontext(
      servletcontext servletcontext) {
    //創建spring應用構建器,并進行相關屬性設置
    springapplicationbuilder builder = createspringapplicationbuilder();
    standardservletenvironment environment = new standardservletenvironment();
    environment.initpropertysources(servletcontext, null);
    builder.environment(environment);
    builder.main(getclass());
    applicationcontext parent = getexistingrootwebapplicationcontext(servletcontext);
    if (parent != null) {
      this.logger.info("root context already created (using as parent).");
      servletcontext.setattribute(
          webapplicationcontext.root_web_application_context_attribute, null);
      builder.initializers(new parentcontextapplicationcontextinitializer(parent));
    }
    builder.initializers(
        new servletcontextapplicationcontextinitializer(servletcontext));
    builder.contextclass(annotationconfigembeddedwebapplicationcontext.class);
     
    //調用configure方法,創建war類型的web項目后,由于編寫springbootservletinitializer的子類重寫configure方法,所以此處調用的是我們定義的子類重寫的configure方法
    builder = configure(builder);
     
    //通過構建器構建了一個spring應用
    springapplication application = builder.build();
    if (application.getsources().isempty() && annotationutils
        .findannotation(getclass(), configuration.class) != null) {
      application.getsources().add(getclass());
    }
    assert.state(!application.getsources().isempty(),
        "no springapplication sources have been defined. either override the "
            + "configure method or add an @configuration annotation");
    // ensure error pages are registered
    if (this.registererrorpagefilter) {
      application.getsources().add(errorpagefilterconfiguration.class);
    }
    //啟動spring應用
    return run(application);
  }
   
  //spring應用啟動,創建并返回ioc容器
  protected webapplicationcontext run(springapplication application) {
    return (webapplicationcontext) application.run();
  }  
}

springbootservletinitializer實例執行onstartup方法的時候會通過createrootapplicationcontext方法來執行run方法,接下來的過程就同以jar包形式啟動的應用的run過程一樣了,在內部會創建ioc容器并返回,只是以war包形式的應用在創建ioc容器過程中,不再創建servlet容器了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.cnblogs.com/developerxiaofeng/p/9081689.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 成人免费网站在线观看 | 日韩国产在线看 | 午夜成人免费影院 | 欧美自拍视频 | 中文字幕 国产精品 | 天天干天天操 | 午夜视频在线观看网站 | 日韩理论在线 | 亚洲成人精品一区 | 国产日韩欧美三级 | 嫩草视频在线 | 自拍偷拍欧美 | 日本视频一区二区三区 | 久久小视频 | 国产欧美久久久久久 | 天堂av一区 | 成人h动漫在线看 | 色婷婷综合久久久中文字幕 | 国产香蕉视频 | 国产艹 | 国产日韩一区二区三区 | 国产精品久久久久久久久久新婚 | 欧美一区不卡 | 日本a v在线播放 | 欧美中文在线 | 免费欧美一级 | 九九免费精品视频 | 亚洲在线一区 | 久久99精品久久久久久园产越南 | 国产中文字幕在线免费观看 | 一级a毛片| 亚洲精品乱码久久久久久久 | 欧美大片免费 | 国产精品久久久 | 久久久久亚洲 | 国产性猛交xxxx免费看久久 | 午夜黄色影院 | 91福利视频免费 | 成人午夜视频在线播放 | 精品乱码一区二区三四区 | 一级色视频 |