• 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编程思想》

  • 相关阅读:
    @AutoConfigurationPackage注解类
    【PAT(甲级)】1053 Path of Equal Weight
    基于SSM的零食商城管理系统
    集合框架总结-set
    2022-6-30 随机过程之条件期望及其性质 (二)
    全堆栈图像生成器专为Multiverse后端Bootcamp设计,结合了React、Firebase和Hugging Face API
    Openssl数据安全传输平台015:OCCI的使用方法+在项目中的设计与实现
    Redisson-Lock-加锁原理
    Linux sudo -i取消密码的方法
    程序员职场生活记录分享——打工人沪漂五年,不想工作了
  • 原文地址:https://blog.csdn.net/yingcly003/article/details/127598718