原始ssm方式,web.xml中的配置

  1. <!--加载springioc容器,创建Bean-->
  2. <listener>
  3. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  4. </listener>
  5. <!-- 配置SpringMVC核心过滤器,拦截所有的http请求 -->
  6. <servlet>
  7. <servlet-name>springmvc</servlet-name>
  8. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  9. <init-param>
  10. <param-name>contextConfigLocation</param-name>
  11. <param-value>classpath:springmvc.xml</param-value>
  12. </init-param>
  13. </servlet>

为什么spring-boot的jar可以直接运行?

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. </plugin>
  7. </plugins>
  8. </build>

做了两件事:

  • 1)编写manifest.mf

1656599905(1).jpg

  • 2)打的jar包内再打入jar,fat jar,依赖的jar包也打包进jar内

  • Java没有提供任何标准的方式来加载嵌套的jar文件(即,它们本身包含在jar中的jar文件),就是没办法加载依赖

还需要manifest.mf文件内配置的Main-Class来加载jar包内的jar文件以及class文件,自定义了类加载器去加载

启程的时候先找到Main-Class,进行依赖的jar进行加载,加载完成之后,再找到Start-Class利用反射调用本应用程序的main方法

总结:

  • 通过spring-boot-plugin 生成MANIFEST.MF文件,文件内有个重要的属性main-class,指定运行java -jar的主程序,把依赖的jar文件打包在fat jar,运行java -jar,就会运行JarLauncher。
  • JarLauncher通过加载BOOT-INF/classes目录及BOOT-INF/lib目录下jar文件,实现了fat jar的启动。
  • SpringBoot通过扩展JarFile、JarURLConnection及URLStreamHandler,实现了jar in jar中资源的加载。
  • SpringBoot通过扩展URLClassLoader–LauncherURLClassLoader,实现了jar in jar中class文件的加载。

spring boot启动spring容器

refresh方法内把配置类解析为Bean定义
springboot启动的时候会生成一个spring上下文ApplicationContext,还会读取全局配置文件等

  1. public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
  2. //创建SpringApplication的时候,会把启动类给存储起来
  3. return new SpringApplication(primarySources).run(args);
  4. }
  5. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  6. this.resourceLoader = resourceLoader;
  7. Assert.notNull(primarySources, "PrimarySources must not be null");
  8. //将启动类存储在primarySources
  9. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  10. //推算web环境 算法与ConditionOnClass差不多
  11. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  12. this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
  13. //对外扩展
  14. setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  15. //监听器
  16. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  17. this.mainApplicationClass = deduceMainApplicationClass();
  18. }

refresh之前读取配置类

总结:
1. 获取启动类:根据启动类加载ioc容器
2.获取web应用类型
3.spring.factories读取了对外扩展的ApplicationContextInitializer ,ApplicationListener 对外扩展, 对类解耦(比如全局配置文件、热部署插件)
4. 根据main推算出所在的类

run启动

  1. public ConfigurableApplicationContext run(String... args) {
  2. StopWatch stopWatch = new StopWatch();
  3. stopWatch.start();//控制台打印的时间
  4. DefaultBootstrapContext bootstrapContext = createBootstrapContext();
  5. ConfigurableApplicationContext context = null;
  6. configureHeadlessProperty();
  7. //读取一个listener,发布一个事件
  8. //事件多播器,监听者模式
  9. SpringApplicationRunListeners listeners = getRunListeners(args);
  10. listeners.starting(bootstrapContext, this.mainApplicationClass);
  11. try {
  12. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
  13. //读取所有的配置文件,通过监听器的方式读取的
  14. ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
  15. configureIgnoreBeanInfo(environment);
  16. Banner printedBanner = printBanner(environment);
  17. //创建spring的上下文,会启动内嵌的tomcat
  18. context = createApplicationContext();
  19. context.setApplicationStartup(this.applicationStartup);
  20. prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
  21. refreshContext(context);
  22. afterRefresh(context, applicationArguments);
  23. stopWatch.stop();
  24. if (this.logStartupInfo) {
  25. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
  26. }
  27. listeners.started(context);
  28. callRunners(context, applicationArguments);
  29. }
  30. catch (Throwable ex) {
  31. handleRunFailure(context, ex, listeners);
  32. throw new IllegalStateException(ex);
  33. }
  34. try {
  35. listeners.running(context);
  36. }
  37. catch (Throwable ex) {
  38. handleRunFailure(context, ex, null);
  39. throw new IllegalStateException(ex);
  40. }
  41. return context;
  42. }