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 到容器,来替代默认的配置就可以扩展了

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