zoukankan      html  css  js  c++  java
  • Java SPI、servlet3.0与@HandlesTypes源码分析

    关于Java SPI与servlet3.0的应用,这里说的很精炼,链接地址如下。

    https://blog.csdn.net/pingnanlee/article/details/80940993

    以Tomcat8.5.31对Servlet的实现为例,简单提一点,Tomcat获取ServletContainerInitializer的实现类是在org.apache.catalina.startup.ContextConfig.webConfig() 中,Step 3调用processServletContainerInitializers(),

    使用了自己的WebappServiceLoader,解释为A variation of Java's JAR ServiceLoader。

    顺带一提tomcat启动时webConfig() 的调用链:

    Tomcat.start()->各种代理的start()->org.apache.catalina.core.StandardContext.startInternal->LifecycleBase.fireLifecycleEvent->org.apache.catalina.startup.ContextConfig.lifecycleEvent->configureStart->webConfig 

    另:感叹一下tomcat的源码中,每一个方法都好长,和spring源码的深层次相比简直各有千秋,以及那个叫做ok的boolean 变量,可能相比用异常来表示更为直观吧。

     

    @HandlesTypes的实现原理:

    首先这个注解最开始令我非常困惑,他的作用是将注解指定的Class对象作为参数传递到onStartup(ServletContainerInitializer)方法中。

    然而这个注解是要留给用户扩展的,他指定的Class对象并没有要继承ServletContainerInitializer,更没有写入META-INF/services/的文件(也不可能写入)中,那么Tomcat是怎么扫描到指定的类的呢。

    答案是Byte Code Engineering Library (BCEL),这是Apache Software Foundation 的Jakarta 项目的一部分,作用同ASM类似,是字节码操纵框架。

    webConfig() 在调用processServletContainerInitializers()时记录下注解的类名,然后在Step 4和Step 5中都来到processAnnotationsStream这个方法,使用BCEL的ClassParser在字节码层面读取了/WEB-INF/classes和某些jar(应该可以在叫做fragments的概念中指定)中class文件的超类名和实现的接口名,判断是否与记录的注解类名相同,若相同再通过org.apache.catalina.util.Introspection类load为Class对象,最后保存起来,于Step 11中交给org.apache.catalina.core.StandardContext,也就是tomcat实际调用

    ServletContainerInitializer.onStartup()的地方。

     

    至此,谜团终于解开。

     

    不过还有一个小疑问,StandardContext存放@HandlesTypes的对象叫做Map<ServletContainerInitializer,Set<Class<?>>> initializers,他的addServletContainerInitializer方法除了webConfig()以外,还被TomcatEmbeddedServletContainerFactory.addJasperInitializer和TomcatEmbeddedServletContainerFactory.configureContext调用,不知道运行起来是否有多余的class混入其中。也难怪spring要在SpringServletContainerInitializer.onstart的处理中这样注释的原因了吧:D

      // Be defensive: Some servlet containers provide us with invalid classes,
      // no matter what @HandlesTypes says...

    不知道其他Servlet,比如Jetty引擎,是怎么实现@HandlesTypes这个注解的呢。

     

  • 相关阅读:
    Codeforces Round #372 (Div. 1) B. Complete The Graph (枚举+最短路)
    HDU6430 Problem E. TeaTree【dsu on tree】
    HDU4358 Boring counting【dsu on tree】
    HDU6191 Query on A Tre【dsu on tree + 01字典树】
    2019 ICPC Asia Yinchuan Regional
    广义后缀自动机 例题
    2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)
    BZOJ3238 [Ahoi2013]差异 【SAM or SA】
    HDU4622 Reincarnation【SAM】
    BZOJ1396 识别子串【SAM+SegmentTree】
  • 原文地址:https://www.cnblogs.com/feixuefubing/p/11593411.html
Copyright © 2011-2022 走看看