SpringBoot自动装配原理

淩亂°似流年 2024-03-22 14:48 179阅读 0赞

1、什么是自动装配

自动装配就是把别人(官方)写好的config配置类加载到spring容器,然后根据这个配置类生成一些项目需要的bean对象。 (小声逼逼:就像我们自己在项目了写的config配置类一样的,只不过这个是别人写好的,你什么都不用管)

2、自动装配的开关在哪里

  1. @SpringBootApplication
  2. |--@EnableAutoConfiguration
  3. |--@Import({
  4. AutoConfigurationImportSelector.class})

@SpringBootApplication注解里的@EnableAutoConfiguration@Import注解导入了一AutoConfigurationImportSelector.class类,这个类的selectImports方法会扫描我们类路径下的一个spring.factories文件(里面装的是很多官方写好的自动配置类的全限定名),然后返回这些类的名字。

  • selectImports方法如下:

    public String[] selectImports(AnnotationMetadata annotationMetadata) {

    1. if (!this.isEnabled(annotationMetadata)) {
    2. return NO_IMPORTS;
    3. } else {
    4. AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
    5. return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    6. }
    7. }

复制

  • spring.factories文件的位置如下:

21f3d54bad65eaab0567fc984a3671cc.png

  • spring.factories文件的内容如下:

b8a53c560ff150f72490301d6026d748.png

3、自动装配开始(以tomcat为例)

前面的selectImports函数会拿到spring.factories文件里的自动配置类,然后去解析这些配置类,这里以ServletWebServerFactoryAutoConfiguration为例

b501692dc3aeee99c791e04f3bad6c7d.png

58dd4a798f16e715747534cf35918847.png

这个类上面有很多条件注解,大致就是说当你的应用是web应用,符合spring MVC那一套,像什么Servlet啊等等,这个配置类才生效。其中这个配置类又用@Import注解导入了几个类如下:

  1. @Import({
  2. ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
  3. EmbeddedTomcat.class,
  4. EmbeddedJetty.class,
  5. EmbeddedUndertow.class})

复制

这几个看名字就知道是什么,就是一些web容器嘛,Tomcat、Jetty、Undertow。其实EmbeddedTomcat.classEmbeddedJetty.classEmbeddedUndertow.classServletWebServerFactoryConfiguration里的三个静态内部类。 这里以EmbeddedTomcat.class这个内部类为例,代码如下:

  1. @ConditionalOnClass({
  2. Servlet.class, Tomcat.class, UpgradeProtocol.class})
  3. @ConditionalOnMissingBean(
  4. value = {
  5. ServletWebServerFactory.class},
  6. search = SearchStrategy.CURRENT
  7. )
  8. static class EmbeddedTomcat {
  9. EmbeddedTomcat() {
  10. }
  11. @Bean
  12. TomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers, ObjectProvider<TomcatContextCustomizer> contextCustomizers, ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
  13. TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
  14. factory.getTomcatConnectorCustomizers().addAll((Collection)connectorCustomizers.orderedStream().collect(Collectors.toList()));
  15. factory.getTomcatContextCustomizers().addAll((Collection)contextCustomizers.orderedStream().collect(Collectors.toList()));
  16. factory.getTomcatProtocolHandlerCustomizers().addAll((Collection)protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
  17. return factory;
  18. }
  19. }

复制

注意:第一行的@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class}),这个条件注解表示你的类路径下有tomcat的依赖,即导入了Tomcat的jar包才会生效,EmbeddedTomcat.classEmbeddedJetty.class也同理,但是只能有一个哈,导入了tomcat的jar包就不能导入其它的,不然会报错,当然了springboot默认tomcat,不需要我们导入。 这里会返回一个TomcatServletWebServerFactory类,点进去后,其代码如下:

  1. public class TomcatServletWebServerFactory
  2. extends AbstractServletWebServerFactory
  3. implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
  4. 其它代码不重要,哈哈。。。

复制

这里继承了一个AbstractServletWebServerFactory类, --------------AbstractServletWebServerFactory类又继承了--------------AbstractConfigurableWebServerFactory, 好,点击AbstractConfigurableWebServerFactory进去就可以看到我们熟悉的8080端口号了,如下:

e2c9a6c50fb1520cc9c0c97868bfd963.png

3、结束语

其实springboot的自动装配还是比较复杂的,大概可以概括为:在启动类的run方法传入启动类的class(方便后面获取其注解信息)。 执行run方法,创建SpringApplication对象,并用LoadSpringFactories()方法将/META-INF/spring.factories文件里的k-v读入缓存(方便后面加载时使用)。 然后继续run方法,在某处会获取传入的启动类的class,并解析上面的注解,当解析到@Import({AutoConfigurationImportSelector.class})时会将AutoConfigurationImportSelector加载进方法区,通过反射创建对象,调用其某一个方法,从缓存读取前面存储的k-v,并经过一系列的过滤、去重等,最后将需要的配置类加载,生成BD对象,创建Bean对象,放入spring容器。

发表评论

表情:
评论列表 (有 0 条评论,179人围观)

还没有评论,来说两句吧...

相关阅读