SpringBoot

自动装配原理

从Spring的IOC到SpringBoot的自动装配原理

DeferedImportSelector对Bean加载顺序的影响(当然是由@Import导入的)

 

 DeferedImportSelector有一个分组的概念,如果自定义了一个类,实现了Group接口,可以在这里面自定义排序规则。

 

 

 

 Group有延迟的特性,还有分组的特性。

扫描读取所有jar包当中的spring.factories文件,将文件中得配置读取到缓存中,为Map结构。

在这个过程,会排除和过滤掉不需要的自动配置类。

排除在EnableAutoConfiguration中可以配置要排除的自动配置类。

过滤则主要通过扫描spring.factories文件,找到对应key为:AutoConfigurationImportFilter,把对应配置了该key的配置类给过滤掉。比如:

比如有:@conditionalOnBean、@conditionalOnClass、@conditionalOnProperty 

有时候要求要有相应配置或者项目中有相关类才配加载自动配置。

最后扫描了之后可以在DeferedImportSelector的selectImports()方法中进行排序了。sortAutoConfigurations。

所以也可以自定义一个starter。

启动原理

为什么SpringBoot的jar可以直接运行?

Java没有提供任何标准的方式来加载嵌套的jar文件。(即它们本身包含在jar中的jar文件)

用我自己的话来说,maven通过将多个maven-jar的插件,将依赖的jar文件打包到目标的jar包里面,以及会生成一个MAINFESTMF的文件,然后运行java -jar的时候会运行JarLauncher,之后通过反射,找到MAINFEST.MF文件中的启动类,通过反射调用,执行main方法,启动spring boot程序。

总结:

JarLauncher通过BOOT-INF/classes目录以及BOOT-INF/lib目录下jar文件,实现了fat jar的启动。

SpringBoot通过扩展JarFile、JarURLConnection以及URLStreamHandler,实现了jar in jar中资源的加载。

SpringBoot通过扩展URLClassLoader-LauncherURLClassLoader,实现了jar in jar中class文件的加载。

启动类new 一个spring 上下文对象干了什么事情?

总结:

1. 获取启动类;根据启动类加载IOC容器。

2. 获取web应用类型;

3. spring.factories读取了对外扩展的ApplicationContextInitializer,ApplicationListener(对外扩展,对内解耦,比如全局配置文件、热部署插件)

4. 根据main推算出所在的类。

具体执行run方法流程:

读取配置文件(通过监听者模式)

读取配置类,

解析配置类,加载spring容器,解析@component,@Bean等注册为BeanDefinition,然后创建为一个真正的Bean

 SpringBoot是如何启动内置Tomcat的?

类似如下逻辑:

 

 在selfInstialize(ServletContext servletContext)方法中可以获得DispatcherServlet,但是DispatcherServlet怎么来的呢?

有一个DispatcherServletAutoConfiguration的类,这里面自动注入的。而注册DispatcherServlet为Bean主要用的是ServletRegistryBean。而它又实现了ServletContextInitializer接口。

 

 所以,在selfInstialize(ServletContext servletContext)中可以获得DispatcherServlet.

 

 外置Tomcat是如何启动SpringBoot的?

 由Tomcat通过SPI机制,读取ServletContainerInitializer的实现类:SpringServletContainerInitializer,进入该方法,要求Tomcat找到所有实现了WebApplicationInitializer的类,其中包括Dispatcher的。

 

 在调用对应的onStartUp方法

 

 在里面就注册了DispatcherServlet。而启动应用程序main方法用的就是SpringBootServletInitializer。

使用外置的Tomcat,除了要排除内置Tomcat依赖之外,还需要重写一个SpringBootServletInitializer对应接口的实现类:从而告诉tomcat应用程序的自动类是哪个

 

posted @ 2022-12-02 17:46  君莫笑我十年游  阅读(103)  评论(0编辑  收藏  举报