springboot源码理解三、自动配置(第三方依赖中的bean)

自动配置(第三方依赖中的bean)

  • springboot是如何进行自动配置的
    • @SpringBootApplication
      • @SpringBootConfiguration
      • @EnableAutoConfiguration
        • @AutoConfigurationPackage
        • @Import

springboot会自动将一些类注册进spring IoC容器,
包括有项目根目录下的、第三方依赖中的。

这次我们讲第三方依赖中的。

springboot是如何进行自动配置的

springboot的启动入口是@SpringBootApplication注解标注的类中的main方法。

@SpringBootApplication

@SpringBootApplication是一个组合注解,我们重点关注这三个注解:

@SpringBootConfiguration;
@EnableAutoConfiguration;
@ComponentScan。
springboot源码理解三、自动配置(第三方依赖中的bean)_第1张图片

@SpringBootConfiguration

@Configuration是spring提供的一个注解,标记了该类是一个配置类

配置类中被@Bean修饰的成员会被加载到spring容器中。
springboot源码理解三、自动配置(第三方依赖中的bean)_第2张图片

@EnableAutoConfiguration

启动自动配置功能的核心注解。
springboot源码理解三、自动配置(第三方依赖中的bean)_第3张图片
spring中有很多Enable开头的注解,
作用是借助@Import来收集并注册特定场景下相关的bean,加载到IoC容器。
@EnableAutoConfiguration就是借助@Import,
来收集所有符合自动配置条件的BeanDefinition,加载到IoC容器。

@AutoConfigurationPackage

springboot源码理解三、自动配置(第三方依赖中的bean)_第4张图片
AutoConfigurationPackages.Registrar.class
点进去,

在register(registry, new PackageImport(metadata).getPackageName());
这一行打上断点,
debug运行SpringBootMytestApplication。
springboot源码理解三、自动配置(第三方依赖中的bean)_第5张图片
可以看到new PackageImport(metadata).getPackageName(),
是com.duohoob.springbootmytest,即@AutoConfigurationPackage修饰类所在的包,
是我们应用启动类所在的目录。

register方法,
springboot源码理解三、自动配置(第三方依赖中的bean)_第6张图片
注册了一个bean,这个bean是org.springframework.boot.autoconfigure.AutoConfigurationPackages.BasePackages,
并且有一个参数,应用启动类所在的包名,
供之后使用,比如定义扫描时的扫描范围。

@Import

spring的底层注解,给容器导入一个组件。

@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector可以帮助springboot将所有符合条件的@Configuration配置类
都加载到当前springboot创建并使用的IoC容器,ApplicationContext中。

AutoConfigurationImportSelector的类图,
springboot源码理解三、自动配置(第三方依赖中的bean)_第7张图片
Aware:一个超级接口,表示一个bean可以被spring容器通过回调的方式通知。
说白了就是,使bean具备了获取容器资源的能力。

实现了Aware接口就会执行相应的回调,并且在回调中拿到spring的一些底层组件。
比如实现了BeanFactoryAware的bean,
setBeanFactory会在bean初始化之前被spring容器调用,并拿到BeanFactory这个组件对象。
springboot源码理解三、自动配置(第三方依赖中的bean)_第8张图片
AutoConfigurationImportSelector在被回调时会拿到相应的组件并赋值给自己的属性。
springboot源码理解三、自动配置(第三方依赖中的bean)_第9张图片
ImportSelector:用来导入外部配置类的核心接口。
AutoConfigurationImportSelector实现了DeferredImportSelector,
在springboot启动过程中,会执行org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping的getImports,
这个是实现自动配置逻辑的入口方法,
springboot源码理解三、自动配置(第三方依赖中的bean)_第10张图片
点开this.group.process
因为上图this.group = DeferredImportSelector.Group group;
所以,
在这里插入图片描述
springboot源码理解三、自动配置(第三方依赖中的bean)_第11张图片
加载配置类
springboot源码理解三、自动配置(第三方依赖中的bean)_第12张图片
获取spring.factories,
springboot源码理解三、自动配置(第三方依赖中的bean)_第13张图片
我们先在getCandidateConfigurations打一个断点,
在这里插入图片描述
然后F7进loadFactoryNames,
springboot源码理解三、自动配置(第三方依赖中的bean)_第14张图片
然后看到factoryTypeName是org.springframework.boot.autoconfigure.EnableAutoConfiguration,这个我们接下来会用到的。

SpringFactoriesLoader#loadFactoryNames
在这里插入图片描述
SpringFactoriesLoader#loadSpringFactories
springboot源码理解三、自动配置(第三方依赖中的bean)_第15张图片
我们看这个常量:FACTORIES_RESOURCE_LOCATION,
springboot源码理解三、自动配置(第三方依赖中的bean)_第16张图片
看到有好多个META-INF\spring.factories文件,这些文件都会被加载,
springboot源码理解三、自动配置(第三方依赖中的bean)_第17张图片
我们打开个,
spring-boot-2.2.9.RELEASE\spring-boot-project\spring-boot-autoconfigure\src\main\resources\META-INF\spring.factories
springboot源码理解三、自动配置(第三方依赖中的bean)_第18张图片
这个org.springframework.boot.autoconfigure.EnableAutoConfiguration就是loadFactoryNames中的factoryTypeName,

loadFactoryNames的作用:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\下的这些,
就是是需要加载的配置类,它们中被@Bean修饰的成员将会被加载到springIoC容器中。

回到getAutoConfigurationEntry中,
springboot源码理解三、自动配置(第三方依赖中的bean)_第19张图片
接下来会移除重复、排除(在@SpringBootApplication注解的exclude属性去定义)的配置类
还有过滤掉用不到的配置类

注意这一行:
configurations = filter(configurations, autoConfigurationMetadata);
这个方法会根据配置类上的各种@ConditionalOn开头的注解,
去决定是否加载该配置类中的bean。

例如ElasticsearchAutoConfiguration中的@ConditionalOnClass注解,
@ConditionalOnClass({ Client.class, TransportClientFactoryBean.class })
它的意思就是当前项目的classpath下存在指定的类:Client、TransportClientFactoryBean时,
才会起作用,否则就移除。
springboot源码理解三、自动配置(第三方依赖中的bean)_第20张图片
也就是也就是当前项目引入了对应依赖时才会起作用。

接下来具体的装配工作就交给spring来完成了。

你可能感兴趣的:(SpringBoot,spring,boot,spring,java)