• spring自动装配servlet


    疑问:传统servlet项目是如何集成到springboot项目中的?为何无需再配置web.xml

    原理:servlet3.0配置api+spring抽象实现AbstractAnnotationConfigDispatcherServletInitializer

    servlet3.0配置api: 基于ServletContainerInitializer接口实现与@HandlesTypes过滤出

    WebApplicationInitializer具体实现类集合,而AbstractAnnotationConfigDispatcherServletInitializer的默认实现,就配置了DisPachservlet(AbstractAnnotationConfigDispatcherServletInitializer父类中实现了),从而可以自动装备
    1. //
    2. // Source code recreated from a .class file by IntelliJ IDEA
    3. // (powered by FernFlower decompiler)
    4. //
    5. package org.springframework.web;
    6. import java.lang.reflect.Modifier;
    7. import java.util.ArrayList;
    8. import java.util.Collections;
    9. import java.util.Iterator;
    10. import java.util.List;
    11. import java.util.Set;
    12. import javax.servlet.ServletContainerInitializer;
    13. import javax.servlet.ServletContext;
    14. import javax.servlet.ServletException;
    15. import javax.servlet.annotation.HandlesTypes;
    16. import org.springframework.core.annotation.AnnotationAwareOrderComparator;
    17. import org.springframework.lang.Nullable;
    18. import org.springframework.util.ReflectionUtils;
    19. @HandlesTypes({WebApplicationInitializer.class})
    20. public class SpringServletContainerInitializer implements ServletContainerInitializer {
    21. public SpringServletContainerInitializer() {
    22. }
    23. public void onStartup(@Nullable Set> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
    24. List initializers = Collections.emptyList();
    25. Iterator var4;
    26. if (webAppInitializerClasses != null) {
    27. initializers = new ArrayList(webAppInitializerClasses.size());
    28. var4 = webAppInitializerClasses.iterator();
    29. while(var4.hasNext()) {
    30. Class waiClass = (Class)var4.next();
    31. if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
    32. try {
    33. ((List)initializers).add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass, new Class[0]).newInstance());
    34. } catch (Throwable var7) {
    35. throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
    36. }
    37. }
    38. }
    39. }
    40. if (((List)initializers).isEmpty()) {
    41. servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
    42. } else {
    43. servletContext.log(((List)initializers).size() + " Spring WebApplicationInitializers detected on classpath");
    44. AnnotationAwareOrderComparator.sort((List)initializers);
    45. var4 = ((List)initializers).iterator();
    46. while(var4.hasNext()) {
    47. WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
    48. initializer.onStartup(servletContext);
    49. }
    50. }
    51. }
    52. }

    spring抽象实现AbstractAnnotationConfigDispatcherServletInitializer:WebApplicationInitializer具体抽象,可装备dispachServlet

    1. //
    2. // Source code recreated from a .class file by IntelliJ IDEA
    3. // (powered by FernFlower decompiler)
    4. //
    5. package org.springframework.web.servlet.support;
    6. import org.springframework.lang.Nullable;
    7. import org.springframework.util.ObjectUtils;
    8. import org.springframework.web.context.WebApplicationContext;
    9. import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    10. public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer {
    11. public AbstractAnnotationConfigDispatcherServletInitializer() {
    12. }
    13. @Nullable
    14. protected WebApplicationContext createRootApplicationContext() {
    15. Class[] configClasses = this.getRootConfigClasses();
    16. if (!ObjectUtils.isEmpty(configClasses)) {
    17. AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    18. context.register(configClasses);
    19. return context;
    20. } else {
    21. return null;
    22. }
    23. }
    24. protected WebApplicationContext createServletApplicationContext() {
    25. AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    26. Class[] configClasses = this.getServletConfigClasses();
    27. if (!ObjectUtils.isEmpty(configClasses)) {
    28. context.register(configClasses);
    29. }
    30. return context;
    31. }
    32. @Nullable
    33. protected abstract Class[] getRootConfigClasses();
    34. @Nullable
    35. protected abstract Class[] getServletConfigClasses();
    36. }

     

    springboot如何推断是web应用:

    SpringApplication 在run方法之前推断,只能检查当前classLoader存在class存在,来判断是否为web应用。

    判断标准:是否有Servlet和ConfigurableWebApplicationContext,有则为web servlet项目即传统springmvc

    javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"
    1. //
    2. // Source code recreated from a .class file by IntelliJ IDEA
    3. // (powered by FernFlower decompiler)
    4. //
    5. package org.springframework.boot;
    6. import org.springframework.util.ClassUtils;
    7. public enum WebApplicationType {
    8. NONE,
    9. SERVLET,
    10. REACTIVE;
    11. private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
    12. private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
    13. private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
    14. private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
    15. private WebApplicationType() {
    16. }
    17. static WebApplicationType deduceFromClasspath() {
    18. if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
    19. return REACTIVE;
    20. } else {
    21. String[] var0 = SERVLET_INDICATOR_CLASSES;
    22. int var1 = var0.length;
    23. for(int var2 = 0; var2 < var1; ++var2) {
    24. String className = var0[var2];
    25. if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
    26. return NONE;
    27. }
    28. }
    29. return SERVLET;
    30. }
    31. }
    32. }

    遗留问题: 

    AnnotationConfigWebApplicationContext即可扫描springmvc相关的注解,从而达到自动装备

     

    文章:摘录部分《小马哥 springBoot编程思想》

  • 相关阅读:
    SQL注入 Less26(过滤空格和注释符,使用不带空格的报错注入)
    记一次性能飙升的Mysql CRUD数据表迁移到Clickhouse表的过程
    创建第一个FreeRTOS工程
    Go语言 结构体
    P2922 [USACO08DEC] Secret Message G - 字典树
    Nginx Rewrite
    某攻防演练心得之随笔记
    【WLAN】Android 13 WIFI 选网机制--NetworkNominator 解读
    volatile 无法保证原子性 案例展示
    底部terminal消失
  • 原文地址:https://blog.csdn.net/yingcly003/article/details/127598718