SpringBoot項目啓動時自動配置原理

本篇說說SpringBoot項目啓動時的原理,是按個人理解,說的不好請諒解

1.創建好項目後有個主類,上面有@SpringBootApplication註解
package com.yizheng.api;

@SpringBootApplication
public class ApiAcceptApplication {}

在idea中按住Ctrl點擊進去,會看到下面兩個關鍵註解(其他註解沒有列出來)

@SpringBootConfiguration  //該類爲配置類
@EnableAutoConfiguration  //啓動自動配置
public @interface SpringBootApplication {}

從 @EnableAutoConfiguration 點進去,又有兩個關鍵的註解,這兩個註解就是SpringBoot項目啓動時自動配置的核心

 //掃描主類架包及以下所有子類到容器
@AutoConfigurationPackage  
//把符合條件的組件自動配置到容器
@Import({AutoConfigurationImportSelector.class}) 
public @interface EnableAutoConfiguration {}
2. 掃描主類架包及以下所有子類到容器 @AutoConfigurationPackage

從@AutoConfigurationPackage點進去,看到@Import導入了一個Registrar.class

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}

點擊 Registrar.class,看到 registerBeanDefinitions方法,猜測是把一些bean導入到容器中

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
        }
    }

在 registerBeanDefinitions方法處打一個端點,可以看到 getPackageName()返回的是 @SpringBootApplication 所在主類的 package 名,然後springboot把該架包和以下子包的所有組件導入到容器,和以前的SpringMVC手動掃描組件一樣,只不過在SpringBoot中變爲自動掃描了,所以我們在該 package下添加的控制器能對外提供服務
在這裏插入圖片描述

3.把符合條件的組件自動配置到容器@Import({AutoConfigurationImportSelector.class})

導入了 AutoConfigurationImportSelector.class,點進去可看到 selectImports()方法,該方法返回String數組,調試下面的代碼,看到系統自動加載了110個自動配置類,最後返回29個類是符合條件的

在這裏插入圖片描述
在這裏插入圖片描述
原理:項目根據元數據加載所有依賴jar組件的 META-INF/spring.factories 文件中的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 屬性的值,下圖右邊區域有很多很多,這些就是SpringBoot封裝好的自動配置類,搜索 WebMvcAutoConfiguration,可以點進去,看到這些代碼是以前SpringMVC時需要手動配置的,現在被SpringBoot自動寫好了

在這裏插入圖片描述

以Redis爲例,如果引用了Redis,那麼也會加載 META-INF/spring.factories 文件中的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 屬性的值,裏面一個 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

看RedisAutoConfiguration的源碼,

  • 1.@Configuration 表示該類是配置類
  • 2.ConditionalOnClass({RedisOperations.class}) 表示該類需要有RedisOperations
  • 3.EnableConfigurationProperties({RedisProperties.class}) 表示啓動自動配置屬性,把application.properties中的屬性值映射到 RedisProperties.class 類的屬性上
  • 4.還會導入一些配置類

```java
@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
  public RedisAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

裏面的代碼表示會往容器中添加一個 bean,條件是容器中沒有 redisTemplate bean存在,如果我們自己配置了 redisTemplate bean,則此bean不會添加到容器,有了此默認的bean後,只要在項目中

@Autowired
RedisTemplate redisTemplate;

就可以使用redis的功能了

以上就是SpringBoot啓動時自動配置的原理,如果我們要使用相關組件,只要添加好對應的依賴,然後在 application.properties中添加相關配置即可,如果不知道怎麼配置,可以點擊到 xxxxAutoConfiguration中查看xxxxProperties類中查看

自行擴展:可以添加自定義配置的 bean 到容器,來替代默認的配置就可以擴展了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章